guixloop.c

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

C
772
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "guiwind.h"
#include "guixutil.h"
#include "uimouse.h"
#include "guiscrol.h"
#include "guixloop.h"
#include "guiwhole.h"
#include "guicontr.h"
#include "guiscale.h"
#include "guifloat.h"
#include "guixkey.h"
#include "guisysme.h"
#include "guixwind.h"
#include "guisize.h"
#include "guismove.h"
#include "guimapky.h"
#include "guixhook.h"
#include "guigadgt.h"
#include "guixinit.h"
#include <stdlib.h>
#include <stdio.h>

/* includes from guixmain.c */
extern  gui_window      *GUICurrWnd;

/* statics */
static  ORD             OldCol          = -1;      /* old column of mouse */
static  ORD             OldRow          = -1;      /* old row of mouse    */

static  gui_window *GUIMouseWnd      = NULL;

static enum {
    MOUSE_FREE,                 /* mouse moving not in press-drag sequence */
    MOUSE_CLIENT,               /* mouse press in client area, no release  */
    MOUSE_MOVE,                 /* window being moved by mouse             */
    MOUSE_SIZE,                 /* window being resized by mouse           */
    MOUSE_MAX_START,            /* mouse press to start maximize           */
    MOUSE_MIN_START,            /* mouse press to start minimize           */
    MOUSE_RESTORE_START         /* mouse press to start restore            */
} MouseState;

EVENT GUIUserEvents[] = {
    GUI_FIRST_USER_EVENT, LAST_EVENT,
    EV_NO_EVENT,
    EV_NO_EVENT
};

static EVENT GUIInternalEvents[] = {
    GUI_FIRST_SYS_MENU, GUI_LAST_SYS_MENU,
    EV_NO_EVENT,
    EV_NO_EVENT
};

static  EVENT           PrevMouseEvent  = EV_NO_EVENT;
static  bool            MinimizedMoved  = FALSE;
static  gui_window      *ButtonDownSent = NULL;

/*
 * SendPointEvent -- send mouse event to use with the point it occured at
 */

static void SendPointEvent( gui_window *wnd, gui_event gui_ev,
                            gui_coord *point )
{
    gui_point   pt;
    bool        down_sent;

    down_sent = ButtonDownSent == wnd;
    switch( gui_ev ) {
    case GUI_LBUTTONDOWN :
    case GUI_RBUTTONDOWN :
        ButtonDownSent = wnd;
        break;
    case GUI_LBUTTONUP :
    case GUI_RBUTTONUP :
        ButtonDownSent = NULL;
        break;
    default :
        break;
    }
    /* if the mouse event is not on the border, or if it is a mouse up on
     * the border
     */
    if( down_sent || ( MouseState == MOUSE_CLIENT ) ) {
        if( ( wnd->hgadget != NULL ) && !GUI_HSCROLL_EVENTS_SET( wnd ) ) {
            point->x += wnd->hgadget->pos;
        }
        if( ( wnd->vgadget != NULL ) && !GUI_VSCROLL_EVENTS_SET( wnd ) ) {
            point->y += wnd->vgadget->pos;
        }
        GUIMakeRelative( wnd, point, &pt );
        GUIEVENTWND( wnd, gui_ev, &pt );
    }
}

static bool ValidMaxRestore( gui_window *wnd, ORD wnd_row, ORD wnd_col )
{
    return( ( wnd->style & GUI_MAXIMIZE ) &&
            GUI_RESIZE_GADGETS_USEABLE( wnd ) &&
            ( wnd_col >= wnd->screen.area.width-MAXOFFSET-1 ) &&
            ( wnd_col <= wnd->screen.area.width-MAXOFFSET+1 ) &&
            ( wnd_row == ( wnd->use.row - 1 ) ) );
}

static bool ValidMin( gui_window *wnd, ORD wnd_row, ORD wnd_col )
{
    return( ( wnd->style & GUI_MINIMIZE ) &&
            GUI_RESIZE_GADGETS_USEABLE( wnd ) &&
            ( wnd_col >= wnd->screen.area.width-MINOFFSET-1 ) &&
            ( wnd_col <= wnd->screen.area.width-MINOFFSET+1 ) &&
            ( wnd_row == ( wnd->use.row - 1 ) ) );
}

/*
 * ProcessMouseReleaseDrag -- take action because mouse was released.
 *                            Also use in the case of drag.
 */

