home *** CD-ROM | disk | FTP | other *** search
Text File | 2001-02-10 | 79.4 KB | 2,802 lines |
- /* POPMENU.C
- *==========================================================================
- * DESCRIPTION: Generic Popup Routines ( New and Improved )
- * VERSION 0.00 Started: February 7, 1991
- * VERSION 0.10 March 4, 1991
- * version 1.00 April 24,1991
- * Recreated damaged files
- * Removed open workstation calls.
- * vhandle = graf_handle()
- *
- *
- * INCLUDE: POPMENU.H
- * Requires: POP_HEAD.H
- *
- */
-
-
-
- /* INCLUDE FILES
- *==========================================================================
- */
- #include <sys\gemskel.h>
- #include <string.h >
- #include <tos.h>
- #include <stdlib.h>
- #include <stdio.h>
-
- #include "pop_head.h"
- #include "device.h"
-
-
- extern int xres, yres;
-
-
- /* PROTOTYPES
- *==========================================================================
- */
- void InitPopUpMenus( void );
- int GetNewPopMenu( void );
- POP_PTR GetMenuPtr( int MenuID );
-
- BOOLEAN InitCmdChar( POP_PTR PopPtr );
- void BuildCmdChar( POP_PTR PopPtr );
- void BuildKeyCodes( POP_PTR PopPtr, char *text, int num_entry );
- void DeletePopUpMenu( int MenuID );
-
- int InsertPopUpMenu( char *text, int num_entries, int height );
- long PopUpMenuSelect( int MenuID, int xpos, int ypos, int Item );
- BOOLEAN Pop_Blit( long *PopPtr, GRECT *xclip, int flag );
-
-
- BOOLEAN Build_Objects( POP_PTR curptr );
- void SetRootNode( OBJECT *tree, int xpos, int ypos, int Width, int Num );
- void SetTextNode( OBJECT *tree, int parent, POP_PTR PopPtr, int obj, int Ypos, int textnum, int Width );
- long CalcTextBufferSize( POP_PTR PopPtr );
- void BuildText( POP_PTR PopPtr );
- int CountBlanksNeeded( char *dindex, char *dtemp, int width, int num );
-
-
- BOOLEAN Pop_Arrow( POP_PTR PopPtr, int obj );
- void UpArrowStatus( POP_PTR PopPtr );
- void DownArrowStatus( POP_PTR PopPtr );
- void SetArrowClickDelay( long delay );
-
- /* KEYCODE CHECKING */
- long CheckForKeyCodes( POP_PTR PopPtr, char *text, int num_entry );
- char *CheckForCtrl( char *text );
- char *CheckForAlt( char *text );
- char *CheckForCapKey( char *text );
- char *CheckForCmdKey( char *text );
- BOOLEAN CheckForDisable( char *text );
- BOOLEAN CheckForMenuCheck( char *text );
- char *CheckForSubMenu( char *text );
- char *CheckForFuncKey( char *text );
- BOOLEAN CheckForDuplicate( char *text );
-
- /* APPEARANCE OF ITEMS */
- void SetHeight( int MenuID, int Height );
- void SetNumItems( int MenuID, int NumItems );
-
- void CheckItem( int MenuID, int item, BOOLEAN check );
- void DisableItem( int MenuID, int item );
- void EnableItem( int MenuID, int item );
-
- void SetItemCmd( int MenuID, int item, char cmd );
- char GetItemCmd( int MenuID, int item );
-
- void SetSubMenuID( int MenuID, int item, int ID );
- int GetSubMenuID( int MenuID, int item );
-
- void SetItemMark( int MenuID, int item, char key );
- char GetItemMark( int MenuID, int item );
-
- void SetFuncMark( int MenuID, int item, int num );
- int GetFuncMark( int MenuID, int item );
-
- void SetItem( int MenuID, int item, char *text );
- char *GetItem( int MenuID, int item );
-
- int GetStartItem( int MenuID );
- void SetStartItem( int MenuID, int item );
-
-
- /* SUBMENU HANDLING */
- POP_PTR DoSubMenu( POP_PTR PopPtr, int obj );
- BOOLEAN ShowSubMenu( int MenuID, int xpos, int ypos, GRECT *rect );
- void HideSubMenu( POP_PTR PopPtr );
- long EvntSubMenu( POP_PTR PopPtr );
- int FindNum( POP_PTR PopPtr, int obj );
- long MenuChoice( void );
-
-
- /* SUBMENU DELAY */
- long GetTimeHz( void );
- void SetSubMenuDelay( long ms );
- void SetSubDragDelay( long ms );
-
-
- void AdjustToScreen( POP_PTR PopPtr, int xpos, int ypos, GRECT *rect, BOOLEAN byte_flag, BOOLEAN Display_Flag );
- void WaitForUpButton( void );
-
- /* EXTERNALS
- *==========================================================================
- * These functions and variables are required and must be
- * supplied externally.
- */
-
- int BUT_OR( void ); /* Used to ensure left mouse button */
- extern int (*BADDR)( void );
- extern int BSTATE;
- extern int BREAL;
-
-
- /* DEFINES
- *==========================================================================
- */
- #define INIT_DISPLAY_DELAY 300L /* Initial Submenu Display Delay */
- #define INIT_DRAG_DELAY 3000L /* Initial Submenu Drag Delay */
-
- #define INIT_CLICK_DELAY 150L /* Delay for STARTING arrow scroll */
-
- #define STLOW 2
- #define STMED 3
-
- #define MAX_MENUS 50 /* Maximum # of Menus allowed...*/
- #define UP_ARROW 0x01
- #define DOWN_ARROW 0x02
- #define RIGHT_ARROW 0x03
-
-
-
- /* GLOBAL
- *==========================================================================
- */
- POP_NODE MenuList[ MAX_MENUS ]; /* Menu structure Storage */
- BOOLEAN free_flag[ MAX_MENUS ];
-
- char *KeyText[] = { "HOME", /* Text for menu items using these*/
- "HELP", /* as keyboard shortcuts... */
- "UNDO",
- "ESC",
- "INSERT",
- "CLR",
- "DEL",
- "TAB",
- "ENTER",
- "RETURN"
- };
-
-
- char CmdText[ 10 ]; /* Temp string storage... */
- char TempString[ 255 ];
- int xout[57]; /* used for vq_extnd() */
-
-
- long SUBMENU_DELAY; /* Delay time for submenus to appear ( ms ) */
- long SUBDRAG_DELAY; /* Delay time for submenus to go active( ms) */
- long CLICK_DELAY; /* Delay time for arrows to start scrolling(ms)*/
- long TimeInHz; /* Current Time in 200 Hz */
-
- /* Used by the MenuChoice() call */
- int CurObject; /* Current Object clicked on. ( Global ) */
- int CurMenu; /* Current Menu clicked on. ( Global ) */
-
-
- /* FUNCTIONS
- *==========================================================================
- */
-
-
- /* InitPopMenus()
- * ====================================================================
- * Simply clears out the flags in the free_flags structure.
- */
- void
- InitPopUpMenus( void )
- {
- int i;
-
- for( i = 0; i < MAX_MENUS; i++ )
- free_flag[ i ] = FALSE;
- SetSubMenuDelay( INIT_DISPLAY_DELAY );
- SetSubDragDelay( INIT_DRAG_DELAY );
- SetArrowClickDelay( INIT_CLICK_DELAY );
- }
-
-
-
- /* InsertPopMenu()
- * ====================================================================
- * Returns: Pointer to the POPUP structure.
- * IN:
- * XHEIGHT ( in characters ) - actually, number of entries displayed
- * NUM_ENTRIES - Total # of menu entries.
- * Pointer to text address...
- * OUT: # >= 0 Valid Menu ID
- * # < 0 Error messages.
- * -1 = Memory Allocation Error.
- * -2 = No more Menu Slots available.
- */
- int
- InsertPopUpMenu( char *text, int num_entries, int height )
- {
- POP_PTR PopPtr;
- int MenuID;
-
- MenuID = GetNewPopMenu();
-
- /* No more menu slots available.*/
- if( MenuID == -1 )
- return( -2 );
-
- PopPtr = GetMenuPtr( MenuID );
- PPREV( PopPtr ) = ( POP_PTR )NULL;
-
- PMENUID( PopPtr ) = MenuID;
- PXPOS( PopPtr ) = PYPOS( PopPtr ) = 0;
- PNUM( PopPtr ) = num_entries;
- POBJECT( PopPtr ) = ( OBJECT *)NULL;
-
- /* Take care of height of menu */
- if( height > PNUM( PopPtr ) )
- height = PNUM( PopPtr );
- PHEIGHT( PopPtr ) = height;
- PIX_HEIGHT( PopPtr ) = ( PHEIGHT( PopPtr ) * gl_hchar );
- PTEXT( PopPtr ) = text;
-
- if( !InitCmdChar( PopPtr ))
- {
- /* If memory error, clear out the Menu Slot
- * and return a -1.
- */
- free_flag[ MenuID ] = FALSE;
- MenuID = -1;
- }
- return( MenuID );
- }
-
-
-
- /* GetNewPopMenu()
- * ====================================================================
- * Find an unused slot for a menu.
- * RETURN( -1 ) if there are no more menu slots available.
- */
- int
- GetNewPopMenu( void )
- {
- int i;
-
- for( i = 0; i < MAX_MENUS; i++ )
- {
- if( !free_flag[ i ] )
- {
- free_flag[i] = TRUE;
- return( i );
- }
- }
- return( -1 );
- }
-
-
-
-
- /* GetMenuPtr()
- * ====================================================================
- * Returns a pointer to the Menu Structure if given a valid menuID
- */
- POP_PTR
- GetMenuPtr( int MenuID )
- {
- return( ( POP_PTR )&MenuList[ MenuID ] );
- }
-
-
-
- /* InitCmdChar()
- * ====================================================================
- * Initializes the CmdChar memory for a menu structure.
- * The memory is MALLOCed! So the application MUST call
- * DeletePopMenu() for each menu created. OR ELSE...!
- * Need to check for malloc failures.
- * RETURN: FALSE = ERROR!
- * TRUE = AOK!
- * It will be up to the program to inform the user that
- * no menu was created and initialized.
- */
- BOOLEAN
- InitCmdChar( POP_PTR PopPtr )
- {
- int i;
-
- PCmdChar( PopPtr ) = ( CmdChar *)malloc( (long)( (long)PNUM( PopPtr ) + 10L ) * (long)sizeof( CmdChar ));
- /* We go up to + 2 because we have ...
- * PNUM() = UP ARROW TEXT
- * PNUM+1 = DOWN ARROW TEXT
- * PNUM+2 = BLANK TEXT
- */
- if( PCmdChar( PopPtr ) )
- {
- for( i = 0; i <= ( PNUM( PopPtr ) + 2 ); i++ )
- {
- CmdState( PopPtr->CharPtr[ i ] ) = NORMAL;
- CmdSubMenu( PopPtr->CharPtr[ i ] ) = -1;
- CmdFlag( PopPtr->CharPtr[i] ) = '\0';
- }
-
- BuildCmdChar( PopPtr );
- return( TRUE );
- }
- else
- return( FALSE );
- }
-
-
-
-
- /* BuildCmdChar()
- * ====================================================================
- * Calculate the text buffer size that we'll have to malloc, based upon
- * the largest text string and the number of entries.
- */
- void
- BuildCmdChar( POP_PTR PopPtr )
- {
- char *txtptr;
- long length;
- int count;
-
- txtptr = PTEXT( PopPtr );
- if( txtptr )
- {
- for( count = 0; count < PNUM( PopPtr ); count++ )
- {
- length = strlen( txtptr );
- BuildKeyCodes( PopPtr, txtptr, count );
- txtptr += ( length + 1 );
- }
- }
- }
-
-
-
-
-
- /* BuildKeyCodes()
- * =====================================================================
- * Checks the text string for various keycodes and subtracts
- * an appropriate amount from the length if any are found.
- * For many of these, there should only be one of them.
- * We then ADD back in the amount of ACTUAL text usage this item
- * would take. IE: a Function Key can be F10 so 3 characters...
- * or a CmdKey can be the letters: 'DELETE' 6 characters added.
- * This will also fill up the CMDCHAR structures.
- */
- void
- BuildKeyCodes( POP_PTR PopPtr, char *text, int num_entry )
- {
- char *txtptr;
-
- if( ( txtptr = CheckForCtrl( text )) != NULL )
- {
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '^';
- CmdHotKey( PopPtr->CharPtr[ num_entry ] ) = *( ++txtptr );
- }
-
-
- if( ( txtptr = CheckForAlt( text ) ) != NULL )
- {
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '&';
- CmdHotKey( PopPtr->CharPtr[ num_entry ] ) = *( ++txtptr );
- }
-
- if( ( txtptr = CheckForCapKey( text ) ) != NULL )
- {
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '|';
- CmdHotKey( PopPtr->CharPtr[ num_entry ] ) = *( ++txtptr );
- }
-
- if( ( txtptr = CheckForCmdKey( text ) ) != NULL )
- {
- /* We ACKNOWLEDGE -----
- * [H] HELP [U] Undo [E] Escape [I] Insert
- * [D] DEL [C] Clr [h] Home [T] TAB
- * [e] ENTER [R] RETURN
- */
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '$';
- CmdHotKey( PopPtr->CharPtr[ num_entry ] ) = *( ++txtptr );
- }
-
-
- /* Check for the '@' character which will tell us to
- * disable the current menu item that we are working on.
- */
-
- if( CheckForDisable( text ) )
- DisableItem( PMENUID( PopPtr ), num_entry );
- else
- EnableItem( PMENUID( PopPtr ), num_entry );
-
- /* Check for CheckMark ( ! ) */
- CheckItem( PMENUID( PopPtr ), num_entry, CheckForMenuCheck( text ) );
-
- if( ( txtptr = CheckForSubMenu( text ) ) != NULL )
- {
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '~';
- txtptr++;
- CmdSubMenu( PopPtr->CharPtr[ num_entry ] ) = atoi( txtptr );
- }
-
- if( ( txtptr = CheckForFuncKey( text ) ) != NULL )
- {
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '#';
- txtptr++;
- CmdFuncKey( PopPtr->CharPtr[ num_entry ] ) = atoi( txtptr );
- }
-
- if( CheckForDuplicate( text ) )
- CmdFlag( PopPtr->CharPtr[ num_entry ] ) = '*';
- }
-
-
-
-
-
-
- /* DeletePopUpMenu()
- * ====================================================================
- */
- void
- DeletePopUpMenu( int MenuID )
- {
- POP_PTR PopPtr;
-
- if( free_flag[ MenuID ] )
- {
- free_flag[ MenuID ] = FALSE;
- PopPtr = GetMenuPtr( MenuID );
-
- if( PCmdChar( PopPtr ) )
- free( PCmdChar( PopPtr ) );
-
- PCmdChar( PopPtr ) = ( CmdChar *)NULL;
- }
- }
-
-
-
-
- /* PopUpMenuSelect()
- * ====================================================================
- * Displays the actual popup menu.
- * Let's the user select an object.
- * IN: POP_PTR PopPtr;
- * int xpos;
- * int ypos;
- * int Start_Obj; Index to show selected else start with 0
- * BOOLEAN Arrow_Flag; If TRUE, display arrows if height < num_items.
- * FALSE, don't display arrows if height < num_items.
- * returns: long where....
- * HIGH WORD LOW WORD
- * MenuID Item Selected.
- * -1L if NONE selected.
- * If the MenuID is valid, but the item is -1, then
- * the user clicked on a disabled menu item.
- * -2L if Memory Allocation Error
- * -3L if workstation error.
- */
- long
- PopUpMenuSelect( int MenuID, int xpos, int ypos, int Item )
- {
-
- long obj;
- POP_PTR PopPtr;
- GRECT rect;
- MRETS mk;
- int max_height;
-
- WaitForUpButton();
- wind_update( BEG_MCTRL );
-
- open_vwork();
- vq_extnd( vhandle, 0, xout );
- xres = xout[0];
- yres = xout[1];
-
- vex_butv( vhandle, BUT_OR, &BADDR );
-
- PopPtr = GetMenuPtr( MenuID );
- PopUpItem( PopPtr ) = Item;
-
- PXPOS( PopPtr ) = xpos;
- PYPOS( PopPtr ) = ypos;
- PPREV( PopPtr ) = ( POP_PTR )NULL;
-
- /* Take care of height of menu */
- if( PHEIGHT( PopPtr ) > PNUM( PopPtr ) )
- PHEIGHT( PopPtr ) = PNUM( PopPtr );
-
- /* Limit Height to Height of screen - ( 2 * gl_hchars ) */
- max_height = yres - ( 2 * gl_hchar );
- while( ( PHEIGHT( PopPtr ) * gl_hchar ) > max_height )
- PHEIGHT( PopPtr ) -= 1;
-
- PIX_HEIGHT( PopPtr ) = ( PHEIGHT( PopPtr ) * gl_hchar );
-
-
- /* Take care of the width of the menu here...*/
- PTEXTBUFFSIZE( PopPtr ) = CalcTextBufferSize( PopPtr );
- PIX_WIDTH( PopPtr ) = ( PWIDTH( PopPtr ) * gl_wchar );
-
- AdjustToScreen( PopPtr, xpos, ypos, &rect, FALSE, TRUE );
- if( Pop_Blit( (long *)&PMEM( PopPtr ), &PObRect( PopPtr ), 0 ) )
- {
- if( Build_Objects( PopPtr ) )
- {
- obj = EvntSubMenu( PopPtr );
- if( obj == -2L ) /* returning from a submenu - error */
- obj = -1L; /* then set it to click on nothing */
- Pop_Blit( (long *)&PMEM( PopPtr ), &PObRect( PopPtr ), 1 );
- }
- else /* Memory Allocation Error in Space Capsule */
- obj = -2L;
-
- if( POBJECT( PopPtr ) )
- free( POBJECT( PopPtr ) );
-
- if( PTEXTBUFF( PopPtr ) )
- free( PTEXTBUFF( PopPtr ) );
-
- }
- else /* ERROR: Memory Allocation Error */
- obj = -2L;
-
- POBJECT( PopPtr ) = ( OBJECT *)NULL;
- PTEXTBUFF( PopPtr ) = ( char *)NULL;
-
- Evnt_button( 1, 1, 0, &mk );
-
- vex_butv( vhandle, BADDR, &BADDR );
- close_vwork();
-
- wind_update( END_MCTRL );
-
- return( obj );
- }
-
-
-
-
- /* Build_Objects()
- * ====================================================================
- * RETURN: TRUE - AOK
- * FALSE- Memory Allocation Error
- */
- BOOLEAN
- Build_Objects( POP_PTR PopPtr )
- {
- int num_objects;
- GRECT rect;
- int text_index; /* Index into the text data 0 based */
- int count;
- int ypos; /* Y position of object ( in characters*/
- int temp;
-
- OBJECT *tree;
- int obj;
-
- /* Calculate the number of objects needed...
- * ROOT + # of STRINGS + ( safety buffer )
- */
- num_objects = 1 + PHEIGHT( PopPtr ) + 10; /* + 10 for safety buffer */
-
- /* get the memory for this number of objects */
- POBJECT( PopPtr ) = ( OBJECT * )malloc( (long)(sizeof( OBJECT ) * (long)num_objects ));
-
- /* Malloc the text memory and then build them. */
- /* Need malloc checking of course... */
- PTEXTBUFF( PopPtr) = malloc( PTEXTBUFFSIZE( PopPtr ) );
-
- /* Memory Allocation Error */
- if( !POBJECT( PopPtr ) || !PTEXTBUFF( PopPtr ) )
- return( FALSE );
-
- BuildText( PopPtr );
-
-
- /* setup the root */
- tree = POBJECT( PopPtr );
- SetRootNode( tree, PXPOS( PopPtr ), PYPOS( PopPtr ),
- PWIDTH( PopPtr ), PHEIGHT( PopPtr ) );
-
- ypos = text_index = 0;
-
- obj = 1; /* Start Creating from object 1 */
- PFIRST( PopPtr ) = 1; /* first G_STRING starts at 3 */
-
- POFFSET( PopPtr ) = ( PopUpItem( PopPtr ) + ( PNUM( PopPtr ) > PHEIGHT( PopPtr ) )) / PHEIGHT( PopPtr );
-
- if( POFFSET( PopPtr ) )
- {
- POFFSET( PopPtr ) = PopUpItem( PopPtr );
- temp = PNUM( PopPtr ) - PHEIGHT( PopPtr ) + 1;
-
- if( POFFSET( PopPtr ) >= temp )
- POFFSET( PopPtr ) = temp;
- }
- text_index = POFFSET( PopPtr );
-
- for( count = 0; count < PHEIGHT( PopPtr ); count++ )
- {
- if( count == 0 )
- {
- if( POFFSET( PopPtr ) )
- SetTextNode( tree, ROOT, PopPtr, obj++, ypos++, PNUM( PopPtr ), PWIDTH( PopPtr ) );
- else
- {
- if( CmdState( PopPtr->CharPtr[ text_index ] ) & CHECKED )
- CheckObj( obj );
- SetTextNode( tree, ROOT, PopPtr, obj++, ypos++, text_index++, PWIDTH( PopPtr ) );
- }
- }
- else
- {
- if( count >= ( PHEIGHT( PopPtr ) - 1 ) )
- {
- if( ( POFFSET( PopPtr ) + PHEIGHT( PopPtr ) ) < PNUM( PopPtr ) )
- SetTextNode( tree, ROOT, PopPtr, obj++, ypos++, PNUM( PopPtr ) + 1, PWIDTH( PopPtr ) );
- else
- {
- if( CmdState( PopPtr->CharPtr[ text_index ] ) & CHECKED )
- CheckObj( obj );
-
- SetTextNode( tree, ROOT, PopPtr, obj++, ypos++, text_index++, PWIDTH( PopPtr ) );
- }
- }
- else
- {
- if( CmdState( PopPtr->CharPtr[ text_index ] ) & CHECKED )
- CheckObj( obj );
-
- SetTextNode( tree, ROOT, PopPtr, obj++, ypos++, text_index++, PWIDTH( PopPtr ) );
- }
- }
- }
- PLAST( PopPtr ) = obj - 1;
- ObFlags( obj - 1 ) = LASTOB;
-
- rect = ObRect( ROOT );
- rect.g_x -= 2;
- rect.g_y -= 2;
- rect.g_w += 5;
- rect.g_h += 5;
- rc_intersect( &desk, &rect ); /* clip to desktop */
- Objc_draw( tree, ROOT, MAX_DEPTH, &rect );
- return( TRUE );
- }
-
-
-
- /* SetRootNode()
- * ====================================================================
- */
- void
- SetRootNode( OBJECT *tree, int xpos, int ypos, int Width, int Num )
- {
- ObNext( ROOT ) = -1;
- ObHead( ROOT ) = -1;
- ObTail( ROOT ) = -1;
- ObType( ROOT ) = G_BOX;
- ObFlags( ROOT ) = NONE;
- ObState( ROOT ) = SHADOWED;
- ObIndex( ROOT ) = 0xFF1100L;
-
- /* fix up for screen...*/
- ObX( ROOT ) = xpos;
- ObY( ROOT ) = ypos;
- ObW( ROOT ) = Width * gl_wchar;
- ObH( ROOT ) = Num * gl_hchar;
- }
-
-
-
- /* SetTextNode()
- * ====================================================================
- */
- void
- SetTextNode( OBJECT *tree, int parent, POP_PTR PopPtr, int obj, int Ypos, int textnum, int Width )
- {
- ObNext( obj ) = -1;
- ObHead( obj ) = -1;
- ObTail( obj ) = -1;
-
- ObType( obj ) = G_STRING;
- ObFlags( obj ) = NONE;
-
- ObString( obj ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * textnum ];
-
- ObState( obj ) = CmdState( PopPtr->CharPtr[ textnum ] );
-
- ObX( obj ) = 0;
- ObY( obj ) = Ypos * gl_hchar;
- ObW( obj ) = Width * gl_wchar;
- ObH( obj ) = gl_hchar;
- objc_add( tree, parent, obj );
- }
-
-
-
-
- /* CalcTextBufferSize()
- * ====================================================================
- * Calculate the text buffer size that we'll have to malloc, based upon
- * the largest text string and the number of entries.
- */
- long
- CalcTextBufferSize( POP_PTR PopPtr )
- {
- char *xptr;
- long size;
- long xsize;
- long actual;
- int i;
-
- size = 0L;
- PWIDTH( PopPtr ) = 0;
- xptr = ( char *)NULL;
- xptr = PTEXT( PopPtr );
- if( xptr )
- {
- for( i = 0; i < PNUM( PopPtr ); i++ )
- {
- xsize = strlen( xptr );
- actual = CheckForKeyCodes( PopPtr, xptr, i );
- if( actual > size )
- size = actual;
- xptr += ( xsize + 1 );
-
- /* Get's us past the nulls to the head of the next string */
- while( !( *xptr ) )
- xptr++;
- }
- /* size-> now contains the length of the longest string. */
- size += 1; /* for a blank after...*/
- size += 2; /* for 2 blanks before the string*/
- /* Number of characters in our longest string...*/
- PWIDTH( PopPtr ) = (int)size;
-
- size += 1; /* for the null. */
- size += 10; /* for the Control Keys or RT Arrow */
- size *= PNUM( PopPtr ); /* For the number of entries. */
- size += ( size / 2 ); /* Buffer area, just in case */
- }
- return( size );
- }
-
-
- /* BuildText()
- * ====================================================================
- * Takes the pointer to the menu_text given by the program and
- * builds the text in the memory buffer where...
- * 1) 2 spaces before each text string.
- * 2) 1 space after the longest string.
- * 3) pads spaces after shorter strings to match the longest string.
- * 4) Null terminates each string.
- * 5) *# - The char following is duplicated the width of the menu.
- * Characters following it are ignored to the end of the string.
- * example: *- The line is filled with "---------"
- * 6) @ - means to disable this menu item
- * 7) /# - means that there is a keycode: ie: /T == [T]
- * 8) ## - means that there is a function key. #10 is F10
- * 9) ^# - means that there is a ctrl key: ^H
- * 10) $# - means that there is a CmdKey: ie: $H = HELP ( 4 chars )
- * We ACKNOWLEDGE -----
- * [H] HELP [U] Undo [E] Escape [I] Insert
- * [D] DEL [C] Clr [h] Home [T] TAB
- * [e] ENTER [R] RETURN
- *
- * 11) - means that there is an ALT Key: &A - Alt A
- * 12) ~# - means that there is a submenu: ~1 - attach submenu 1
- * 13) ! - means that the menu item is CHECKED.
- */
- void
- BuildText( POP_PTR PopPtr )
- {
- char *sindex; /* Pointer to source text... */
- char *stemp; /* Pointer INTO source text */
- char *dindex; /* Pointer to destination text */
- char *dtemp; /* Pointer INTO destination text*/
- int num_entries; /* Number of entries counter... */
- int num;
- int num2;
- long length; /* length of a string... */
- long i; /* temp variable... */
-
- if( !PTEXTBUFF( PopPtr ) ) /* if there is no destination buffer...*/
- return; /* skip doing all of this... */
-
- sindex = PTEXT( PopPtr );
- dindex = PTEXTBUFF( PopPtr );
-
- for( num_entries = 0; num_entries <= PNUM( PopPtr ); num_entries++ )
- {
- if( num_entries < PNUM( PopPtr ) )
- {
-
- if( ( stemp = strchr( sindex, '*' )) != NULL )
- {
- /* Check for a '*' character. The character following
- * will be extened the length of the string.
- * All characters following after that will be ignored.
- */
- stemp++; /* gets us to the item we want to duplicate */
- dtemp = dindex; /* get a ptr to the destination */
-
- /* Duplicate the character to the proper width wanted...*/
- for( i = 0; i < PWIDTH( PopPtr ); i++ )
- *dtemp++ = *stemp;
- *dtemp = '\0'; /* NULL terminate the string */
- }
- else
- {
- strcpy( dindex, " " ); /* Pad the entry with 2 blanks */
- stemp = sindex; /* Get a pointer to the source */
- dtemp = dindex+2; /* Get a pointer to the dest...*/
-
- /* Copy the source string to the destination buffer
- * skipping the HOT chars that will allow submenus,
- * disabling menus, keycodes etc.
- */
- while( *stemp )
- {
- switch( *stemp )
- {
- case '@': /* Disable menu item */
- case '!': /* CheckMark menu item */
- stemp++;
- break;
-
- case '^': /* Ctrl Key */
- case '&': /* Alt Key */
- case '|': /* Cap Key */
- case '$': /* CmdKey */
- case '~': /* Submenu */
- stemp += 2;
- break;
-
- case '#': /* FuncKey */
- stemp += 2;
- num = CmdFuncKey( PopPtr->CharPtr[ num_entries ] );
- if( num > 9 )
- stemp++;
- break;
-
- default: *dtemp++ = *stemp++;
- break;
- }
- }
-
- /* Now add in the necessary text for the Keycodes..*/
- switch( CmdFlag( PopPtr->CharPtr[ num_entries ] ) )
- {
- case '^': /* Ctrl Key */
- case '&': /* Alt Key */
- num = CountBlanksNeeded( dindex, dtemp, PWIDTH( PopPtr ), 2 );
- for( i = 0; i < num; i++ )
- *dtemp++ = ' '; /* add a space */
- *dtemp++ = (( CmdFlag( PopPtr->CharPtr[ num_entries ] ) == '^' ) ? ( '^' ) : ( 0x07 ) );
- *dtemp++ = CmdHotKey( PopPtr->CharPtr[ num_entries ] );
- break;
-
- case '|': /* Cap Key */
- num = CountBlanksNeeded( dindex, dtemp, PWIDTH( PopPtr ), 3 );
- for( i = 0; i < num; i++ )
- *dtemp++ = ' '; /* add a space */
- *dtemp++ = '[';
- *dtemp++ = CmdHotKey( PopPtr->CharPtr[ num_entries ] );
- *dtemp++ = ']';
- break;
-
- case '$': /* CmdKey */
- switch( CmdHotKey( PopPtr->CharPtr[ num_entries ] ) )
- {
- case 'h': /* Home */
- strcpy( &CmdText[0], KeyText[0] );
- break;
-
- case 'H': /* HELP */
- strcpy( &CmdText[0], KeyText[1] );
- break;
-
- case 'U': /* Undo */
- strcpy( &CmdText[0], KeyText[2] );
- break;
-
- case 'E': /* Escape*/
- strcpy( &CmdText[0], KeyText[3] );
- break;
-
- case 'I': /* Insert */
- strcpy( &CmdText[0], KeyText[4] );
- break;
-
- case 'C': /* Clr */
- strcpy( &CmdText[0], KeyText[5] );
- break;
-
- case 'D': /* Delete */
- strcpy( &CmdText[0], KeyText[6] );
- break;
-
- case 'T': /* TAB */
- strcpy( &CmdText[0], KeyText[7] );
- break;
-
- case 'e': /* ENTER */
- strcpy( &CmdText[0], KeyText[8] );
- break;
-
- case 'R': /* RETURN */
- strcpy( &CmdText[0], KeyText[9] );
- break;
-
- default: CmdText[0] = '\0';
- break;
- }
- num = (int)strlen( &CmdText[0] );
- num = CountBlanksNeeded( dindex, dtemp, PWIDTH( PopPtr ), num );
- for( i = 0; i < num; i++ )
- *dtemp++ = ' '; /* add a space */
- *dtemp = '\0';
- strcat( dindex, &CmdText[0] );
- length = strlen( dindex );
- dtemp = dindex + length;
- break;
-
- case '#': /* FuncKey */
- num = CmdFuncKey( PopPtr->CharPtr[ num_entries ] );
- num = (( num < 10 ) ? ( 2 ) : ( 3 ) );
- num2 = CountBlanksNeeded( dindex, dtemp, PWIDTH( PopPtr ), num );
- for( i = 0; i < num2; i++ )
- *dtemp++ = ' '; /* add a space */
- *dtemp++ = 'F';
- num = CmdFuncKey( PopPtr->CharPtr[ num_entries ] );
- if( num < 10 )
- *dtemp++ = num + '0';
- else /* handle special case for F10 */
- {
- *dtemp++ = '1';
- *dtemp++ = '0';
- }
- break;
-
- case '~': /* Submenu */
- num = CountBlanksNeeded( dindex, dtemp, PWIDTH( PopPtr ), 2 );
- for( i = 0; i < num; i++ )
- *dtemp++ = ' '; /* add a space */
- *dtemp++ = RIGHT_ARROW; /* Right Arrow */
- *dtemp++ = ' ';
- break;
-
- default:
- break;
- }
- *dtemp = '\0';
-
- /* Get the length of the destination string and
- * pad it with blanks to make it the width of
- * the final string wanted.
- */
- length = strlen( dindex );
- for( i = length; i < PWIDTH( PopPtr ); i++ )
- strcat( dindex, " " );
-
- }
- /* Get the length of the actual string and
- * advance it to the next string skipping the NULL
- * and moving to the first char of the next string.
- */
- length = strlen( sindex );
- sindex = sindex + length + 1;
-
- /* Advance us thru the nulls to the start of the next string*/
- while( !(*sindex) )
- sindex++;
-
- /* Advance dest to end of the new string */
- dindex = dindex + PWIDTH( PopPtr ) + 1;
- }
- else
- {
- /* The PNUM() menu item will have an UP Arrow in its text */
- strcpy( dindex, " " );
- for( i = 1; i < PWIDTH( PopPtr ); i++ )
- strcat( dindex, " " );
- *(dindex + 2 ) = UP_ARROW; /* UP ARROW */
-
- /* The PNUM() + 1 menu item will have a DOWN Arrow in its text */
- dindex = dindex + PWIDTH( PopPtr ) + 1;
- strcpy( dindex, " " );
- for( i = 1; i < PWIDTH( PopPtr ); i++ )
- strcat( dindex, " " );
- *(dindex + 2 ) = DOWN_ARROW; /* DOWN ARROW */
-
- /* The PNUM() + 2 menu item will have a blank string in its text*/
- dindex = dindex + PWIDTH( PopPtr ) + 1;
- strcpy( dindex, " " );
- for( i = 1; i < PWIDTH( PopPtr ); i++ )
- strcat( dindex, " " );
- }
- }
- }
-
-
-
- /* CountBlanksNeeded()
- * ====================================================================
- * Counts the number of blanks to go between the menu item and the
- * control key or whatever.
- */
- int
- CountBlanksNeeded( char *dindex, char *dtemp, int width, int num )
- {
- long length;
-
- *dtemp = '\0';
- length = strlen( dindex );
- return( width - 1 - (int)length - num );
- }
-
-
-
-
- /* Pop_Arrow()
- *==========================================================================
- * Scroll the popup menu items if up or down arrow is selected.
- *
- * IN: int obj: up or down arrow is selected.
- * int *offset: Offset into the menu items text array
- * int num_items: Total number of menu items involved.
- * char *items[]: Pointer to the text array
- *
- * OUT: TRUE - ended on a submenu
- * FALSE - ended on a normal menu item.
- */
- BOOLEAN
- Pop_Arrow( POP_PTR PopPtr, int obj )
- {
- OBJECT *tree;
- int DrawFlag;
- int i,j;
- GRECT rect;
- GRECT xrect, clip;
- MRETS mk;
- int pxy[8];
- int xclip[4];
- long location = 0L; /* SCREEN MFDB */
- BOOLEAN DelayFlag;
- BOOLEAN ReturnFlag;
-
- tree = POBJECT( PopPtr );
-
- xrect = ObRect( obj );
- objc_offset( tree, obj, &xrect.g_x, &xrect.g_y );
- DelayFlag = TRUE;
- ReturnFlag = FALSE;
-
- do
- {
- BSTATE = 0;
- DrawFlag = FALSE;
- /* Up Arrow Selected AND not at the top */
- if( ( obj == PFIRST( PopPtr ) ) && ( POFFSET( PopPtr ) > 0 ))
- {
- POFFSET( PopPtr ) -= 1;
- DrawFlag = TRUE;
- /* special handling...to make it jump to zero if
- * we are displaying item 2, we can jump to zero, blit and
- * redraw the top 2 items instead.
- */
- if( POFFSET( PopPtr ) == 1 )
- POFFSET( PopPtr ) = 0;
- }
-
- /* DOWN Arrow and not within PHEIGHT() items from the bottom */
- if( ( obj == PLAST( PopPtr ) ) && ( POFFSET( PopPtr ) <= ( PNUM( PopPtr ) - PHEIGHT( PopPtr ) ) ) )
- {
- POFFSET( PopPtr ) += 1;
- DrawFlag = TRUE;
- /* Special handling for first item only */
- if( POFFSET( PopPtr ) == 1 )
- {
- if( ( POFFSET( PopPtr ) + PHEIGHT( PopPtr ) - 1 ) < PNUM( PopPtr ) )
- POFFSET( PopPtr ) += 1;
- }
- }
-
- j = POFFSET( PopPtr );
- if( DrawFlag )
- {
- UpArrowStatus( PopPtr );
- DownArrowStatus( PopPtr );
-
- /* Get the Blit Rectangle */
- clip = ObRect( PFIRST( PopPtr ));
- objc_offset( tree, ROOT, &clip.g_x, &clip.g_y );
- clip.g_h *= PHEIGHT( PopPtr );
-
- /* Calculate the height */
-
- if( strchr( ObString( PFIRST( PopPtr ) ), UP_ARROW ) )
- {
- clip.g_h -= gl_hchar; /* Subtract 1 char height */
- clip.g_y += gl_hchar; /* Move the Ypos down 1 level */
- }
-
- if( strchr( ObString( PLAST( PopPtr )), DOWN_ARROW ) )
- {
- clip.g_h -= gl_hchar; /* Subtract 1 char height */
- }
-
- /* Set up SOURCE rectangle */
- rc_intersect( &desk, &clip );
- rect = clip;
- rc_2xy( &clip, ( WORD *)&pxy[0] );
-
- if( obj == PFIRST( PopPtr ) )
- clip.g_y += gl_hchar;
-
- if( obj == PLAST( PopPtr ) )
- clip.g_y -= gl_hchar;
- rc_intersect( &desk, &clip );
- rc_2xy( &clip, ( WORD *)&pxy[4] );
-
- clip = rect;
- rc_2xy( &clip, ( WORD *)&xclip[0] );
- vs_clip( vhandle, 1, xclip );
- graf_mouse( M_OFF, 0L );
- vro_cpyfm( vhandle, 3, pxy, ( MFDB *)&location, ( MFDB *)&location );
- graf_mouse( M_ON, 0L );
-
- for( i = PFIRST( PopPtr ); i <= PLAST( PopPtr ); i++ )
- {
- if( ObType( i ) == G_STRING )
- {
- if( i == PFIRST( PopPtr ) && strchr( ObString( PFIRST( PopPtr )), UP_ARROW ))
- {
- ObString( i ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * PNUM( PopPtr ) ];
- continue;
- }
-
- if( i == PLAST( PopPtr ) && strchr( ObString( PLAST( PopPtr )), DOWN_ARROW ))
- {
- ObString( i ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * ( PNUM( PopPtr ) + 1 ) ];
- continue;
- }
-
- SetNormal( i );
- if( CmdState( PopPtr->CharPtr[j] ) & CHECKED )
- CheckObj( i );
-
- if( CmdState( PopPtr->CharPtr[j] ) & DISABLED )
- Disable( i );
-
- ObString( i ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * j++ ];
- }
- }
-
-
- if( obj == PFIRST( PopPtr ) )
- {
- rect = ObRect( obj );
- objc_offset( tree, obj, &rect.g_x, &rect.g_y );
- if( strchr( ObString( obj ), UP_ARROW ) )
- rect.g_y += gl_hchar;
- else
- {
- rect.g_h += gl_hchar;
- ObString( obj ) = &PTEXTBUFF( PopPtr )[ 0 ];
- if( !(CmdState( PopPtr->CharPtr[ 0 ] ) & DISABLED) )
- Select( obj );
-
- if( CmdState( PopPtr->CharPtr[ 0 ] ) & CHECKED )
- CheckObj( obj );
- }
- }
-
- if( obj == PLAST( PopPtr ) )
- {
- rect = ObRect( obj );
- objc_offset( tree, obj, &rect.g_x, &rect.g_y );
- rect.g_y -= gl_hchar;
- if( !strchr( ObString( obj ), DOWN_ARROW ) )
- {
- rect.g_h += gl_hchar;
- ObString( obj ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * ( PNUM( PopPtr ) - 1 )];
- if( !(CmdState( PopPtr->CharPtr[ PNUM( PopPtr ) - 1 ] ) & DISABLED) )
- Select( obj );
- if( CmdState( PopPtr->CharPtr[ PNUM( PopPtr ) - 1 ] ) & CHECKED )
- CheckObj( obj );
- }
- }
- Objc_draw( tree, ROOT, MAX_DEPTH, &rect );
- }
- else
- {
- if( ( obj == PFIRST( PopPtr ) ) &&
- ( !strchr( ObString( obj ), UP_ARROW )) &&
- ( !( CmdState( PopPtr->CharPtr[ 0 ] ) & DISABLED )) &&
- ( CmdFlag( PopPtr->CharPtr[0] ) == '~' )
- )
- ReturnFlag = TRUE;
-
- if( ( obj == PLAST( PopPtr ) ) &&
- ( !strchr( ObString( obj ), DOWN_ARROW ) ) &&
- ( !( CmdState( PopPtr->CharPtr[ PNUM( PopPtr ) - 1 ] ) & DISABLED )) &&
- ( CmdFlag( PopPtr->CharPtr[ PNUM( PopPtr ) - 1 ] ) == '~' )
- )
- ReturnFlag = TRUE;
- }
-
- if( DelayFlag )
- {
- Evnt_timer( CLICK_DELAY );
- DelayFlag = FALSE;
- }
-
- Graf_mkstate( &mk );
- }while( (( BSTATE == 1 ) || ( BREAL == 1 )) && ( xy_inrect( mk.x, mk.y, &xrect )));
-
- Evnt_button( 1, 1, 0, &mk ); /* Make sure we have an up button...*/
- return( ReturnFlag );
- }
-
-
-
-
- /* Pop_Blit()
- * ====================================================================
- * Blit from screen to buffer or buffer to screen for Popup Box redraws.
- *
- * IN: long *PopPtr: Pointer to memory buffer...
- * GRECT *clip: GRECT of clip blit area
- * int flag: 0 - blit from screen to buffer
- * 1 - blit from buffer to screen
- *
- * OUT: returns TRUE if successful, FALSE if failed.
- */
- BOOLEAN
- Pop_Blit( long *PopPtr, GRECT *xclip, int flag )
- {
- long location = 0L; /* SCREEN MFDB */
- int nplanes; /* Number of planes */
- unsigned long size; /* size of malloc */
- int pxy[8]; /* pxy for blit */
- GRECT clip;
- MFDB PopMFDB; /* buffer MFDB */
-
- clip = ( GRECT )*xclip;
- clip.g_x -= 2; /* adjust the clip area to take care of*/
- clip.g_y -= 2; /* the edges and shadows... */
- clip.g_w += 5;
- clip.g_h += 5;
- rc_2xy( &clip, ( WORD *)&pxy[0] );
- vs_clip( vhandle, 1, pxy );
-
- vq_extnd( vhandle, 1, work_out );
- nplanes = work_out[4];
-
- if( !flag ) /* screen to buffer blit*/
- {
- size = (unsigned long)(((long)clip.g_w + 7L )/8L) *
- (long)clip.g_h * (long)nplanes;
- size *= 2L;
- *PopPtr = (long )malloc( (unsigned long ) size );
- }
-
- if( !*PopPtr )
- return( FALSE );
-
- PopMFDB.fd_addr = (long *)*PopPtr; /* Setup the MFDB */
- PopMFDB.fd_w = clip.g_w;
- PopMFDB.fd_h = clip.g_h;
- PopMFDB.fd_wdwidth = ( clip.g_w + 15 ) / 16;
- PopMFDB.fd_stand = 0;
- PopMFDB.fd_nplanes = nplanes;
- PopMFDB.fd_r1 = PopMFDB.fd_r2 = PopMFDB.fd_r3 = 0;
-
- graf_mouse( M_OFF, 0L );
- if(!flag )
- {
- /* Screen to buffer blit */
- rc_intersect( &desk, &clip );
- rc_2xy( &clip, ( WORD *)&pxy[0] );
- pxy[4] = pxy[5] = 0;
- pxy[6] = clip.g_w - 1;
- pxy[7] = clip.g_h - 1;
- vro_cpyfm( vhandle, 3, pxy, ( MFDB *)&location, &PopMFDB );
- }
- else
- {
- /* Buffer to screen blit */
- rc_intersect( &desk, &clip );
- pxy[0] = pxy[1] = 0;
- pxy[2] = clip.g_w - 1;
- pxy[3] = clip.g_h - 1;
- rc_2xy( &clip, ( WORD *)&pxy[4] );
- vro_cpyfm( vhandle, 3, pxy, &PopMFDB, ( MFDB *)&location );
- if( *PopPtr )
- free( (long *)*PopPtr );
- *PopPtr = 0L;
- }
- graf_mouse( M_ON, 0L );
-
- return( TRUE );
- }
-
-
-
-
- /* UpArrowStatus()
- * =====================================================================
- */
- void
- UpArrowStatus( POP_PTR PopPtr )
- {
- OBJECT *tree;
- GRECT rect;
-
- tree = POBJECT( PopPtr );
-
- /* Check if we need to activate the UP ARROW or deactivate it */
- if( POFFSET( PopPtr ) ) /* display the UP ARROW */
- {
- if( !strchr( ObString( PFIRST( PopPtr )), UP_ARROW ) )
- {
- rect = ObRect( PFIRST( PopPtr ) );
- objc_offset( tree, PFIRST( PopPtr ), &rect.g_x, &rect.g_y );
-
- SetNormal( PFIRST( PopPtr ) );
- ObString( PFIRST( PopPtr ) ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * PNUM( PopPtr ) ];
- Objc_draw( tree, ROOT, MAX_DEPTH, &rect );
- }
- }
- else
- ObString( PFIRST( PopPtr ) ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * ( PNUM( PopPtr ) + 2 ) ];
- }
-
-
-
- /* DownArrowStatus()
- * =====================================================================
- */
- void
- DownArrowStatus( POP_PTR PopPtr )
- {
- OBJECT *tree;
- GRECT rect;
-
- tree = POBJECT( PopPtr );
-
- /* Check if we need to display the DOWN ARROW */
-
- /* DISPLAY the DOWN ARROW */
- if( ( POFFSET( PopPtr ) + PHEIGHT( PopPtr )) <= PNUM( PopPtr ) )
- {
- if( !strchr( ObString( PLAST( PopPtr )), DOWN_ARROW ) )
- {
- rect = ObRect( PLAST( PopPtr ) );
- objc_offset( tree, PLAST( PopPtr ), &rect.g_x, &rect.g_y );
-
- SetNormal( PLAST( PopPtr ) );
- ObString( PLAST( PopPtr ) ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * ( PNUM( PopPtr ) + 1 ) ];
- Objc_draw( tree, ROOT, MAX_DEPTH, &rect );
- }
- }
- else
- ObString( PLAST( PopPtr ) ) = &PTEXTBUFF( PopPtr )[ ( PWIDTH( PopPtr ) + 1 ) * ( PNUM( PopPtr ) + 2 ) ];
- }
-
-
-
-
- /* SetArrowClickDelay()
- * =====================================================================
- * Set the Click Delay before the menu starts to scroll.
- */
- void
- SetArrowClickDelay( long delay )
- {
- CLICK_DELAY = (( delay > 0L ) ? ( delay ) : ( INIT_CLICK_DELAY ));
- }
-
-
-
-
- /* CHECK FOR KEYCODES...
- * =====================================================================
- * Checks the string for the keystrings below so that they may be
- * subtracted from the length of the string for calculation purposes.
- */
-
- /* CheckForCtrl()
- * =====================================================================
- * Looks for a ^ in the string.
- * Returns a pointer to the string where it starts.
- */
- char
- *CheckForCtrl( char *text )
- {
- return( strchr( text, '^' ) );
- }
-
-
-
- /* CheckForAlt()
- * =====================================================================
- * Looks for a & in the string.
- * Returns a pointer to the string where it starts.
- */
- char
- *CheckForAlt( char *text )
- {
- return( strchr( text, '&' ) );
- }
-
-
- /* CheckForCapKey()
- * =====================================================================
- * Looks for a / in the string.
- * Returns a pointer to the string where it starts.
- */
- char
- *CheckForCapKey( char *text )
- {
- return( strchr( text, '|' ) );
- }
-
-
- /* CheckForCmdKey()
- * =====================================================================
- * Looks for a $ in the string.
- * Returns pointer to the string where it starts.
- */
- char
- *CheckForCmdKey( char *text )
- {
- return( strchr( text, '$' ) );
- }
-
-
- /* CheckForDisable()
- * =====================================================================
- * Looks for a @ in the string.
- * Returns TRUE if found, FALSE if not.
- */
- BOOLEAN
- CheckForDisable( char *text )
- {
- return( ( BOOLEAN )strchr( text, '@' ) );
- }
-
-
- /* CheckForMenuCheck()
- * =====================================================================
- * Looks for a ! in the string.
- * Returns TRUE if found, FALSE if not.
- */
- BOOLEAN
- CheckForMenuCheck( char *text )
- {
- return( ( BOOLEAN )strchr( text, '!' ) );
- }
-
-
-
- /* CheckForSubMenu()
- * =====================================================================
- * Looks for a ~ in the string.
- * Returns the pointer to the string where it starts.
- */
- char
- *CheckForSubMenu( char *text )
- {
- return( strchr( text, '~' ) );
- }
-
-
-
- /* CheckForFuncKey()
- * =====================================================================
- * Looks for a # in the string.
- * Returns the pointer to the string if found.
- */
- char
- *CheckForFuncKey( char *text )
- {
- return( strchr( text, '#' ) );
- }
-
-
- /* CheckForDuplicate()
- * =====================================================================
- * Looks for a * in the string.
- * Returns TRUE if found, FALSE if not.
- * The length of the string to compare should be ZERO. :-)
- * This is because this string will be the width of the menu.
- */
- BOOLEAN
- CheckForDuplicate( char *text )
- {
- return( ( BOOLEAN )strchr( text, '*' ));
- }
-
-
-
- /* CheckForKeyCodes()
- * =====================================================================
- * Checks the text string for various keycodes and subtracts
- * an appropriate amount from the length if any are found.
- * For many of these, there should only be one of them.
- * We then ADD back in the amount of ACTUAL text usage this item
- * would take. IE: a Function Key can be F10 so 3 characters...
- * or a CmdKey can be the letters: 'DEL' 3 characters added.
- * This will also fill up the CMDCHAR structures.
- */
- long
- CheckForKeyCodes( POP_PTR PopPtr, char *text, int num_entry )
- {
- long length;
- long num;
-
- length = strlen( text );
-
- if( strchr( text, '@' ))
- length -= 1L;
-
- if( strchr( text, '!' ))
- length -= 1L;
-
- switch( CmdFlag( PopPtr->CharPtr[ num_entry ] ) )
- {
- case '^':
- case '~':
- case '#':
- case '&': length += 1L;
- break;
-
- case '|': length += 2L;
- break;
-
- case '$': switch( CmdHotKey( PopPtr->CharPtr[ num_entry ] ) )
- {
- case 'h': /* Home */
- strcpy( &CmdText[0], KeyText[0] );
- break;
-
- case 'H': /* HELP */
- strcpy( &CmdText[0], KeyText[1] );
- break;
-
- case 'U': /* Undo */
- strcpy( &CmdText[0], KeyText[2] );
- break;
-
- case 'E': /* Escape*/
- strcpy( &CmdText[0], KeyText[3] );
- break;
-
- case 'I': /* Insert */
- strcpy( &CmdText[0], KeyText[4] );
- break;
-
- case 'C': /* Clr */
- strcpy( &CmdText[0], KeyText[5] );
- break;
-
- case 'D': /* Delete */
- strcpy( &CmdText[0], KeyText[6] );
- break;
-
- case 'T': /* TAB */
- strcpy( &CmdText[0], KeyText[7] );
- break;
-
- case 'e': /* ENTER */
- strcpy( &CmdText[0], KeyText[8] );
- break;
-
- case 'R': /* RETURN */
- strcpy( &CmdText[0], KeyText[9] );
- break;
-
- default: CmdText[0] = '\0';
- break;
- }
- num = strlen( &CmdText[0] );
- num = num - 2 + 1; /* minus the ctrl codes + 1 space */
- length += num;
- break;
-
- case '*': length = 1L;
- break;
-
- default:
- break;
- }
- return( length );
- }
-
- /* END OF KEYCODE CHECKING
- * =====================================================================
- */
-
-
- /* CONTROLLING THE APPEARANCE OF ITEMS
- * =====================================================================
- */
-
- /* SetHeight()
- * =====================================================================
- * Set the height of the Menu.( in chars ).
- */
- void
- SetHeight( int MenuID, int Height )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
-
- if( Height > 0 )
- PHEIGHT( PopPtr ) = Height;
- }
-
-
-
- /* SetNumItems()
- * =====================================================================
- * Set the number of items in the menu. This can be used to display
- * fewer items than the InsertMenu() call created.
- */
- void
- SetNumItems( int MenuID, int NumItems )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- if( NumItems > 0 )
- PNUM( PopPtr ) = NumItems;
- }
-
-
-
- /* CheckItem()
- * =====================================================================
- * Places or removes a check mark at the left of a menu item.
- */
- void
- CheckItem( int MenuID, int item, BOOLEAN check )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- if( check )
- CmdState( PopPtr->CharPtr[ item ] ) |= CHECKED;
- else
- CmdState( PopPtr->CharPtr[ item ] ) &= ~CHECKED;
- }
-
-
-
- /* DisableItem()
- * =====================================================================
- * Disables a menu item.
- */
- void
- DisableItem( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- CmdState( PopPtr->CharPtr[ item ] ) |= DISABLED;
- }
-
-
-
- /* EnableItem()
- * =====================================================================
- * Enables a menu item.
- */
- void
- EnableItem( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- CmdState( PopPtr->CharPtr[ item ] ) &= ~DISABLED;
- }
-
-
- /* SetItemCmd()
- * =====================================================================
- * This can be used to attach a submenu to a menu item.
- * You must still call 'SetSubMenuID()' tell the popups which
- * submenu to attach. Otherwise, this is a great way to change
- * the keyboard shortcuts. Use SetItemMark() to change the
- * keyboard shortcuts AFTER setting the type with the SetItemCmd().
- */
- void
- SetItemCmd( int MenuID, int item, char cmd )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- CmdFlag( PopPtr->CharPtr[ item ] ) = cmd;
- }
-
-
- /* GetItemCmd()
- * =====================================================================
- * This can be used to determine if a submenu is attached to
- * this menu item. It returns the current command.
- * RETURNS:
- * '~' == SubMenu for example
- */
- char
- GetItemCmd( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- return( CmdFlag( PopPtr->CharPtr[ item ] ) );
- }
-
-
-
- /* SetSubMenuID()
- * =====================================================================
- * This can be used to change the ID of the submenu associated
- * with a menu item. Nothing happens of course, if the menu_item
- * does not have a submenu CMD.
- */
- void
- SetSubMenuID( int MenuID, int item, int ID )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- if( GetItemCmd( MenuID, item ) == '~' )
- CmdSubMenu( PopPtr->CharPtr[ item ] ) = ID;
- }
-
-
- /* GetSubMenuID()
- * =====================================================================
- * This can be used to get the ID of the submenu associated
- * with the menu item. Course, the item must HAVE a submenu in
- * the first place. Use GetItemCmd to determine if there is a
- * submenu.
- * RETURN: -1 if there is no submenu.
- */
- int
- GetSubMenuID( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- if( GetItemCmd( MenuID, item ) == '~' )
- return( CmdSubMenu( PopPtr->CharPtr[ item ] ));
- else
- return( -1 );
- }
-
-
- /* SetItemMark()
- * =====================================================================
- * This can be used to change the CMDKEY of a keyboard shortcut.
- * The command type itself is set with SetItem(). All except function
- * keys and submenus.
- */
- void
- SetItemMark( int MenuID, int item, char key )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- CmdHotKey( PopPtr->CharPtr[ item ] ) = key;
- }
-
-
-
- /* GetItemMark()
- * =====================================================================
- * This can be used to see what the CMDKEY shortcut is associated with
- * the menu item. All except function keys and submenus.
- */
- char
- GetItemMark( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- return( CmdHotKey( PopPtr->CharPtr[ item ] ) );
- }
-
-
- /* SetFuncMark()
- * =====================================================================
- * This can be used to set the Functio key # that is to be
- * associated with the menu item.
- */
- void
- SetFuncMark( int MenuID, int item, int num )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- CmdFuncKey( PopPtr->CharPtr[ item ] ) = num;
- }
-
-
-
-
- /* GetFuncMark()
- * =====================================================================
- * This can be used to get wot function key # is associated with
- * the menu item.
- */
- int
- GetFuncMark( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- return( CmdFuncKey( PopPtr->CharPtr[ item ] ) );
- }
-
-
-
- /* SetItem()
- * =====================================================================
- * Set the Menu item string.
- * 1) The string must not exceed the original string length.
- * 2) Meta characters will be printed as regular text.
- * 3) If the string is longer than the original, then
- * the new string will be truncated.
- */
- void
- SetItem( int MenuID, int item, char *text )
- {
- POP_PTR PopPtr;
- int count;
- char *txtptr;
- long length;
- long length2;
-
- PopPtr = GetMenuPtr( MenuID );
-
- txtptr = PTEXT( PopPtr );
- if( txtptr )
- {
- for( count = 0; count < item; count++ )
- {
- length = strlen( txtptr );
- txtptr += ( length + 1 );
- }
- /* we've reached the text area that we want. */
- length = strlen( txtptr );
- strncpy( txtptr, text, length );
- length2 = strlen( txtptr );
- for( count = (int)length2; count < length; count++ )
- strcat( txtptr, " " );
- }
- }
-
-
-
- /* GetItem()
- * =====================================================================
- * Returns the string associated with the menu item WITHOUT
- * the meta characters.
- */
- char
- *GetItem( int MenuID, int item )
- {
- POP_PTR PopPtr;
- int count;
- char *txtptr;
- char *sptr;
- char *dptr;
- long length;
-
- PopPtr = GetMenuPtr( MenuID );
-
- txtptr = PTEXT( PopPtr );
- if( txtptr )
- {
- for( count = 0; count < item; count++ )
- {
- length = strlen( txtptr );
- txtptr += ( length + 1 );
- }
-
- /* we've reached the text area that we want. */
- length = strlen( txtptr );
- sptr = txtptr;
- dptr = &TempString[0];
-
- while( *sptr )
- {
-
- switch( *sptr )
- {
- case '*':
- case '@':
- case '!': sptr++;
- break;
-
- case '^':
- case '~':
- case '&':
- case '$':
- case '|': sptr += 2;
- break;
-
- case '#': sptr += 2;
- length = strlen( sptr );
- if( length > 1 )
- sptr++;
- break;
-
- default: *dptr++ = *sptr++;
- break;
- }
- }
- *dptr = '\0';
- return( ( char *)&TempString[0] );
- }
- return( (char *)NULL );
- }
-
-
-
- /* SetStartItem()
- * =====================================================================
- * This can be used to Set the start item on a submenu. This will
- * work of course, on the main menu too.
- */
- void
- SetStartItem( int MenuID, int item )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- PopUpItem( PopPtr ) = item;
- }
-
-
-
- /* GetStartItem()
- * =====================================================================
- * This can be used to get the start item in a submenu. Or at least
- * wot it currently thinks it is...
- */
- int
- GetStartItem( int MenuID )
- {
- POP_PTR PopPtr;
-
- PopPtr = GetMenuPtr( MenuID );
- return( PopUpItem( PopPtr ) );
- }
-
-
-
- /* END OF APPEARANCE OF ITEMS
- * =====================================================================
- */
-
-
- /* SUBMENU HANDLING
- * =====================================================================
- */
-
-
-
- /* DoSubMenu()
- * =====================================================================
- * Display the submenu if necessary...
- *
- */
- POP_PTR
- DoSubMenu( POP_PTR PopPtr, int obj )
- {
- int num;
- POP_PTR SubPopPtr;
- GRECT SubRect;
- int MenuID;
- OBJECT *tree;
- int curx;
-
-
- ActiveTree( POBJECT( PopPtr ) );
- SubPopPtr = ( POP_PTR )NULL;
- if( obj != -1 )
- {
- num = FindNum( PopPtr, obj );
- if( CmdFlag( PopPtr->CharPtr[ num ] ) == '~' )
- {
- SubRect = ObRect( obj );
- objc_offset( tree, obj, &SubRect.g_x, &SubRect.g_y );
-
- MenuID = CmdSubMenu( PopPtr->CharPtr[ num ] );
- SubPopPtr = GetMenuPtr( MenuID );
- /* Displays faster if drawn on a byte boundary.*/
- curx = SubRect.g_x + SubRect.g_w -1 - gl_wchar;
- curx = (( curx + 7 )/8)*8;
- if( !ShowSubMenu( MenuID, curx, SubRect.g_y, &SubRect ))
- SubPopPtr = ( POP_PTR )NULL;
- }
- }
- return( SubPopPtr );
- }
-
-
-
-
- /* ShowSubMenu()
- * =====================================================================
- * Display the Initial Submenu
- * RETURN: TRUE - AOK
- * FALSE - Memory allocation error.
- */
- BOOLEAN
- ShowSubMenu( int MenuID, int xpos, int ypos, GRECT *rect )
- {
- POP_PTR PopPtr;
- int max_height;
-
- PopPtr = GetMenuPtr( MenuID );
-
- PPREV( PopPtr ) = ( POP_PTR )NULL;
-
- PXPOS( PopPtr ) = xpos;
- PYPOS( PopPtr ) = ypos;
-
- /* Take care of height of menu */
- if( PHEIGHT( PopPtr ) > PNUM( PopPtr ) )
- PHEIGHT( PopPtr ) = PNUM( PopPtr );
-
- /* Limit Height to Height of screen - ( 2 * gl_hchars ) */
- max_height = yres - ( 2 * gl_hchar );
- while( ( PHEIGHT( PopPtr ) * gl_hchar ) > max_height )
- PHEIGHT( PopPtr ) -= 1;
-
- PIX_HEIGHT( PopPtr ) = ( PHEIGHT( PopPtr ) * gl_hchar );
-
- /* Take care of the width of the menu here...*/
- PTEXTBUFFSIZE( PopPtr ) = CalcTextBufferSize( PopPtr );
- PIX_WIDTH( PopPtr ) = ( PWIDTH( PopPtr ) * gl_wchar );
-
- AdjustToScreen( PopPtr, xpos, ypos, rect, TRUE, FALSE );
-
- if( Pop_Blit( (long *)&PMEM( PopPtr ), &PObRect( PopPtr ), 0 ) )
- {
- if( Build_Objects( PopPtr ))
- return( TRUE );
- }
- return( FALSE );
- }
-
-
-
-
- /* HideSubMenu()
- * =====================================================================
- * Hides the Submenu and free's any memory that it malloc'ed.
- */
- void
- HideSubMenu( POP_PTR PopPtr )
- {
- Pop_Blit( (long *)&PMEM( PopPtr ), &PObRect( PopPtr ), 1 );
-
- if( POBJECT( PopPtr ) )
- free( POBJECT( PopPtr ) );
-
- if( PTEXTBUFF( PopPtr ) )
- free( PTEXTBUFF( PopPtr ) );
-
- POBJECT( PopPtr ) = ( OBJECT *)NULL;
- PTEXTBUFF( PopPtr ) = ( char *)NULL;
- }
-
-
-
-
- /* EvntSubMenu()
- * ====================================================================
- * Submenu Handling...
- * IN: POP_PTR PopPtr
- * OUT: long -1L No Menu Items selected.
- * -2L We've rentered the submenu ( won't get to user )
- * High Word Low Word
- * --------- --------
- * Menu ID -1 Selected Disabled Item
- * Menu ID Menu Item Selected Menu Item.
- */
- long
- EvntSubMenu( POP_PTR PopPtr )
- {
- long result; /* Result to return with... */
- MRETS mk; /* mouse structures */
- int oldobj; /* old object */
- int done = FALSE; /* Done flag to return.. */
- int obj; /* object mouse is over... */
- int event; /* Mouse button event flag */
- /* TRUE = event occurred */
- POP_PTR SubPopPtr; /* Pointer to Submenu... */
- POP_PTR TempPtr; /* Temporary Submenu Pointer */
-
- GRECT SubRect; /* ObRect of Submenu */
- GRECT TempRect; /* Temp ObRect */
-
- GRECT wall; /* ObRect for boundary checks */
- GRECT BoxRect; /* ObRect for boundary checks */
- GRECT DragRect; /* ObRect for Drag boundary */
-
- OBJECT *tree; /* Object tree declaration */
- int Action; /* Action that is occurring */
- int num; /* temp number storage */
- int ActiveObj; /* Current Active Object */
-
- long CurTimeHz; /* Time in 200Hz...*/
- BOOLEAN MenuDelayFlag; /* Display Submenu Delay in effect*/
- BOOLEAN MenuDragFlag; /* Drag Submenu Delay in effect */
- BOOLEAN DragStart; /* Start Drag Submenu Delay... */
- int MenuObject; /* Object to start the timer on*/
- int OldY; /* Old Y pos for a drag */
- int OldX;
-
- ActiveTree( POBJECT( PopPtr ) );
- Graf_mkstate( &mk );
-
- oldobj = -1;
- obj = objc_find( tree, ROOT, MAX_DEPTH, mk.x, mk.y );
- SubPopPtr = ( POP_PTR )NULL;
- BoxRect = ObRect( ROOT );
- result = -1L;
- OldY = 0;
- OldX = 0;
-
- MenuDelayFlag = FALSE;
- MenuDragFlag = FALSE;
- DragStart = FALSE;
- ActiveObj = -1;
- BSTATE = BREAL = 0;
-
- do
- {
- if( obj != -1 )
- {
- if( obj != oldobj )
- {
- wall = ObRect( obj );
- objc_offset( tree, obj, &wall.g_x, &wall.g_y );
- if( SubPopPtr )
- {
- PPREV( SubPopPtr ) = ( POP_PTR )NULL;
- HideSubMenu( SubPopPtr );
- SubPopPtr = ( POP_PTR )NULL;
- MenuDragFlag = FALSE;
- MenuDelayFlag = FALSE;
- DragStart = FALSE;
- ActiveObj = -1;
- }
- if(( oldobj != -1 ) && ( oldobj != obj ))
- deselect( tree, oldobj );
-
- if( ( obj == PFIRST( PopPtr ) && strchr( ObString( obj ), UP_ARROW ) ) ||
- ( obj == PLAST( PopPtr ) && strchr( ObString( obj ), DOWN_ARROW ) )
- )
- deselect( tree, obj );
- else
- {
- if( !IsDisabled( obj ) )
- {
- select( tree, obj );
-
- if( ( num = FindNum( PopPtr, obj )) != -1 )
- {
- if( CmdFlag( PopPtr->CharPtr[ num ] ) == '~' )
- {
- Supexec( GetTimeHz );
- CurTimeHz = TimeInHz;
- MenuDelayFlag = TRUE;
- MenuDragFlag = FALSE;
- DragStart = FALSE;
- MenuObject = obj;
- }
- }
- }
- }
- }
- }
- else
- {
- if(( oldobj != -1 ) && ( oldobj != obj ) )
- {
- deselect( tree, oldobj );
- }
- }
- oldobj = obj;
-
- Graf_mkstate( &mk );
- OldY = mk.y;
- OldX = mk.x;
- do
- {
- BSTATE = 0;
- if( MenuDragFlag )
- {
- if( ( !xy_inrect( mk.x, mk.y, &wall ) ||
- ( SubPopPtr && xy_inrect( mk.x, mk.y, &SubRect ) ))
- )
- {
- if( DragStart )
- {
- Supexec( GetTimeHz );
- CurTimeHz = TimeInHz;
- DragStart = FALSE;
- DragRect.g_x = mk.x;
- DragRect.g_y = SubRect.g_y;
- DragRect.g_h = SubRect.g_h;
-
- OldX = mk.x;
- OldY = mk.y;
-
- if( mk.x <= SubRect.g_x )
- {
- DragRect.g_w = SubRect.g_w + ( SubRect.g_x - DragRect.g_x );
- }
- else
- {
- DragRect.g_x = SubRect.g_x;
- DragRect.g_w = mk.x - SubRect.g_x + 1;
- }
- }
-
- if( SubPopPtr )
- {
- if( !DragStart )
- {
- Supexec( GetTimeHz );
- if( ( TimeInHz - CurTimeHz ) >= SUBDRAG_DELAY )
- MenuDragFlag = FALSE;
-
- if( !xy_inrect( mk.x, mk.y, &DragRect ) ||
- (xy_inrect( mk.x, mk.y, &DragRect ) &&
- ( mk.x == OldX ) &&
- ( mk.y != OldY )
- )
- )
- MenuDragFlag = FALSE;
- else
- {
- DragRect.g_x = mk.x;
- if( mk.x <= SubRect.g_x )
- {
- DragRect.g_w = SubRect.g_w + ( SubRect.g_x - DragRect.g_x );
- }
- else
- {
- DragRect.g_x = SubRect.g_x;
- DragRect.g_w = mk.x - SubRect.g_x + 1;
- }
- }
- }
-
- /* We're in the new submenu...*/
- if( xy_inrect( mk.x, mk.y, &SubRect ) )
- {
- Action = 0;
- MenuDragFlag = FALSE;
- break;
- }
- MenuDelayFlag = FALSE;
- }
- }
- }
- else
- {
- BoxRect = ObRect( ROOT );
- if( xy_inrect( mk.x, mk.y, &BoxRect ) )
- {
- /* We're in our current submenu still
- * but we might be in a new menu item.
- */
- Action = 1;
- break;
- }
- else
- {
- /* Checking to see if we're in any of the previous menus */
- TempPtr = PPREV( PopPtr );
- while( TempPtr )
- {
- /* We're in a previous submenu or root */
- TempRect = PObRect( TempPtr );
- if( xy_inrect( mk.x, mk.y, &TempRect ) )
- {
- Action = 2;
- goto abort;
- }
- TempPtr = PPREV( TempPtr );
- }
- }
-
- /* if we reach here, we're outside of all the rectangles.*/
- if( SubPopPtr )
- {
- HideSubMenu( SubPopPtr );
- PPREV( SubPopPtr ) = ( POP_PTR )NULL;
- SubPopPtr = ( POP_PTR )NULL;
- ActiveObj = -1;
- MenuDragFlag = FALSE;
- MenuDelayFlag = FALSE;
- }
-
- if( oldobj != -1 )
- {
- deselect( tree, oldobj );
- oldobj = obj = -1;
- }
- }
- Action = -1;
-
- OldX = mk.x;
- OldY = mk.y;
- Evnt_timer( 0L ); /* Kludge to put in a delay
- * so that we can get a new mouse
- * x,y with > 1 pixel difference
- */
- Graf_mkstate( &mk );
- }while( !BSTATE );
- abort:
- /* we've exited due to a button click, OR
- * we've entered one of the rectangles.
- * Let's see wot we've got.
- * If Action == -1, then the user clicked outside of
- * ANY rectangles and we should just exit and close
- * down all of the menus.
- */
- Graf_mkstate( &mk );
- obj = objc_find( tree, ROOT, MAX_DEPTH, mk.x, mk.y );
-
- /* Fix for when the submenu is displayed and we click
- * on its title to exit.
- */
- if( xy_inrect( mk.x, mk.y, &wall ) &&
- SubPopPtr && MenuDragFlag && ( BSTATE == 1 ) )
- Action = 1;
-
- event = FALSE;
- switch( Action )
- {
- case 0: /* Entered the New Submenu, if there is one */
- if( SubPopPtr )
- {
- /* need to check wot is returned...*/
- result = EvntSubMenu( SubPopPtr );
- if(( result == -1L ) || ( result != -2L ) )
- {
- obj = -1;
- event = TRUE;
- goto leave;
- }
- TempPtr = SubPopPtr;
- PPREV( SubPopPtr ) = ( POP_PTR )NULL;
- HideSubMenu( SubPopPtr );
- SubPopPtr = ( POP_PTR )NULL;
- MenuDragFlag = FALSE;
- MenuDelayFlag = FALSE;
-
- Graf_mkstate( &mk );
- obj = objc_find( tree, ROOT, MAX_DEPTH, mk.x, mk.y );
- num = FindNum( PopPtr, obj );
- if( ( obj != -1 ) && ( ActiveObj == obj ) &&
- ( CmdFlag( PopPtr->CharPtr[ num ] ) == '~' ) &&
- ( GetMenuPtr( CmdSubMenu( PopPtr->CharPtr[ num ] )) == TempPtr )
- )
- {
- if( !IsSelected( obj ) )
- select( tree, obj );
-
- if( ( SubPopPtr = DoSubMenu( PopPtr, obj )) != ( POP_PTR )NULL )
- {
- ActiveObj = obj;
- SubRect = PObRect( SubPopPtr );
- ActiveTree( POBJECT( PopPtr ) );
- PPREV( SubPopPtr ) = PopPtr;
- MenuDragFlag = TRUE;
- DragStart = TRUE;
- wall = ObRect( obj );
- objc_offset( tree, obj, &wall.g_x, &wall.g_y );
- }
- }
- else
- ActiveObj = -1;
- }
- break;
-
- case 1: /* we are still in the current submenu...*/
- /* The user click on an arrow button? */
- if( (( BSTATE == 1 ) || ( BREAL == 1 )) && (( obj == PFIRST( PopPtr) && strchr( ObString( obj ), UP_ARROW )) ||
- (( obj == PLAST( PopPtr ) ) && strchr( ObString( obj ), DOWN_ARROW ))
- ))
- {
- if( Pop_Arrow( PopPtr, obj ) )
- {
- if( ( num = FindNum( PopPtr, obj )) != -1 )
- {
- if( CmdFlag( PopPtr->CharPtr[ num ] ) == '~' )
- {
- Supexec( GetTimeHz );
- CurTimeHz = TimeInHz;
- MenuDelayFlag = TRUE;
- MenuObject = obj;
- }
- }
- }
- }
- else
- {
- if( !SubPopPtr && MenuDelayFlag && ( MenuObject == obj ))
- {
- Supexec( GetTimeHz );
- if( ( TimeInHz - CurTimeHz ) >= SUBMENU_DELAY )
- {
- MenuDelayFlag = FALSE;
- if( !IsSelected( obj ) )
- select( tree, obj );
-
- if( ( SubPopPtr = DoSubMenu( PopPtr, obj )) != ( POP_PTR )NULL )
- {
- ActiveObj = obj;
- SubRect = PObRect( SubPopPtr );
- ActiveTree( POBJECT( PopPtr ) );
- PPREV( SubPopPtr ) = PopPtr;
- MenuDragFlag = TRUE;
- DragStart = TRUE;
- wall = ObRect( obj );
- objc_offset( tree, obj, &wall.g_x, &wall.g_y );
- }
-
- }
- }
- else
- MenuDelayFlag = FALSE;
-
- /* we are just in another menu item.
- * If a submenu was displayed, hide it.
- */
- if( SubPopPtr && ( ActiveObj != obj ) )
- {
- PPREV( SubPopPtr ) = ( POP_PTR )NULL;
- HideSubMenu( SubPopPtr );
- SubPopPtr = ( POP_PTR )NULL;
- MenuDragFlag = FALSE;
- MenuDelayFlag = FALSE;
- ActiveObj = -1;
- }
-
- /* if the buttons are down, they clicked on something*/
- if(( BSTATE == 1 ) || ( BREAL == 1 ))
- {
- event = TRUE;
-
- obj = objc_find( tree, ROOT, MAX_DEPTH, mk.x, mk.y );
-
- CurMenu = PMENUID( PopPtr );
- CurObject = obj;
- result = 0L;
- }
- }
- break;
-
- case 2: /* we have entered a previous submenu... */
- result = -2L;
-
- case -1: /* we have clicked outside of ANY submenus.*/
- if( Action == -1 )
- {
- /* don't exit if not a left button click */
- if( BSTATE != 1 )
- goto leave;
- }
- CurMenu = CurObject = -1;
- default: event = TRUE;
- obj = -1;
- break;
- }
-
- leave:
- if( event )
- {
- if( SubPopPtr )
- {
- PPREV( SubPopPtr ) = ( POP_PTR )NULL;
- HideSubMenu( SubPopPtr );
- SubPopPtr = ( POP_PTR )NULL;
- }
- done = TRUE;
- }
-
- }while( !done );
-
-
- if(( obj != -1 ) && ( result != -2L ) && ( result != -1L ) )
- {
- result = 0L;
- result = ( int )PMENUID( PopPtr );
- result = ( result << 16L );
-
- if( !IsDisabled( obj ) )
- obj = FindNum( PopPtr, obj );
- else
- obj = -1;
- result |= ( obj & 0x0000FFFF );
- }
- return( result );
- }
-
-
-
- /* FindNum()
- * =====================================================================
- * Given the object #, find the adjusted index of the menu item.
- */
- int
- FindNum( POP_PTR PopPtr, int obj )
- {
- int offset;
-
- offset = POFFSET( PopPtr );
- if( offset > 0 )
- offset -= 1;
- obj -= PFIRST( PopPtr );
- obj += offset;
- return( obj );
- }
-
-
-
-
- /* MenuChoice()
- * =====================================================================
- * Returns the CURRENT values of the menu and object clicked on.
- * Call ONLY after the PopMenuSelect() call has returned.
- */
- long
- MenuChoice( void )
- {
- long value;
- POP_PTR PopPtr;
- int obj;
-
- value = 0L;
- value = ( int )CurMenu;
- value = ( value << 16L );
-
- if( CurMenu != -1 )
- {
- PopPtr = GetMenuPtr( CurMenu );
- obj = FindNum( PopPtr, CurObject );
- }
- else
- obj = -1;
- value |= ( obj & 0x0000FFFF );
- return( value );
- }
-
-
- /* END OF SUBMENU ROUTINES
- * =====================================================================
- */
-
-
-
-
-
- /* SUBMENU DELAY ROUTINES
- * =====================================================================
- */
-
- /* GetTimeHz()
- * =====================================================================
- * Gets the System time in 20ms ticks.
- */
- long
- GetTimeHz( void )
- {
- long *ptr;
-
- ptr = ( long *)0x4BA;
- TimeInHz = *ptr;
- return( TimeInHz );
- }
-
-
-
-
- /* SetSubMenuDelay()
- * =====================================================================
- * Sets the length of time before a submenu appears as the user drags
- * the pointer thru a menu list.
- * The Units are in # of Milliseconds. ( 1000 = 1 second ).
- */
- void
- SetSubMenuDelay( long ms )
- {
- if( ms < 0L )
- ms = INIT_DISPLAY_DELAY;
- if( ms )
- ms /= 20L;
- SUBMENU_DELAY = ms;
- }
-
-
-
-
- /* SetSubDragDelay()
- * =====================================================================
- * Sets the length of time the user has to drag diagonally, a pointer
- * to an active submenu before the submenu closes.
- */
- void
- SetSubDragDelay( long ms )
- {
- if( ms < 0L )
- ms = INIT_DRAG_DELAY;
- if( ms )
- ms /= 20L;
- SUBDRAG_DELAY = ms;
- }
-
-
- /* END OF SUBMENU DELAY ROUTINES
- * =====================================================================
- */
-
-
-
- /* AdjustToScreen()
- * =====================================================================
- * Takes the Submenu XY and adjusts it so that it fits within
- * the screen area still. If there is an optional object, we will
- * adjust around that.
- * If we DO adjust, we'll try to get it on a byte boundary.
- * BOOLEAN byte_flag - a flag to align the xpos on a byte boundary.
- * - TRUE - YES!
- * - NOTE: if the menu does not want byte adjusting
- * BUT it is off the screen, we will adjust
- * it back ONTO the screen on a byte boundary.
- * We just won't byte_adjust it if its already
- * on the screen in its entirety.
- * BOOLEAN Display_Flag; - a flag for vertical alignment of submenus.
- * - When the submenu extends BELOW the bottom
- * of the screen, there are 2 ways to adjust
- * the menu.
- * 1)Adjust by displaying the menu upwards vertically
- * from the rectangle button.
- * 2)Adjust by moving the menu upwards 1 gl_hchar
- * at a time until the menu does not extend
- * below the screen boundary.
- * TRUE - Use Version 1
- * FALSE - Use Version 2
- */
- void
- AdjustToScreen( POP_PTR PopPtr, int xpos, int ypos, GRECT *rect, BOOLEAN byte_flag, BOOLEAN Display_Flag )
- {
- int temp;
- int position;
-
- /* Handle the X Coordinate Adjustments...
- *------------------------------------------------------------------
- */
- temp = xpos + PIX_WIDTH( PopPtr );
- if( temp > ( xres - 4 ))
- {
- if( !byte_flag )
- {
- temp -= ( xres - 4 );
- temp = ( temp + gl_wchar )/gl_wchar;
- temp *= gl_wchar;
- xpos -= temp;
- }
- else
- {
- xpos = rect->g_x - PIX_WIDTH( PopPtr );
- xpos = ( xpos + gl_wchar )/gl_wchar;
- xpos *= gl_wchar;
- }
- }
- else
- {
- if( byte_flag )
- {
- xpos = ( xpos + ( gl_wchar - 1 ) )/gl_wchar;
- xpos *= gl_wchar;
- }
- }
-
- /* Handle X limits < 0 */
- while( xpos <= 0 )
- xpos += gl_wchar;
- PXPOS( PopPtr ) = xpos;
-
-
- /* Handle the Y Coordinate Adjustments...
- *------------------------------------------------------------------
- */
- /* Calculates the Position so that the submenu start item
- * is adjacent to the button that activated it.
- */
- position = ( PopUpItem( PopPtr ) + ( PNUM( PopPtr ) > PHEIGHT( PopPtr ) )) / PHEIGHT( PopPtr );
- if( position )
- {
- position = PopUpItem( PopPtr );
- temp = PNUM( PopPtr ) - PHEIGHT( PopPtr ) + 1;
-
- if( position >= temp )
- position = temp;
- position -= 1;
- }
- position = PopUpItem( PopPtr ) - position;
- ypos = ypos - ( position * gl_hchar );
-
-
- /* Calculates a new position if the submenu exceeds the
- * height of the screen.
- */
- temp = ypos + PIX_HEIGHT( PopPtr );
- if( temp > ( yres - 4 ))
- {
- if( Display_Flag )
- ypos = ypos - ( (PHEIGHT( PopPtr ) - position - 1 )* gl_hchar );
- else
- {
- do
- {
- ypos -= gl_hchar;
- temp = ypos + PIX_HEIGHT( PopPtr );
- }while( temp > ( yres - 4 ) );
- }
- }
-
- while( ypos <= ( gl_hchar + ( gl_hchar/2 ) ))
- ypos += gl_hchar;
-
- PYPOS( PopPtr ) = ypos;
- }
-
-
-
-
- /* WaitForUpButton()
- * =====================================================================
- * Waits for an up button.
- */
- void
- WaitForUpButton( void )
- {
- MRETS mk;
-
- do
- {
- Graf_mkstate( &mk );
- }while( mk.buttons );
- }
-
-
-