home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / v / vista / c / menu < prev    next >
Text File  |  1996-02-01  |  18KB  |  757 lines

  1. // **************************************************************************
  2. //                     Copyright 1996 David Allison
  3. //
  4. //             VV    VV    IIIIII     SSSSS     TTTTTT       AA
  5. //             VV    VV      II      SS           TT       AA  AA
  6. //             VV    VV      II        SSSS       TT      AA    AA
  7. //              VV  VV       II           SS      TT      AAAAAAAA
  8. //                VV       IIIIII     SSSS        TT      AA    AA
  9. //
  10. //                    MULTI-THREADED C++ WIMP CLASS LIBRARY
  11. //                                for RISC OS
  12. // **************************************************************************
  13. //
  14. //             P U B L I C    D O M A I N    L I C E N C E
  15. //             -------------------------------------------
  16. //
  17. //     This library is copyright. You may not sell the library for
  18. //     profit, but you may sell products which use it providing
  19. //     those products are presented as executable code and are not
  20. //     libraries themselves.  The library is supplied without any
  21. //     warranty and the copyright owner cannot be held responsible for
  22. //     damage resulting from failure of any part of this library.
  23. //
  24. //          See the User Manual for details of the licence.
  25. //
  26. // *************************************************************************
  27.  
  28. //
  29. // menu.c
  30. //
  31.  
  32. #include "Vista:icon.h"
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <new.h>
  37. #include <ctype.h>
  38. #include <swis.h>
  39. #include <kernel.h>
  40. #include <stdarg.h>
  41.  
  42. #ifndef __EASY_C
  43.  
  44. // an exception here needs to close the file pointer used for the parser.  This
  45. // trick redefines the throw macro to close the file and then call __throw
  46.  
  47. static FILE *menu_fp ;
  48.  
  49. #undef throw
  50. #define throw menu_fp?fclose(menu_fp):0,__throw
  51.  
  52. #endif
  53.  
  54. MenuItem::MenuItem (char *n, Menu *m, char *text, int length)
  55.    {
  56.    name = n ;
  57.    next = NULL ;
  58.    menu = m ;
  59.    submenu = NULL ;
  60.    index = m->add_item(this) ;           // add a new menu item
  61.    MenuItemData *item = &m->data->items[index] ;
  62.    item->item_flags = 0 ;
  63.    item->window_handle = -1 ;
  64.    item->icon_flags = Icon::ITEXT + Icon::IFILLED + Icon::IVCENTRE + 7*Icon::IFORECOL ;
  65.    print (text) ;
  66.    }
  67.  
  68. MenuItem::MenuItem (char *name, Menu *menu, char *sprite, void *sprite_area)
  69.    {
  70.    }
  71.  
  72. void MenuItem::tick()
  73.    {
  74.    menu->data->items[index].item_flags |= TICKED ;
  75.    }
  76.  
  77. void MenuItem::untick()
  78.    {
  79.    menu->data->items[index].item_flags &= ~TICKED ;
  80.    }
  81.  
  82. void MenuItem::fade()
  83.    {
  84.    menu->data->items[index].icon_flags |= Icon::INOSELECT ;
  85.    }
  86.  
  87. void MenuItem::unfade()
  88.    {
  89.    menu->data->items[index].icon_flags &= ~Icon::INOSELECT ;
  90.    }
  91.  
  92. int MenuItem::flags(int f, int m)
  93.    {
  94.    int old = menu->data->items[index].item_flags ;
  95.    menu->data->items[index].item_flags = (old & ~m) | f ;
  96.    return old ;
  97.    }
  98.  
  99. int MenuItem::is_ticked()
  100.    {
  101.    return menu->data->items[index].item_flags & TICKED ;
  102.    }
  103.  
  104. int MenuItem::is_faded()
  105.    {
  106.    return menu->data->items[index].icon_flags & Icon::INOSELECT ;
  107.    }
  108.  
  109. MenuItem::operator int()
  110.    {
  111.    return index ;
  112.    }
  113.  
  114. MenuItem::operator char *()
  115.    {
  116.    return name ;
  117.    }
  118.  
  119. void MenuItem::make_writeable (char *buffer, int length, char *valid)
  120.    {
  121.    MenuItemData *i = &menu->data->items[index] ;
  122.    i->icon_data.indirecttext.buffer = buffer ;
  123.    i->icon_data.indirecttext.bufflen = length ;
  124.    i->icon_data.indirecttext.validstring = valid ;
  125.    i->icon_flags |= Icon::BWRITABLE * Icon::IBTYPE + Icon::INDIRECT +
  126.                     Icon::IHCENTRE + Icon::IVCENTRE + Icon::ITEXT ;
  127.    i->item_flags |= WRITEABLE ;
  128.    }
  129.  
  130. void MenuItem::set_submenu(Menu *submenu)
  131.    {
  132.    this->submenu = submenu ;
  133.    menu->data->items[index].submenu = submenu->data ;
  134.    }
  135.  
  136. void Menu::init (char *n, char *title)
  137.    {
  138.    name = n ;
  139.    next = NULL ;
  140.    num_items = 0 ;
  141.    max_items = 5 ;
  142.    item_adjust = 0 ;
  143.    if ((data = (MenuData*)malloc (sizeof (MenuData) + sizeof (MenuItemData) * max_items)) == NULL)
  144.       throw ("Out of memory") ;
  145.    items = NULL ;
  146.    max_width = 0 ;
  147.    strncpy (data->title, title, 12) ;
  148.    data->title_fore_colour = 7 ;
  149.    data->title_back_colour = 2 ;
  150.    data->work_fore_colour = 7 ;
  151.    data->work_back_colour = 0 ;
  152.    data->item_width = strlen(title) * 16;
  153.    data->item_height = 44 ;
  154.    data->item_gap = 0 ;
  155.    }
  156.  
  157. Menu::Menu (char *name, char *title)
  158.    {
  159.    init (name, title) ;
  160.    }
  161.  
  162. Menu::Menu (char *name, char *title, MenuItem *item)
  163.    {
  164.    init (name, title) ;
  165.    item->set_submenu (this) ;
  166.    }
  167.  
  168. Menu::~Menu()
  169.    {
  170.    }
  171.  
  172. int Menu::add_item (MenuItem *item)
  173.    {
  174.    if (num_items == max_items)         // out of item space?
  175.       {
  176.       max_items += 5 ;
  177.       if ((data = (MenuData*)realloc (data, sizeof (MenuData) + sizeof (MenuItemData) * max_items)) == NULL)
  178.          throw ("Out of memory") ;
  179.       }
  180.    item->next = items ;          // add to list
  181.    items = item ;
  182.    return num_items++ ;
  183.    }
  184.  
  185. void Menu::finish()
  186.    {
  187.    items->flags(MenuItem::LAST) ;        // set last item
  188.    }
  189.  
  190. void Menu::open (int x, int y)
  191.    {
  192.    _kernel_swi_regs r ;
  193.    _kernel_oserror *e ;
  194.    r.r[1] = (int)data ;
  195.    r.r[2] = x ;
  196.    r.r[3] = y ;
  197.    if ((e = _kernel_swi (Wimp_CreateMenu, &r, &r)) != NULL)
  198.       throw (e) ;
  199.    }
  200.  
  201. void Menu::close()
  202.    {
  203.    _kernel_swi_regs r ;
  204.    _kernel_oserror *e ;
  205.    r.r[1] = -1 ;
  206.    if ((e = _kernel_swi (Wimp_CreateMenu, &r, &r)) != NULL)
  207.       throw (e) ;
  208.    }
  209.  
  210. void Menu::iconbar_adjust (int &x, int &y)
  211.    {
  212.    x -= 16 ;
  213.    y = 96 ;
  214.    y += num_items * (data->item_height + data->item_gap) + item_adjust ;
  215.    }
  216.  
  217. MenuItem *Menu::selection (int *hits)
  218.    {
  219.    int i ;
  220.    MenuItem *item ;
  221.    Menu *m = this ;
  222.    for (i = 0 ; ; i++)
  223.       if (hits[i] == -1)
  224.          break ;
  225.    MenuItem *out_items = (MenuItem*)malloc ((i+1) * sizeof (MenuItem)) ;
  226.    if (out_items == NULL)
  227.       throw ("Out of memory") ;
  228.    for (i = 0 ; hits[i] != -1 ; i++)
  229.       for (item = m->items ; item != NULL ; item = item->next)
  230.          if (item->index == hits[i])
  231.             {
  232.             out_items[i] = *item ;
  233.             if (hits[i+1] != -1)
  234.                m = item->submenu ;
  235.             break ;
  236.             }
  237.    out_items[i].name = NULL ;
  238.    out_items[i].index = -1 ;
  239.    return out_items ;
  240.    }
  241.  
  242. bool Menu::invalid_selection (int *hits)
  243.    {
  244.    int i ;
  245.    MenuItem *item ;
  246.    MenuItem *last_item = NULL ;
  247.    Menu *m = this ;
  248.    for (i = 0 ; hits[i] != -1 ; i++)
  249.       for (item = m->items ; item != NULL ; item = item->next)
  250.          if (item->index == hits[i])
  251.             {
  252.             last_item = item ;
  253.             if (hits[i+1] != -1)
  254.                m = item->submenu ;
  255.             break ;
  256.             }
  257. #ifdef __EASY_C
  258.    return last_item != NULL && (last_item->flags() & MenuItem::MENUWARNING) ;
  259. #else
  260.    return (bool)(last_item != NULL && (last_item->flags() & MenuItem::MENUWARNING)) ;
  261. #endif
  262.    }
  263.  
  264. MenuItem *Menu::item (char *iname)
  265.    {
  266.    for (MenuItem *item = items ; item != NULL ; item = item->next)
  267.       if (strcmp (item->name, iname) == 0)
  268.          return item ;
  269.    return NULL ;
  270.    }
  271.  
  272.  
  273. void Menu::print (char *item_name, char *format ...)
  274.    {
  275.    MenuItem *i = item (item_name) ;
  276.    if (i == NULL)
  277.       throw ("No such menu item") ;
  278.    va_list ap ;
  279.    va_start (ap, format) ;
  280.    i->vprint (format, ap) ;
  281.    }
  282.  
  283. void MenuItem::print (char *format...)
  284.    {
  285.    char str[1024] ;
  286.    va_list arg ;
  287.    va_start (arg,format) ;
  288.    vprint (format, arg) ;
  289.    }
  290.  
  291. void MenuItem::vprint (char *format, va_list ap)
  292.    {
  293.    char str[1024] ;
  294.    vsprintf (str,format,ap) ;
  295.    int length = strlen (str) ;
  296.    MenuItemData *item = &menu->data->items[index] ;
  297.    if (length > menu->max_width)
  298.       {
  299.       menu->max_width = length ;
  300.       int l = (length + 1) * 16 ;
  301.       if (l > menu->data->item_width)
  302.          menu->data->item_width = l ;
  303.       }
  304.    if (length <= 12)
  305.       {
  306.       item->icon_flags &= ~Icon::INDIRECT ;
  307.       strncpy (item->icon_data.text, str, length) ;
  308.       if (length < 12)
  309.          item->icon_data.text[length] = 0 ;
  310.       }
  311.    else
  312.       {
  313.       item->icon_flags |= Icon::INDIRECT ;
  314.       item->icon_data.indirecttext.buffer = new char [length+1] ;
  315.       item->icon_data.indirecttext.validstring = (char *)-1 ;
  316.       item->icon_data.indirecttext.bufflen = length+1 ;
  317.       strcpy (item->icon_