home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / hc1_2_x / popupmen.sit / popup.c next >
C/C++ Source or Header  |  1989-09-13  |  8KB  |  440 lines

  1. /*        PopUpMenu 2.0b2
  2.  
  3.         This HyperCard external function presents the user with a pop-up-
  4.         menu from which she would then select an item.  If no item is 
  5.         selected NULL is returned to your HyperTalk script.  Otherwise, 
  6.         the ordinal number of the item selected is returned.
  7.         
  8.         PopUpMenu is called with one to four arguments.  The first argument 
  9.         is the menu.  This menu is a series of menu items.  Each item is 
  10.         separated by either a comma, semi-colon, carriage-return, line-
  11.         feed, or tab.  Each item's characters will be added to the menu 
  12.         with AppendMenu;  Thus, any of the AppendMenu meta-characters can 
  13.         be used (except for the hierarchical menu meta-character). 
  14.         
  15.         The second argument is the number of an item to be checked.  If 
  16.         this argument is missing or empty then no item will be checked.
  17.         
  18.         The third and fourth arguments position the pop-up-menu.  The
  19.         coordinates must be global to the screen.  (I have retained 
  20.         global coordinates to maintain compatibility with PopUpMenu 
  21.         1.x.)  If either of these arguments is missing or empty then
  22.         the menu position defaults to the current mouse position.
  23.         
  24.         If all arguments are omitted then version and copyright
  25.         information is returned.
  26.         
  27.         Usage example.
  28.         
  29.             on mouseDown
  30.                 get PopUpMenu( "Color,Mono,Psychedelic", 3 );
  31.                 
  32.                 if it is empty then
  33.                     answer "Nothing was selected."
  34.                 else
  35.                     answer item it of "Color,Mono,Psychedelic" && "was selected."
  36.                 end if
  37.             end mouseDown
  38.             
  39.         Good luck with your stacks!
  40.         
  41.         
  42.         Andrew Gilmartin
  43.         Computing & Information Services
  44.         Box 1885
  45.         Brown University
  46.         Providence, Rhode Island 02912
  47.         
  48.         andrew@brownvm.brown.edu (internet)
  49.         andrew@brownvm (bitnet)
  50.  
  51.         Copyright (c) Brown University 1989.
  52. */
  53.  
  54.  
  55.  
  56.  
  57.  
  58. #include "MenuMgr.h"
  59. #include "HyperXCmd.h"
  60.  
  61.  
  62.  
  63.  
  64.  
  65. #define NULL  0L
  66.  
  67.  
  68. #define FALSE 0
  69. #define TRUE  1
  70.  
  71.  
  72. #define loop  for(;;)
  73.  
  74.  
  75. #define XCMDSetupA4()\
  76.     asm\
  77.     {\
  78.         move.l a4,-(sp)\
  79.         move.l a0,a4\
  80.     }
  81.  
  82.  
  83. #define XCMDRestoreA4()\
  84.     asm\
  85.     {\
  86.         move.l (sp)+,A4\
  87.     }
  88.  
  89.  
  90. #define MENU_ID 5000 /* This will give problems one day! */
  91.  
  92.  
  93.  
  94.  
  95.  
  96. int atoi( char * ascii );
  97.  
  98. int atoi( ascii ) /* "-32767"..."+32767" to -32767...32767 */
  99.     register char * ascii;
  100. {
  101.     register int integer;
  102.     int negative;
  103.     register char c;
  104.     
  105.     if ( *ascii == '-' )
  106.         negative = TRUE, 
  107.         ascii++;
  108.     else if ( *ascii == '+' )
  109.         negative = FALSE, 
  110.         ascii++;
  111.     else
  112.         negative = FALSE;
  113.         
  114.     for( 
  115.         integer = 0;
  116.         c = *ascii++, c >= '0' && c <= '9'; 
  117.         integer = integer * 10 + ( c - '0' ) );
  118.  
  119.     return negative ? - integer : integer;
  120.     
  121. } /* atoi */
  122.  
  123.  
  124.  
  125.  
  126.  
  127. void itoa(char * buffer, int integer );
  128.  
  129. void itoa( buffer, integer ) /* -32767...32767 to "-32767"..."32767" */
  130.     register char * buffer;
  131.     register int integer;
  132. {
  133.     register char _reffub[ 32 ];
  134.     register char * reffub = &_reffub[ 31 ];
  135.     
  136.     *reffub = '\0';
  137.     
  138.     if ( integer < 0 )
  139.     {
  140.         *buffer++ = '-';
  141.         integer = -integer;
  142.     }
  143.     
  144.     do
  145.     {
  146.         *--reffub = '0' + (integer % 10);
  147.         integer /= 10;
  148.     } while( integer > 0 );
  149.     
  150.     while ( *reffub != '\0' )
  151.         *buffer++ = *reffub++;
  152.     *buffer = '\0'; /* C strings end in a null! */ 
  153.         
  154. } /* itoa */
  155.  
  156.  
  157.  
  158.  
  159.  
  160. int strlen( char * string );
  161.  
  162. int strlen( string )
  163.     register char * string;
  164. {
  165.     register int length = 0;
  166.     
  167.     while ( *string++ != 0 )
  168.         length++;
  169.         
  170.     return length;
  171.     
  172. } /* strlen */
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. Handle string_to_param( char * string );
  180.  
  181. Handle string_to_param( string )
  182.     char * string;
  183. {
  184.     int    length;
  185.     Handle handle;
  186.     
  187.     length = strlen( string ) + 1 /* null character */;
  188.     
  189.     handle = NewHandle( length );
  190.     
  191.     if ( handle != NULL )
  192.         BlockMove( string, *handle, length);
  193.     
  194.     return handle;
  195.     
  196. } /* string_to_param */
  197.  
  198.  
  199.  
  200.  
  201.  
  202. Handle integer_to_param( int integer );
  203.  
  204. Handle integer_to_param( integer )
  205.     int integer;
  206. {
  207.     char   string[ 32 ];
  208.     int    length;
  209.     Handle handle;
  210.     
  211.     itoa( (char *) &string, integer );
  212.     
  213.     length = strlen( (char *) &string ) + 1 /* null character */;
  214.     
  215.     handle = NewHandle( length );
  216.     
  217.     if ( handle != NULL )
  218.         BlockMove( &string, *handle, length);
  219.         
  220.     return handle;
  221.     
  222. } /* integer_to_param */
  223.  
  224.  
  225.  
  226.  
  227.  
  228. int param_to_integer( Handle param );
  229.  
  230. int param_to_integer( param )
  231.     Handle param;
  232. {
  233.     return atoi( *param );
  234.     
  235. } /* param_to_integer */
  236.  
  237.  
  238.  
  239.  
  240.  
  241. MenuHandle popupmenu_create_menu( char * menu_items );
  242.  
  243. MenuHandle popupmenu_create_menu( menu_items )
  244.     char * menu_items;
  245. {
  246.     MenuHandle the_menu;
  247.     char       c;
  248.     struct
  249.     {
  250.         Str255 content;
  251.         char * pointer; /* where the next character should be placed in .content */
  252.         int    length;
  253.     } menu_item;
  254.     
  255.     
  256.     /*
  257.         Create an empty menu. MENU_ID has been arbitrarily chosen;
  258.         This might not be a good idea!
  259.     */
  260.     
  261.     if ( ( the_menu = NewMenu( MENU_ID, "\p" ) ) != NULL ) 
  262.     {
  263.         menu_item.pointer = (char *) &menu_item.content;
  264.         menu_item.length  = 0;
  265.             
  266.         loop
  267.         {
  268.             switch ( c = *menu_items++ )
  269.             {
  270.                 case  ',':    /* I figure that these cases should cover most */
  271.                 case  ';':  /* uses of PopUpMenu...                        */
  272.                 case '\n':
  273.                 case '\r':
  274.                 case '\t':
  275.                     if ( menu_item.length > 0 )
  276.                     {
  277.                         *menu_item.pointer = '\0'; /* C strings end in a null! */ 
  278.                         CtoPstr( (char *) &menu_item.content );
  279.                         AppendMenu( the_menu, &menu_item.content );
  280.                     }
  281.                     
  282.                     menu_item.pointer = (char *) &menu_item.content;
  283.                     menu_item.length  = 0;
  284.                     break;
  285.                 
  286.                 case '\0':
  287.                     if ( menu_item.length > 0 )
  288.                     {
  289.                         *menu_item.pointer = '\0'; /* C strings end in a null! */
  290.                         CtoPstr( (char *) &menu_item.content );
  291.                         AppendMenu( the_menu, &menu_item.content );
  292.                     }
  293.                     goto outside_loop;
  294.                     
  295.                 default:
  296.                     if ( menu_item.length < ( sizeof( menu_item.content ) - 1 ) )
  297.                         *menu_item.pointer++ = c,
  298.                         menu_item.length++;
  299.             }
  300.             
  301.         }
  302.         outside_loop:;
  303.     }
  304.     
  305.     return the_menu;
  306.     
  307. } /* popupmenu_create_menu */
  308.  
  309.  
  310.  
  311.  
  312.  
  313. int popupmenu( char * menu_items, int checked_item, Point mouse_location );
  314.  
  315. int popupmenu( menu_items, checked_item, mouse_location )
  316.     char * menu_items;
  317.     int checked_item;
  318.     Point mouse_location;
  319. {
  320.     MenuHandle the_menu;
  321.     long       the_selected_item = 0;
  322.     int        the_checked_item;
  323.     
  324.     
  325.     /* Create Menu */
  326.     
  327.     the_menu = popupmenu_create_menu( menu_items );
  328.     if ( the_menu == NULL )
  329.         return 0;
  330.     
  331.     
  332.     /* Check Menu Item */
  333.     
  334.     if ( checked_item > 0 && checked_item <= CountMItems( the_menu ) )
  335.     {
  336.         CheckItem( the_menu, checked_item, TRUE );
  337.         the_checked_item = checked_item;
  338.     }
  339.     else
  340.     {
  341.         the_checked_item = 1;
  342.     }
  343.     
  344.     
  345.     /* Add the menu to the system */
  346.     
  347.     InsertMenu( the_menu, -1 );
  348.     
  349.     
  350.     /* Get Menu Selection */
  351.  
  352.     the_selected_item = PopUpMenuSelect( 
  353.         the_menu, 
  354.         mouse_location.v,
  355.         mouse_location.h,
  356.         the_checked_item );
  357.  
  358.  
  359.     /* Remove the menu from the system */
  360.     
  361.     DeleteMenu( MENU_ID );
  362.     DisposeMenu( the_menu );
  363.     
  364.     
  365.     /* Return user's selection */
  366.     
  367.     return (int) ( the_selected_item & 0x0000FFFF );
  368.         
  369. } /* popupmenu */
  370.  
  371.  
  372.  
  373.  
  374.  
  375. pascal void main( XCmdBlockPtr paramPtr );
  376.  
  377. pascal void main( paramPtr )
  378.     XCmdBlockPtr paramPtr;
  379. {
  380.     char * menu_items /* = NULL */;
  381.     int    checked_item = -1;
  382.     int    selected_item /* = 0 */;
  383.     Point  mouse_location;
  384.     int    _mouse_location;
  385.     
  386.     XCMDSetupA4();
  387.  
  388.     /*    Get Mouse Location
  389.     
  390.         We need to get the mouse location early in the external just in case the 
  391.         user mouses ahead.  It would be better if the location of the last mouse 
  392.         down were available at the toolbox level...
  393.     */
  394.     
  395.     GetMouse( &mouse_location );
  396.     LocalToGlobal( &mouse_location );
  397.     
  398.     
  399.     /*    Parse Paramater List */
  400.     
  401.     switch ( paramPtr->paramCount )
  402.     {
  403.         case 4:
  404.             _mouse_location = param_to_integer( paramPtr->params[3] );
  405.             if ( _mouse_location > 0 )
  406.                 mouse_location.v = _mouse_location;
  407.             
  408.         case 3:
  409.             _mouse_location = param_to_integer( paramPtr->params[2] );
  410.             if ( _mouse_location > 0 )
  411.                 mouse_location.h = _mouse_location;
  412.                         
  413.         case 2:
  414.             checked_item = param_to_integer( paramPtr->params[1] );
  415.             
  416.         case 1:
  417.             HLock( paramPtr->params[0] );
  418.             menu_items = *(paramPtr->params[0]);
  419.             
  420.             selected_item = popupmenu( menu_items, checked_item, mouse_location );
  421.             if ( selected_item != 0 )
  422.                 paramPtr->returnValue = integer_to_param( selected_item );
  423.                 
  424.             HUnlock( paramPtr->params[0] ); 
  425.             break;
  426.             
  427.         case 0:
  428.             paramPtr->returnValue = string_to_param( 
  429.                 "PopUpMenu 2.0b2, ⌐ Brown University 1989" );
  430.             break;
  431.             
  432.         default:
  433.             break;
  434.     }
  435.     
  436.     XCMDRestoreA4();
  437.  
  438.     /* Bye, Bye! */
  439.     
  440. } /* main */