home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
hypercrd
/
hc1_2_x
/
popupmen.sit
/
popup.c
next >
Wrap
C/C++ Source or Header
|
1989-09-13
|
8KB
|
440 lines
/* PopUpMenu 2.0b2
This HyperCard external function presents the user with a pop-up-
menu from which she would then select an item. If no item is
selected NULL is returned to your HyperTalk script. Otherwise,
the ordinal number of the item selected is returned.
PopUpMenu is called with one to four arguments. The first argument
is the menu. This menu is a series of menu items. Each item is
separated by either a comma, semi-colon, carriage-return, line-
feed, or tab. Each item's characters will be added to the menu
with AppendMenu; Thus, any of the AppendMenu meta-characters can
be used (except for the hierarchical menu meta-character).
The second argument is the number of an item to be checked. If
this argument is missing or empty then no item will be checked.
The third and fourth arguments position the pop-up-menu. The
coordinates must be global to the screen. (I have retained
global coordinates to maintain compatibility with PopUpMenu
1.x.) If either of these arguments is missing or empty then
the menu position defaults to the current mouse position.
If all arguments are omitted then version and copyright
information is returned.
Usage example.
on mouseDown
get PopUpMenu( "Color,Mono,Psychedelic", 3 );
if it is empty then
answer "Nothing was selected."
else
answer item it of "Color,Mono,Psychedelic" && "was selected."
end if
end mouseDown
Good luck with your stacks!
Andrew Gilmartin
Computing & Information Services
Box 1885
Brown University
Providence, Rhode Island 02912
andrew@brownvm.brown.edu (internet)
andrew@brownvm (bitnet)
Copyright (c) Brown University 1989.
*/
#include "MenuMgr.h"
#include "HyperXCmd.h"
#define NULL 0L
#define FALSE 0
#define TRUE 1
#define loop for(;;)
#define XCMDSetupA4()\
asm\
{\
move.l a4,-(sp)\
move.l a0,a4\
}
#define XCMDRestoreA4()\
asm\
{\
move.l (sp)+,A4\
}
#define MENU_ID 5000 /* This will give problems one day! */
int atoi( char * ascii );
int atoi( ascii ) /* "-32767"..."+32767" to -32767...32767 */
register char * ascii;
{
register int integer;
int negative;
register char c;
if ( *ascii == '-' )
negative = TRUE,
ascii++;
else if ( *ascii == '+' )
negative = FALSE,
ascii++;
else
negative = FALSE;
for(
integer = 0;
c = *ascii++, c >= '0' && c <= '9';
integer = integer * 10 + ( c - '0' ) );
return negative ? - integer : integer;
} /* atoi */
void itoa(char * buffer, int integer );
void itoa( buffer, integer ) /* -32767...32767 to "-32767"..."32767" */
register char * buffer;
register int integer;
{
register char _reffub[ 32 ];
register char * reffub = &_reffub[ 31 ];
*reffub = '\0';
if ( integer < 0 )
{
*buffer++ = '-';
integer = -integer;
}
do
{
*--reffub = '0' + (integer % 10);
integer /= 10;
} while( integer > 0 );
while ( *reffub != '\0' )
*buffer++ = *reffub++;
*buffer = '\0'; /* C strings end in a null! */
} /* itoa */
int strlen( char * string );
int strlen( string )
register char * string;
{
register int length = 0;
while ( *string++ != 0 )
length++;
return length;
} /* strlen */
Handle string_to_param( char * string );
Handle string_to_param( string )
char * string;
{
int length;
Handle handle;
length = strlen( string ) + 1 /* null character */;
handle = NewHandle( length );
if ( handle != NULL )
BlockMove( string, *handle, length);
return handle;
} /* string_to_param */
Handle integer_to_param( int integer );
Handle integer_to_param( integer )
int integer;
{
char string[ 32 ];
int length;
Handle handle;
itoa( (char *) &string, integer );
length = strlen( (char *) &string ) + 1 /* null character */;
handle = NewHandle( length );
if ( handle != NULL )
BlockMove( &string, *handle, length);
return handle;
} /* integer_to_param */
int param_to_integer( Handle param );
int param_to_integer( param )
Handle param;
{
return atoi( *param );
} /* param_to_integer */
MenuHandle popupmenu_create_menu( char * menu_items );
MenuHandle popupmenu_create_menu( menu_items )
char * menu_items;
{
MenuHandle the_menu;
char c;
struct
{
Str255 content;
char * pointer; /* where the next character should be placed in .content */
int length;
} menu_item;
/*
Create an empty menu. MENU_ID has been arbitrarily chosen;
This might not be a good idea!
*/
if ( ( the_menu = NewMenu( MENU_ID, "\p" ) ) != NULL )
{
menu_item.pointer = (char *) &menu_item.content;
menu_item.length = 0;
loop
{
switch ( c = *menu_items++ )
{
case ',': /* I figure that these cases should cover most */
case ';': /* uses of PopUpMenu... */
case '\n':
case '\r':
case '\t':
if ( menu_item.length > 0 )
{
*menu_item.pointer = '\0'; /* C strings end in a null! */
CtoPstr( (char *) &menu_item.content );
AppendMenu( the_menu, &menu_item.content );
}
menu_item.pointer = (char *) &menu_item.content;
menu_item.length = 0;
break;
case '\0':
if ( menu_item.length > 0 )
{
*menu_item.pointer = '\0'; /* C strings end in a null! */
CtoPstr( (char *) &menu_item.content );
AppendMenu( the_menu, &menu_item.content );
}
goto outside_loop;
default:
if ( menu_item.length < ( sizeof( menu_item.content ) - 1 ) )
*menu_item.pointer++ = c,
menu_item.length++;
}
}
outside_loop:;
}
return the_menu;
} /* popupmenu_create_menu */
int popupmenu( char * menu_items, int checked_item, Point mouse_location );
int popupmenu( menu_items, checked_item, mouse_location )
char * menu_items;
int checked_item;
Point mouse_location;
{
MenuHandle the_menu;
long the_selected_item = 0;
int the_checked_item;
/* Create Menu */
the_menu = popupmenu_create_menu( menu_items );
if ( the_menu == NULL )
return 0;
/* Check Menu Item */
if ( checked_item > 0 && checked_item <= CountMItems( the_menu ) )
{
CheckItem( the_menu, checked_item, TRUE );
the_checked_item = checked_item;
}
else
{
the_checked_item = 1;
}
/* Add the menu to the system */
InsertMenu( the_menu, -1 );
/* Get Menu Selection */
the_selected_item = PopUpMenuSelect(
the_menu,
mouse_location.v,
mouse_location.h,
the_checked_item );
/* Remove the menu from the system */
DeleteMenu( MENU_ID );
DisposeMenu( the_menu );
/* Return user's selection */
return (int) ( the_selected_item & 0x0000FFFF );
} /* popupmenu */
pascal void main( XCmdBlockPtr paramPtr );
pascal void main( paramPtr )
XCmdBlockPtr paramPtr;
{
char * menu_items /* = NULL */;
int checked_item = -1;
int selected_item /* = 0 */;
Point mouse_location;
int _mouse_location;
XCMDSetupA4();
/* Get Mouse Location
We need to get the mouse location early in the external just in case the
user mouses ahead. It would be better if the location of the last mouse
down were available at the toolbox level...
*/
GetMouse( &mouse_location );
LocalToGlobal( &mouse_location );
/* Parse Paramater List */
switch ( paramPtr->paramCount )
{
case 4:
_mouse_location = param_to_integer( paramPtr->params[3] );
if ( _mouse_location > 0 )
mouse_location.v = _mouse_location;
case 3:
_mouse_location = param_to_integer( paramPtr->params[2] );
if ( _mouse_location > 0 )
mouse_location.h = _mouse_location;
case 2:
checked_item = param_to_integer( paramPtr->params[1] );
case 1:
HLock( paramPtr->params[0] );
menu_items = *(paramPtr->params[0]);
selected_item = popupmenu( menu_items, checked_item, mouse_location );
if ( selected_item != 0 )
paramPtr->returnValue = integer_to_param( selected_item );
HUnlock( paramPtr->params[0] );
break;
case 0:
paramPtr->returnValue = string_to_param(
"PopUpMenu 2.0b2, ⌐ Brown University 1989" );
break;
default:
break;
}
XCMDRestoreA4();
/* Bye, Bye! */
} /* main */