mouse.c

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

C
1,373
字号
} /* CompareRect */

static OBJPTR FindBSelectRoot( LPRECT rect )
/******************************************/
{
    RECT            obj_loc;
    OBJPTR          root;
    OBJPTR          obj;
    LIST *          list;       // children of root
    SUBOBJ_REQUEST  req;
    compare_rect_rc rc;
    BOOL            done;

    root = GetMainObject();
    req.a.ty = ALL;
    done = FALSE;
    while( !done ) {
        list = NULL;
        FindObjList( root, &req, &list );
        for( ; list != NULL; list = ListConsume( list ) ) {
            /* check each child for containment */
            obj = ListElement( list );
            Location( obj, &obj_loc );
            rc = CompareRect( rect, &obj_loc );
            if( rc == RECT_A_IN_B || rc == RECT_EQUAL ) {
                /* we have containment in one of the children so set the */
                /* root to that child and start over */
                root = obj;
        /**/    break;
            }
        }
        if( list == NULL ) {
            /* we made it down the list without finding further containment */
            done = TRUE;
        } else {
            ListFree( list );
        }
    }
    return( root );
} /* FindBSelectRoot */

static void FindBSelectChildren( OBJPTR root, LIST ** child, LIST ** gchild )
/***************************************************************************/
/* find the children and grand children of root */
{
    SUBOBJ_REQUEST  req;
    LIST *          curr;
    LIST *          new_gchild;

    req.a.ty = ALL;
    *child = NULL;
    *gchild = NULL;
    FindObjList( root, &req, child );
    for( curr = *child; curr != NULL; curr = ListNext( curr ) ) {
        new_gchild = NULL;
        FindObjList( ListElement( curr ), &req, &new_gchild );
        ListMerge( gchild, new_gchild );
    }
} /* FindBSelectChildren */

static BOOL BuildBSelectList( LPRECT rect, LIST * child, LIST ** sel )
/********************************************************************/
/* returns TRUE if at least one of the objects in sel was contained */
{
    BOOL        contained;
    RECT        obj_loc;
    LIST *      curr;
    OBJPTR      currobj;

    *sel = NULL;
    contained = FALSE;
    for( curr = child; curr != NULL; curr = ListNext( curr ) ) {
        currobj = ListElement( curr );
        Location( currobj, &obj_loc );
        switch( CompareRect( rect, &obj_loc ) ) {
        case RECT_EQUAL:
        case RECT_B_IN_A:
            contained = TRUE;
            /* fall through */
        case RECT_A_IN_B:
        case RECT_INTERSECT:
            ListAddElt( sel, currobj );
            break;
        }
    }
    return( contained );
} /* BuildBSelectList */

static void BandedSelect( LPRECT rect )
/*************************************/
/* Banded selection is done by finding the lowest level object that fully */
/* contains the selection rect and calling that the root. The objects that */
/* may be select are either children of the root or grandchildren of the root */
/* which intersect with the rect. Preference is given to which ever of the two*/
/* sets contains an object which is fully contained in rect with ties going */
/* to the child set. */
{
    OBJPTR      root;
    LIST *      child;          // children of root
    LIST *      gchild;         // grandchildren of root
    LIST *      child_sel;
    LIST *      gchild_sel;
    LIST *      sel_list;
    BOOL        child_cont;     // some children were fully contained in rect
    BOOL        gchild_cont;    // some gchildren were fully contained in rect
    OBJPTR      currobj;
    CURROBJPTR  currptr;

    root = FindBSelectRoot( rect );
    FindBSelectChildren( root, &child, &gchild );
    /* if the root has no children try one level up so that, if possible, */
    /* something will be select on a banded select */
    if( ListCount( child ) == 0 ) {
        GetObjectParent( root, &root );
        if( root == NULL ) {
            /* this can happen if root was the main object */
            return;
        }
        FindBSelectChildren( root, &child, &gchild );
    }

    child_cont = BuildBSelectList( rect, child, &child_sel );
    gchild_cont = BuildBSelectList( rect, gchild, &gchild_sel );

    /* use the intersecting children if either any of them were fully */
    /* contained in rect or if no grandchildren were fully contained */
    if( child_cont || !gchild_cont ) {
        sel_list = child_sel;
    } else {
        sel_list = gchild_sel;
    }

    /* select the objects if there are any */
    if( sel_list != NULL ) {
        if( !GetShift() ) {
            ResetCurrObject( FALSE );
        }
        StartCurrObjMod();
        for( ; sel_list != NULL; sel_list = ListNext( sel_list ) ) {
            currobj = ListElement( sel_list );
            currptr = GetCurrObjptr( currobj );
            if( currptr == NULL ) {
                AddCurrObject( currobj );
            } else {
                /* Object already in list, just make it primary */
                SetPrimaryObject( currptr );
            }
        }
        EndCurrObjMod();
    }

    if( child != NULL ) ListFree( child );
    if( gchild != NULL ) ListFree( gchild );
    if( child_sel != NULL ) ListFree( child_sel );
    if( gchild_sel != NULL ) ListFree( gchild_sel );
} /* BandedSelect */

