[comp.sys.atari.st] Event Multi & Right Mouse Buttons Example

achowe@tiger.waterloo.edu (anthony howe) (10/18/89)

About 2 years ago this question came up on the net. I still have a hard copy
of the post which I used to develop the following tit-bit on detecting the
right mouse button. Anyways it boiled down to this...

"Install your own button handler in assembler. The button value comes in
d0, save it out to a nice place, then change it to a left click no matter
what, and install the routine using  vex_butv()."  - Kenneth Soohoo

Long exmaple to follow......

-------->8------- EXAMPLE ------------>8--------------
;***
;***    Button Handler
;***
;
;   Trap the mouse button state because the current handler kills or ignores
;   the right mouse button. Once the state is stored chain to the old handler.

            .bss
            .globl      _OldButHandler
            .comm       _OldButHandler, 4
            .globl      _ButState
            .comm       _ButState, 2
            .text       
            .globl      _NewButHandler
_NewButHandler:
            tst.w       d0
            beq.s       newbut1
            move.w      d0, _ButState
            move.w      #1, d0
newbut1:
            move.l      _OldButHandler, -(sp)
            rts         

;***    end of Button Handler

------------->8--------- C portion ------------>8----------
/*
        This example code is ripped straight out of a game I'm writing. There
        is more here than necessary. But for the curious here is a good
        portion of setting up a GEM application. The routines to look at
        in connection with button events are: init() - right at the end,
        fini() - near the top, and ChkButton() - first line. In ChkButton()
        I could have tested ButState directly but then I would have had to
        change M.bstate everywhere. Some code has been ripped out that is
        relative only to the game itself (not GEM or buttons). Also all the
        global variables have been left out too. I denote globals variables
        and routines with a capital letter at the start of a name and on
        and clear sub words -- eg ChkButton is global while process is local.
        Dummy is global while foobar is not, MenuObj is global while snert_var
        is not.
        
        The great book on GEM programming is << Programmer's Guide to GEM >>
        by Phillp Balma and William Fitler from Sybex (ISBN 0-89588-297-3).
        They howver do not cover the right mouse button problem.
        
        NOTE: This is an example only. This code will not work without further
        additions and routines.
*/

int init()
{
    if( Getrez() != 1 ){
        form_alert( 1, 
        "[1][ We need MEDIUM resolution.][  Sorry  ]" );
        return( 5 );
    }/* if */

    if( appl_init() == -1 ){
        return( 5 );
    }/* if */

    ColorGet( OldColor );
    ColorSet( NewColor );

    /* Prepare to load .RSC file. */
    wind_update( BEG_UPDATE );
    graf_mouse( HOURGLASS, NULL );

    if( !rsrc_load( "example.rsc" ) ){
        graf_mouse( ARROW, NULL );
        form_alert( 1, "[1][Could not find| EXAMPLE.RSC][ abort ]" );
        return( 4 );
    }/* if */

    /* Get local pointers to the principal trees */
    rsrc_gaddr( R_TREE, MAIN, &MenuObj );

    /* Get VDI handle and system font sizes. */
    VdiHandle = graf_handle( &SysCharW, &SysCharH, &SysBoxW, &SysBoxH );

    /* Open the screen as virtual workstation */
    VworkOpen( &VdiHandle );
    if( VdiHandle == 0 ){
        return( 3 );
    }/* if */

    /* Find size of desktop. This is the max for any window. */
    wind_get( DESK, WF_WORKXYWH, &DeskX, &DeskY, &DeskW, &DeskH );

    /* Create window #1 */
    GameW = wind_create( INFO, DeskX, DeskY, DeskW, DeskH );
    if( GameW < 0 ){
        form_alert( 1, "[1][No Windows available.][ abort ]" );
        return( 1 );
    }/* if */

    /* Display menu-bar. */
    menu_bar( MenuObj, TRUE );

    /* Init info line */
    strcpy( Info, Ready );
    wind_set( GameW, WF_INFO, Info, 0, 0 );

    /* Open window #1 to fill desk window and get it's current size. */
    graf_growbox( DeskW/2, DeskH/2, 21, 21, DeskX, DeskY, DeskW, DeskH );
    wind_open( GameW, DeskX, DeskY, DeskW, DeskH );
    wind_get( GameW, WF_WORKXYWH, 
              &GameArea.g_x, &GameArea.g_y, &GameArea.g_w, &GameArea.g_h );
    graf_mouse( ARROW, NULL );
    wind_update( END_UPDATE );

    GameInit();

    /* Change mouse button handler so we can get right mouse button. */
    vex_butv( VdiHandle, NewButHandler, &OldButHandler );

    return( 0 );
}/* init */


