mouse.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,373 行 · 第 1/3 页

C
1,373
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Routines to handle the mouse interactions.
*
****************************************************************************/


#include "limits.h"
#include "windows.h"

#include "fmedit.def"
#include "object.def"
#include "state.def"
#include "currobj.def"
#include "grid.def"
#include "list.def"
#include "align.def"
#include "dlist.def"
#include "clip.def"

#include "mouse.def"


/* forward references */

// mouse press actions
static void ActionBegin( POINT, WORD, OBJPTR );
static void ResizeBegin( POINT, WORD, OBJPTR );
static void BeginPaste( POINT, WORD, OBJPTR );
static void ResetEdit( POINT, WORD, OBJPTR );
static void IgnoreMousePress( POINT, WORD, OBJPTR );
static void UnexpectedPressStateRecover( POINT, WORD, OBJPTR );

// mouse move and release actions
static void CheckMousePosn( POINT );
static void DoObjectMove( POINT );
static void DoObjectResize( POINT );
static void DoObjectRecreate( POINT );
static void UnexpectedStateRecover( POINT );
static void BeginMove( POINT );
static void MovePendingBegin( BOOL, OBJPTR );
static void DoPasteMove( POINT );
static void DoSelectRecreate( POINT );
static void IgnoreMouse( POINT );
static void FinishMove( POINT );
static void FinishResize( POINT );
static void FinishCreate( POINT );
static void FinishPaste( POINT );
static void FinishSelect( POINT );
static void FinishMovePending( POINT );
static void FinishActionAborted( POINT pt );
static DLIST * OrderList( LIST * );
static DLIST_ELT GetNextElement( DLIST * );

static void (*MousePressActions[])( POINT, WORD, OBJPTR ) = {
    ActionBegin                     /* DORMANT          */
,   ResizeBegin                     /* OVERBOX          */
,   UnexpectedPressStateRecover     /* MOVING           */
,   ResetEdit                       /* EDITING          */
,   UnexpectedPressStateRecover     /* SIZING           */
,   UnexpectedPressStateRecover     /* CREATING         */
,   UnexpectedPressStateRecover     /* ALIGNING         */
,   BeginPaste                      /* PASTE_PENDING    */
,   UnexpectedPressStateRecover     /* PASTEING         */
,   UnexpectedPressStateRecover     /* SELECTING        */
,   UnexpectedPressStateRecover     /* MOVE_PENDING     */
,   UnexpectedPressStateRecover     /* ACTION_ABORTED   */
,   IgnoreMousePress                /* KBD_MOVING       */
};


static void (*MouseMoveActions[])( POINT ) = {
    CheckMousePosn                  /* DORMANT          */
,   CheckMousePosn                  /* OVERBOX          */
,   DoObjectMove                    /* MOVING           */
,   CheckMousePosn                  /* EDITING          */
,   DoObjectResize                  /* SIZING           */
,   DoObjectRecreate                /* CREATING         */
,   UnexpectedStateRecover          /* ALIGNING         */
,   UnexpectedStateRecover          /* PASTE_PENDING    */
,   DoPasteMove                     /* PASTEING         */
,   DoSelectRecreate                /* SELECTING        */
,   BeginMove                       /* MOVE_PENDING     */
,   IgnoreMouse                     /* ACTION_ABORTED   */
,   IgnoreMouse                     /* KBD_MOVING       */
};


static void (*MouseReleaseActions[])( POINT ) = {
    UnexpectedStateRecover          /* DORMANT          */
,   UnexpectedStateRecover          /* OVERBOX          */
,   FinishMove                      /* MOVING           */
,   IgnoreMouse                     /* EDITING          */
,   FinishResize                    /* SIZING           */
,   FinishCreate                    /* CREATING         */
,   UnexpectedStateRecover          /* ALIGNING         */
,   UnexpectedStateRecover          /* PASTE_PENDING    */
,   FinishPaste                     /* PASTEING         */
,   FinishSelect                    /* SELECTING        */
,   FinishMovePending               /* MOVE_PENDING     */
,   FinishActionAborted             /* ACTION_ABORTED   */
,   IgnoreMouse                     /* KBD_MOVING       */
};


extern void ProcessDBLCLK( POINT point )
/**************************************/