static void FinishSelect( POINT fin_pt )
/**************************************/
/* Finish the select operation */
{
    OBJPTR          eatom;
    RECT            rect;
    POINT           pt;

    fin_pt = fin_pt;
    eatom = GetSelectEatom();
    if( eatom != NULL ) {
        GetAnchor( eatom, &pt );
        Location( eatom, &rect );
        Destroy( eatom, FALSE );
        SetSelectEatom( NULL );
        if( IsRectEmpty( &rect ) ) {
            PointSelect( pt );
        } else {
            BandedSelect( &rect );
        }
    }
    SetDefState();
}

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

/* Leave the MovePending state because mouse up happened before a move */

  {
    OBJPTR          obj;

    SetDefState();
    if( GetControl() ) {
        obj = FindOneObjPt( pt );
        DeleteCurrObjptr( obj );
    }
    MarkCurrObject();
  }

extern void FinishMoveOperation( BOOL change_state )
/**************************************************/

/* Finish the move operation */

  {
    CURROBJPTR currobj;
    LIST *     mycurrobjlist;
    LIST *     clist;
    DLIST *    movedlist;
    BOOL       success;
    OBJPTR     eatom;
    OBJPTR     obj;
    OBJPTR     primary;
    DLIST *    dlist;
    DLIST_ELT  elt;
    DLIST *    newmovedlist;
    RECT       rect;

    if( change_state ) SetState( MOVING );
    primary = GetObjptr( GetCurrObject() );
    mycurrobjlist = GetCurrObjectList();
    for( clist = mycurrobjlist; clist != NULL; clist = ListNext( clist ) ) {
        RemoveFromParent( ListElement( clist ) );
    }
    SetShowError( FALSE ); /* Don't want error message in the middle of
                              multiple moves - paint won't work properly */
    success = TRUE;        /* Flag to indicate whether or not any move failed */
    movedlist = NULL;      /* List of objects that have been moved */
    dlist = OrderList( mycurrobjlist );
    /* Move all objects until done or a move fails.  Move in correct order */
    while( dlist != NULL ) {
        elt = GetNextElement( dlist );
        success = Register( elt.original );
        if( success ) {
            DListRemoveElt( &dlist, elt );
            DListAddElt( &movedlist, elt );
        } else {
            break;
        }
    }
    /* If a move failed, first remove all objects from their parents and
     * then undo all moves that already happened, including the
     * one that failed. Use the correct order.
     */
    if( !success ) {
        newmovedlist = DListCopy( movedlist );
        while( newmovedlist != NULL ) {
            elt = GetNextElement( newmovedlist );
            RemoveFromParent( elt.original );
            DListRemoveElt( &newmovedlist, elt );
        }
        while( movedlist != NULL ) {
            elt = GetNextElement( movedlist );
            UndoMove( elt.original );
            DListRemoveElt( &movedlist, elt );
        }
    }
    /* Notify all objects that the move operation is done */
    obj = GetECurrObject();
    while( obj != NULL ) {
        Notify( obj, MOVE_END, NULL );
        obj = GetNextECurrObject( obj );
    }
    /* Register all of the objects that got removed from the parent but
     * never got moved or moved back.  Use correct order.
     */
    ResetCurrObject( FALSE );
    while( dlist != NULL ) {
        elt = DListElement( dlist );
        eatom = elt.original;
        obj = GetObjptr( eatom );
        Location( eatom, &rect );
        MarkInvalid( &rect );
        Register( obj );
        DListRemoveElt( &dlist, elt );
    }
    StartCurrObjMod();
    for( clist = mycurrobjlist; clist != NULL; clist = ListConsume( clist ) ) {
        obj = ListElement( clist );
        AddCurrObject( GetObjptr( obj ) );
        Destroy( obj, FALSE );
    }
    DListFree( movedlist );
    DListFree( dlist );
    /* Set correct object to be primary */
    if( primary != NULL ) {
        currobj = GetCurrObjptr( primary );
        if( currobj != NULL ) {
            SetPrimaryObject( currobj );
        }
    }
    EndCurrObjMod();
    SetShowError( TRUE );  /* Set flag saying it's okay to show errors now */
    if( change_state ) SetDefState();
    /* Any error shown will cause repainting, so be sure */
    /* that we repaint the current object markers */
    UpdateWindow( GetAppWnd() );
    ReportPending();   /* Report any pending errors */
  }