static void ProcessMouseReleaseDrag( EVENT ev, gui_event gui_ev, ORD row,
                                     ORD col )
{
    gui_coord   point;
    ORD         wnd_row;
    ORD         wnd_col;

    OldCol = col;
    OldRow = row;

    if( GUIMouseWnd == NULL ) {
        return;
    }

    wnd_row = row - GUIMouseWnd->screen.area.row;
    wnd_col = col - GUIMouseWnd->screen.area.col;
    switch( MouseState ) {
    case MOUSE_RESTORE_START :
        if( ValidMaxRestore( GUIMouseWnd, wnd_row, wnd_col ) &&
            ( gui_ev == GUI_LBUTTONUP ) ) {
                GUIZoomWnd( GUIMouseWnd, GUI_NONE );
        }
        break;
    case MOUSE_MAX_START :
        if( ValidMaxRestore( GUIMouseWnd, wnd_row, wnd_col ) &&
            ( gui_ev == GUI_LBUTTONUP ) ) {
            GUIZoomWnd( GUIMouseWnd, GUI_MAXIMIZE );
        }
        break;
    case MOUSE_MIN_START :
        if( ValidMin( GUIMouseWnd, wnd_row, wnd_col ) &&
            ( gui_ev == GUI_LBUTTONUP ) ) {
            GUIZoomWnd( GUIMouseWnd, GUI_MINIMIZE );
        }
        break;
    case MOUSE_SIZE:
        if( !( GUIMouseWnd->style & GUI_RESIZEABLE ) ) {
            return;
        }
        /* fall through */
    case MOUSE_MOVE:
        if( ev == EV_MOUSE_RELEASE_R ) {
            return;
        }
        GUIDoMoveResize( GUIMouseWnd, row, col, ev, NULL );
        break;
    default :
        if( GUIMouseWnd != NULL ) {
            point.x = (gui_ord)col;
            point.y = (gui_ord)row;
            SendPointEvent( GUIMouseWnd, gui_ev, &point );
        }
    }
    if( ev == EV_MOUSE_RELEASE || ev == EV_MOUSE_RELEASE_R ) {
        MouseState = MOUSE_FREE;
    }
}

/*
 * ProcessMousePos - if the mouse has move, send the new position and the
 *                   indicated event to the window containing the mouse
 */

static bool ProcessMousePos( gui_event gui_ev, ORD row, ORD col, gui_window * wnd )
{
    gui_coord    point;

    OldCol = col;
    OldRow = row;
    if( wnd == NULL ) {
        return( FALSE );
    }
    point.x = (gui_ord)col;
    point.y = (gui_ord)row;
    SendPointEvent( wnd, gui_ev, &point );
    return( TRUE );
}

EVENT GUICreatePopup( gui_window *wnd, gui_coord *point )
{
    EVENT       ev;

    point->x -= wnd->screen.area.col;
    point->y -= (wnd->screen.area.row - 1);
    uipushlist( NULL );
    uipushlist( GUIInternalEvents );
    uipushlist( GUIUserEvents );
    ev = GUICreateMenuPopup( wnd, point, wnd->menu, GUI_TRACK_LEFT, NULL );
    uipoplist( /* GUIUserEvents */ );
    uipoplist( /* GUIInternalEvents */ );
    uipoplist( /* NULL */ );
    return( ev );
}

static void ProcessMinimizedMouseEvent( EVENT ev, ORD row, ORD col )
{
    gui_coord point;

    switch( ev ) {
    case EV_MOUSE_PRESS :
        if( GUIStartMoveResize( GUIMouseWnd, row, col, RESIZE_NONE ) ) {
            MouseState = MOUSE_MOVE;
        }
        MinimizedMoved = FALSE;
        break;
   case EV_MOUSE_DRAG :
        MinimizedMoved = TRUE;
        GUIDoMoveResize( GUIMouseWnd, row, col, ev, NULL );
        break;
    case EV_MOUSE_RELEASE :
        if( MouseState == MOUSE_MOVE ) {
            GUIDoMoveResize( GUIMouseWnd, row, col, ev, NULL );
            MouseState = MOUSE_FREE;
        }
        if( !MinimizedMoved ) {
            point.x = (gui_ord)col;
            point.y = (gui_ord)row;
            if( GUICreatePopup( GUICurrWnd, &point ) == EV_MOUSE_DCLICK ) {
                GUIZoomWnd( GUICurrWnd, GUI_NONE );
            }
        }
        break;
    case EV_MOUSE_DCLICK :
        GUIZoomWnd( GUICurrWnd, GUI_NONE );
        break;
    }
}

/*
 * ProcessMousePress -- respond to the press of the mouse
 */