/*  Process a double click on the current object.  This implies a request
 *  to define/redefine the characteristics of the object.
 */

  {
    POINT pt;
    OBJPTR currobj;

    pt = point;
    currobj = GetPrimaryObject();
    if( currobj != NULL ) {
        Define( currobj, &pt, NULL );
    }
  }


static void ResizeBegin( POINT pt, WORD ks, OBJPTR d )
/****************************************************/

/* Begin a resizing operation */

  {
    OBJPTR         object;
    RECT           rect;
    RECT           offrect;
    NOTE_ID        noteid;
    POINT          rgrid;

    pt = pt;         /* ref'd to avoid warning */
    ks = ks;   /* ref'd to avoid warning */
    d = d;
    SetDefState();
    object = GetPrimaryObject();
    if( object != NULL ) {
        if( GetState() == EDITING ) {
            noteid = TERMINATE_EDIT;
            Notify( object, noteid, NULL );
        }
        SetDefState();
        if( !ValidateAction( object, RESIZE, NULL ) ) {
            return;
        }
        SetState( SIZING );
        Location( object, &rect );
        rgrid.x = GetHorizontalInc();
        rgrid.y = GetVerticalInc();
        ResizeIncrements( object, &rgrid );
        SetResizeGrid( rgrid.x, rgrid.y );
        SaveObject();
        object = GetObjptr( object );
        ResetCurrObject( FALSE );
        object = Create( O_EATOM, object, &rect, NULL );
        SetCurrObject( object );
        offrect = rect;
        if( SnapRectToGrid( &offrect ) ) {
            offrect.top -= rect.top;
            offrect.left -= rect.left;
            offrect.right -= rect.right;
            offrect.bottom -= rect.bottom;
            Resize( object, &offrect, TRUE );
        }
    }
  }


static void ResetEdit( POINT pt, WORD keystate, OBJPTR d )
/********************************************************/

/*  Reset the previous editing operation and proceed with the default
 *  action for a mouse press.
 */

  {
    NOTE_ID noteid;
    OBJPTR  currobj;

    d = d;
    noteid = TERMINATE_EDIT;
    currobj = GetECurrObject();
    if( currobj != NULL ) {
        Notify( currobj, noteid, NULL );
    }
    SetBaseState( DORMANT );
    SetDefState();
    MousePressActions[GetState()]( pt, keystate, NULL );
  }


static void UnexpectedStateRecover( POINT pt )
/********************************************/

/*  A mouse press was received in a state where it should be impossible to
 *  get a mouse press. Ignore it.
 */

   {
     pt = pt;           /* ref'd to avoid warning */
#ifdef DEBUG_ON
     MessageBox( GFileIO.hWnd, ( LPSTR ) "State Error",
                  NULL, MB_OK | MB_ICONSTOP );
#endif
   }

static void UnexpectedPressStateRecover( POINT pt, WORD ks, OBJPTR d )
/********************************************************************/

/*  A mouse press was received in a state where it should be impossible to
 *  get a mouse press. Ignore it.
 */

   {
     pt = pt;           /* ref'd to avoid warning */
     ks = ks;           /* ref'd to avoid warning */
     d = d;             /* ref'd to avoid warning */
#ifdef DEBUG_ON
     MessageBox( GFileIO.hWnd, ( LPSTR ) "State Error",
                  NULL, MB_OK | MB_ICONSTOP );
#endif
   }


static void CreateBegin( POINT pt, OBJPTR parent )
/*********************************************/

/* begin the creation of a new object */

  {
    RECT           origin;

    SetState( CREATING );
    SnapPointToGrid( &pt );
    origin.top = pt.y;
    origin.bottom = pt.y;
    origin.left = pt.x;
    origin.right = pt.x;
    SaveObject();
    ResetCurrObject( FALSE );
    SetCurrObject( Create( O_EATOM, parent, &origin, NULL ) );
  }


static void MovePendingBegin( BOOL keystate, OBJPTR object )
/**********************************************************/

/* begin a move operation */

  {
    /* If the object the mouse press was on is not in the current object list
     * then, if mulitple select, add it to the list, otherwise, make it the
     * current object */

    if( GetCurrObjptr( object ) == NULL ) {
        if( !(keystate & MK_SHIFT) && !(keystate & MK_CONTROL) ) {
            ResetCurrObject( FALSE );
        }
        AddCurrObject( object );
        /* Remove the Control flag so that the added selection isn't removed
         * on the Mouse UP of thhe state stays the same as MOVE_PENDING
         */
        keystate &= ~MK_CONTROL;
    } else {
        SetPrimaryObject( GetCurrObjptr( object ) );
    }
    SetKeyState( keystate);
    SetState( MOVE_PENDING );
  }