static DLIST * OrderList( LIST * list )
/*************************************/

/* Return a DLIST that has an element for each element in list (in original)
 * and that object's priority in copy.
 */

  {
    DLIST *    dlist;
    DLIST_ELT  elt;
    CURROBJPTR currobj;
    int        priority;
    OBJPTR     obj;
    LIST *     mylist;

    mylist = list;
    dlist = NULL;
    while( mylist != NULL ) {
        currobj = ListElement( mylist );
        elt.original = currobj;
        mylist = ListNext( mylist );
        elt.copy = 0;
        obj = GetObjptr( currobj );
        GetPriority( obj, &priority );
        elt.copy = ( OBJPTR ) priority;
        DListAddElt( &dlist, elt );
    }
    return( dlist );
  }

static DLIST_ELT GetNextElement( DLIST * dlist )
/***********************************************/

/* Return the lowest priority element in the list */

  {
    DLIST_ELT  elt;
    DLIST_ELT  curr;
    DLIST *    mydlist;

    elt.original = NULL;
    elt.copy = NULL;
    mydlist = dlist;
    if( mydlist == NULL ) {
        return( elt );
    } else {
        curr = DListElement( mydlist );
        mydlist = DListNext( mydlist );
    }
    while( mydlist != NULL ) {
        elt = DListElement( mydlist );
        if( elt.copy < curr.copy ) {
            curr.copy = elt.copy;
            curr.original = elt.original;
        }
        mydlist = DListNext( mydlist );
    }
    return( curr );
  }

extern void BeginMoveOperation( LIST * mycurrobjlist )
/****************************************************/
/* Prepare for the move operation */
{
    POINT          init;
    OBJPTR         eatom;
    OBJPTR         currobj;
    RECT           rect;
    OBJPTR         primary;

    /* Remember the primary object so that it's eatom can be set to primary */
    primary = GetCurrObject();
    ResetCurrObject( FALSE );
    currobj = ListElement( mycurrobjlist );
    StartCurrObjMod();
    while( currobj != NULL ) {
        Location( currobj, &rect );
        eatom = Create( O_EATOM, currobj, &rect, NULL );
        AddCurrObject( eatom );
        /* Remember eatom if this is the eatom for the primary object */
        if( currobj == primary ) {
            primary = GetPrimaryObject();
        }
        init.x = rect.left;
        init.y = rect.top;
        SnapPointToGrid( &init );
        init.x -= rect.left;
        init.y -= rect.top;
        if( (init.x != 0) || (init.y != 0) ) {
            Move( eatom, &init, TRUE );
        }
        mycurrobjlist = ListNext( mycurrobjlist );
        if( mycurrobjlist != NULL ) {
            currobj = ListElement( mycurrobjlist );
        } else {
            currobj = NULL;
        }
    }
    /* Set correct eatom to be primary */
    if( primary != NULL ) {
        SetPrimaryObject( primary );
    }
    EndCurrObjMod();
    /* notify the objects of the move start */
    currobj = GetECurrObject();
    while( currobj != NULL ) {
        Notify( currobj, MOVE_START, NULL );
        currobj = GetNextECurrObject( currobj );
    }
} /* BeginMoveOperation */

extern void AbortMoveOperation( void )
/************************************/
{
    LIST *  objlist;
    OBJPTR  obj;
    OBJPTR  eatom;
    OBJPTR  currobj;
    OBJPTR  primary;

    objlist = GetCurrObjectList();
    primary = GetObjptr( GetCurrObject() );

    /* Notify all objects that the move operation is done */
    obj = GetECurrObject();
    while( obj != NULL ) {
        Notify( obj, MOVE_END, NULL );
        obj = GetNextECurrObject( obj );
    }

    ResetCurrObject( FALSE );

    StartCurrObjMod();
    for( ; objlist != NULL; objlist = ListConsume( objlist ) ) {
        eatom = ListElement( objlist );
        currobj = GetObjptr( eatom );
        AddCurrObject( currobj );
        Destroy( eatom, FALSE );
    }

    /* Set correct object to be primary */
    if( primary != NULL ) {
        currobj = GetCurrObjptr( primary );
        if( currobj != NULL ) {
            SetPrimaryObject( currobj );
        }
    }
    EndCurrObjMod();
} /* AbortMoveOperation */

static void FinishActionAborted( POINT pt )
/***************************************/
{
    pt = pt;

    SetState( DORMANT );
} /* FinishActionAborted */

⌨️ 快捷键说明

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