static void ProcessMousePress( EVENT ev, gui_event gui_ev, ORD row, ORD col,
                               bool new_curr_wnd )
{
    gui_coord   point;
    ORD         wnd_row;
    ORD         wnd_col;
    resize_dir  dir;
    bool        use_gadgets;

    point.x = (gui_ord)col;
    point.y = (gui_ord)row;
    OldCol = col;
    OldRow = row;
    if( GUICurrWnd == NULL ) {
        return;
    }
    dir = RESIZE_NONE;
    if( MouseState == MOUSE_SIZE || MouseState == MOUSE_MOVE ) {
        return;
    }
    MouseState = MOUSE_FREE; /* default */
    if( !( GUICurrWnd->style & GUI_VISIBLE ) ) {
        return;
    }
    wnd_row = row - GUICurrWnd->screen.area.row;
    wnd_col = col - GUICurrWnd->screen.area.col;
    if( wnd_row < GUICurrWnd->use.row ) {
        use_gadgets = !new_curr_wnd || ( GUIGetWindowStyles() &
                      ( GUI_INACT_GADGETS | GUI_INACT_SAME ) );
        if( use_gadgets && GUI_HAS_CLOSER( GUICurrWnd ) &&
            ( wnd_col >= CLOSER_COL -1 ) && ( wnd_col <= CLOSER_COL+1 ) ) {
            if( ( GUICurrWnd->menu != NULL ) && ( ev == EV_MOUSE_PRESS ) ) {
                point.x = GUICurrWnd->screen.area.col;
                ev = GUICreatePopup( GUICurrWnd, &point );
            }
            if( (GUICurrWnd->style & GUI_CLOSEABLE) && (ev == EV_MOUSE_DCLICK) ) {
                if( GUICloseWnd( GUICurrWnd ) ) {
                    MouseState = MOUSE_FREE;
                }
            }
        } else if( use_gadgets && ValidMaxRestore( GUICurrWnd, wnd_row, wnd_col ) ) {
            if( GUI_WND_MAXIMIZED( GUICurrWnd ) ) {
                MouseState = MOUSE_RESTORE_START;
            } else {
                MouseState = MOUSE_MAX_START;
            }
        } else if( use_gadgets && ValidMin( GUICurrWnd, wnd_row, wnd_col ) &&
                   ( ev == EV_MOUSE_PRESS ) ) {
            MouseState = MOUSE_MIN_START;
        } else if( (GUICurrWnd->style & GUI_RESIZEABLE) && (ev == EV_MOUSE_PRESS) &&
                   ( ( wnd_col == 0) || (wnd_col == GUICurrWnd->screen.area.width-1) ) ) {
            dir = RESIZE_UP;
        } else if( ( ev == EV_MOUSE_DCLICK ) || ( ev == EV_MOUSE_PRESS ) ) {
            if( GUIStartMoveResize( GUICurrWnd, row, col, RESIZE_NONE ) ) {
                MouseState = MOUSE_MOVE;
            }
        }
    } else if( GUIPtInRect( &GUICurrWnd->use, wnd_row, wnd_col ) ) {
        MouseState = MOUSE_CLIENT;
        SendPointEvent( GUICurrWnd, gui_ev, &point );
    } else if( ( GUICurrWnd->style & GUI_RESIZEABLE ) && ( ev == EV_MOUSE_PRESS ) &&
               ( wnd_row == GUICurrWnd->screen.area.height-1 ) &&
               ( ( wnd_col == 0 ) || ( wnd_col == GUICurrWnd->screen.area.width-1 ) ) ) {
        dir = RESIZE_DOWN;
    }
    if( dir != RESIZE_NONE ) {
        if( wnd_col == 0 ) {
            dir |= RESIZE_LEFT;
        } else {
            dir |= RESIZE_RIGHT;
        }
        if( GUIStartMoveResize( GUICurrWnd, row, col, dir ) ) {
            MouseState = MOUSE_SIZE;
        }
    }
    GUIMouseWnd = GUICurrWnd;
}

static void ProcessInitPopupEvent( void )
{
    MENUITEM menu;
    unsigned id;

    if( uigetcurrentmenu ( &menu ) ) {
        id = (unsigned) menu.event - GUI_FIRST_USER_EVENT;
        if ( id ) {
            GUIEVENTWND( GUICurrWnd, GUI_INITMENUPOPUP, &id );
        }
    }
}

static void ProcessScrollEvent( EVENT ev  )
{
    gui_event   gui_ev;
    p_gadget    gadget;
    int         diff;
    bool        events;
    gui_event   notify;

    switch( ev ) {
    case EV_SCROLL_UP :
        events = GUICurrWnd->style & GUI_VSCROLL_EVENTS;
        gui_ev = GUI_SCROLL_UP;
        diff = -1;
        gadget = GUICurrWnd->vgadget;

⌨️ 快捷键说明

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