extern BOOL CheckMoveOperation( LIST ** objlist )
/***********************************************/

  {
    LIST *  clist;
    OBJPTR  obj;
    RECT    rect;
    POINT   pt;

    *objlist = GetCurrObjectList();
    for( clist = *objlist; clist != NULL; clist = ListNext( clist ) ) {
        obj = ListElement( clist );
        Location( obj, &rect );
        pt.x = rect.left;
        pt.y = rect.top;
        if( !ValidateAction( obj, MOVE, &pt ) ) {
            SetPrimaryObject( GetCurrObjptr( obj ) );
            MessageBox( GetAppWnd(), "The current selected object cannot be moved.",
                        NULL, MB_ICONEXCLAMATION | MB_OK );

            ListFree( *objlist );
            *objlist = NULL;
            return( FALSE );
        }
    }
    return( TRUE );
  }


static void BeginMove( POINT p )
/******************************/

/* Begin the movement operation */

  {
    LIST * movelist;

    if( CheckMoveOperation( &movelist ) ) {
        SetState( MOVING );
        BeginMoveOperation( movelist );
        ListFree( movelist );
    } else {
        SetState( DORMANT );
    }
    SetPrevMouse( p );
  }


static void SelectBegin( POINT pt, WORD keystate )
/************************************************/

  {
    RECT origin;

    origin.top = pt.y;
    origin.bottom = pt.y;
    origin.left = pt.x;
    origin.right = pt.x;
    SaveObject();
    SetKeyState( keystate );
    SetState( SELECTING );
    SetSelectEatom( Create( O_EATOM, NULL, &origin, NULL ) );
  }

static BOOL InVicinity( OBJPTR * obj, short y, short x )
/******************************************************/

/* See if we're in the vicinity of an object that can be moved */


  {
    POINT          pt;
    OBJPTR         closeobj;

    pt.x = x;
    pt.y = y;
    closeobj = FindOneObjPt( pt );
    if( (closeobj == *obj) || !ValidateAction( closeobj, MOVE, &pt ) ) {
        return( FALSE );
    } else {
        *obj = closeobj;
    }
    return( TRUE );
  }



static BOOL IsMoveOperation( OBJPTR obj, POINT point, WORD keystate )
/*******************************************************************/

  {
    BOOL   ret;

    ret = FALSE;
    if( ValidateAction( obj, MOVE, &point )  ||
        InVicinity( &obj, point.y - OBJ_VICINITY, point.x ) ||
        InVicinity( &obj, point.y + OBJ_VICINITY, point.x ) ||
        InVicinity( &obj, point.y, point.x - OBJ_VICINITY ) ||
        InVicinity( &obj, point.y, point.x + OBJ_VICINITY ) )
        {
        MovePendingBegin( keystate, obj );
        ret = TRUE;
    }
    return( ret );
  }


static void ActionBegin( POINT point, WORD keystate, OBJPTR obj )
/***************************************************************/

/* begin a create or move action depending on the button pressed */

  {
    if( obj == NULL ) {
        obj = FindOneObjPt( point );
    }
    if( GetBaseObjType() != O_NONE ) {
        CreateBegin( point, obj );
    } else if( !IsMoveOperation( obj, point, keystate ) ) {
        SelectBegin( point, keystate );
    }
  }


extern void ProcessButtonDown( POINT point, WORD keystate, OBJPTR obj )
/**********************************************************************/

/* responds to a button down message from the mouse */

  {
    STATE_ID st;

    st = GetState();
    if( st != PASTE_PENDING ) {
        SetCapture( GetAppWnd() );
    }
    MousePressActions[st]( point, keystate, obj );
    SetPrevMouse( point );
  }


static void FinishMove( POINT pt )
/********************************/

/* Finish the movement operation */

  {
    pt = pt;
    FinishMoveOperation( TRUE );
  }


static void IgnoreMouse( POINT pt )
/*********************************/

/* Ignore a mouse action */

  {
    pt = pt;        /* ref'd to avoid warning */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?