void fini( code )
    int code;
{
    int x, y, w, h;

    switch( code ){
        case 0: /* normal exit */
            /* Close window #1 on the display. */
            wind_get( GameW, WF_CURRXYWH, &x, &y, &w, &h );
            wind_close( GameW );
            graf_shrinkbox( DeskW/2, DeskH/2, 21, 21, x, y, w, h );

            /* Free memory used by window #1 & RSC. */
            wind_delete( GameW );
            menu_bar( MenuObj, FALSE );
            vex_butv( VdiHandle, OldButHandler, &Dummy );

        case 1: /* no windows free */
            VworkClose( VdiHandle );

        case 2: /* could not allocate buffers */

        case 3: /* error on device */
            rsrc_free();

        case 4: /* could not load RCS file */
            wind_update( END_UPDATE );
            ColorSet( OldColor );
            appl_exit();

        case 5: /* wrong resolution or error on appl_init() */
    }/* switch */
}/* fini */


int ChkMenu( title, item )
    int title;
    int item;
{
    switch( title ){
        case MDESK:
            if( item == ABOUT ){
                DoAbout();
            }/* if */
            break;

        case MFILE:
            switch( item ){
                case PLAY:
                    break;
    
                case QUIT:
                    return( TRUE );
            }/* switch */
            break;

        case MINFO:
            if( item == STATUS ){
                DoStatus();
            }/* if */
            break;
    }/* switch */
    menu_tnormal( MenuObj, title, TRUE );
    return( FALSE );
}/* ChkMenu */


int ChkMsg()
{
    switch( Msg[0] ){
        case MN_SELECTED:
            return( ChkMenu( Msg[3], Msg[4] ) );

        case WM_REDRAW:
            DoRedraw( Msg[3], (GRECT*) &Msg[4] );
            break;

        case WM_TOPPED:
            wind_set( Msg[3], WF_TOP, 0, 0, 0, 0 );
            break;
    }/* switch */

    return( FALSE );
}/* ChkMsg */


void ChkButton()
{
    M.bstate = ButState;
    if( M.bstate & 1 ){
        strcpy( Info, "left button" );
    } else if( M.bstate & 2 ){
        strcpy( Info, "right button" );
    }/* if */
    wind_set( GameW, WF_INFO, Info, 0, 0 );
}/* ChkButton */


void process()
{
    for( ;; ){
        Event = evnt_multi( MU_BUTTON | MU_MESAG | MU_M1,
                            1, 0x3, 1,
                            M.flag, FieldArea.g_x, FieldArea.g_y,
                            FieldArea.g_w, FieldArea.g_h,
                            0, 0, 0, 0, 0,
                            Msg, 0, 0,
                            &M.x, &M.y, 
                            &M.bstate, &Dummy, &Dummy, &M.bclicks );

        wind_update( BEG_UPDATE );

        if( (Event & MU_MESAG) && ChkMsg() ){
            break;
        }/* if */
                                                        
        if( Event & MU_BUTTON ){
            ChkButton();
        }/* if */

        if( Event & MU_M1 ){
            M.flag = !M.flag;
        }/* if */

        wind_update( END_UPDATE );
    }/* for */
}/* process */


int main()
{
    int     rc;

    srand( SEED );
    rc = init();
    if( !rc ) process();
    fini( rc );
    return( rc );
}/* main */

  achowe@tiger.waterloo.edu     | "Life is not fair. Anyone who tells
   _     -|-|_   _              |  you different is trying to sell you
  (_\ |\| | | | (_) |\| \/      |  something." - The Princess Bride
                     ___/       |                        disclaimer...

covertr@force.UUCP (Richard E. Covert) (10/19/89)

In article <17337@watdragon.waterloo.edu>, achowe@tiger.waterloo.edu (anthony howe) writes:
> About 2 years ago this question came up on the net. I still have a hard copy
> of the post which I used to develop the following tit-bit on detecting the
> right mouse button. Anyways it boiled down to this...
> 
> "Install your own button handler in assembler. The button value comes in
> d0, save it out to a nice place, then change it to a left click no matter
> what, and install the routine using  vex_butv()."  - Kenneth Soohoo
> 
> Long exmaple to follow......
> 
>   achowe@tiger.waterloo.edu     | "Life is not fair. Anyone who tells
>    _     -|-|_   _              |  you different is trying to sell you
>   (_\ |\| | | | (_) |\| \/      |  something." - The Princess Bride
>                      ___/       |                        disclaimer...


Thanks to Anthony Howe for his fine example of right button processing.
I wish that more examples of tricky ST programming would be posted
on this newsgroup.

In particular, I would like to hear from other people who have tried
the 'vdit' program posted awhile ago. 'vdit' was an example in loading
GDOS fonts, but it didn't appear to work. I would like to write a small
utility to print out a sample of each GDOS font in your collection.
So, I need to be able to load and unload GDOS fonts (both screen and
printer) and then dump a sample to the printer.

Any ideas out there??

Richard ( The Whiner (tm) ) Covert