scroll.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 385 行
C
385 行
/****************************************************************************
*
* 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 used for scrolling.
*
****************************************************************************/
#include <stdlib.h>
#include <limits.h>
#include <windows.h>
#include "win1632.h"
#include "fmedit.def"
#include "state.def"
#include "object.def"
#include "global.h"
#define PG_SC_PERCENT 80
#define LN_SC_AMOUNT 10
#define UNLOCK_SCROLL_FUDGE 10
static void DoScroll( HWND wnd, int dx, int dy, BOOL lock );
extern void VerticalScroll( WPARAM wparam, LPARAM lparam, HWND wnd )
/**************************************************************/
{
int ydel;
RECT clrect;
POINT offset;
RECT scrollrect;
wparam = wparam;
lparam = lparam;
if( !( GetScrollConfig() & SCROLL_VERT ) ) {
return;
}
GetClientRect( GetAppWnd(), &clrect );
scrollrect = GetScrollRect();
ydel = 0;
GetOffset( &offset );
switch( LOWORD(wparam) ) {
case SB_BOTTOM:
ydel = scrollrect.bottom - offset.y - clrect.bottom;
break;
case SB_LINEDOWN:
ydel = LN_SC_AMOUNT;
break;
case SB_LINEUP:
ydel = -LN_SC_AMOUNT;
break;
case SB_PAGEDOWN:
ydel = (long)clrect.bottom * PG_SC_PERCENT / 100;
break;
case SB_PAGEUP:
ydel = -((long)clrect.bottom * PG_SC_PERCENT / 100);
break;
case SB_THUMBPOSITION:
//ydel = GET_WM_VSCROLL_POS(wparam,lparam) - offset.y - clrect.bottom;
ydel = GET_WM_VSCROLL_POS(wparam,lparam) - offset.y;
break;
case SB_TOP:
ydel = -offset.y;
break;
default:
break;
}
// make sure we do not expose area's not in the scroll rect
if( ( clrect.bottom <= scrollrect.bottom ) &&
( clrect.top >= scrollrect.top ) ) {
if( ydel ) {
if( clrect.bottom + offset.y + ydel > scrollrect.bottom ) {
ydel = scrollrect.bottom - clrect.bottom - offset.y;
}
} else {
if( clrect.top + offset.y + ydel < scrollrect.top ) {
ydel = clrect.top + offset.y - scrollrect.top;
}
}
}
DoScroll( wnd, 0, ydel, TRUE );
}
extern void HorizontalScroll( WPARAM wparam, LPARAM lparam, HWND wnd )
/****************************************************************/
{
int xdel;
RECT clrect;
POINT offset;
RECT scrollrect;
wparam = wparam;
lparam = lparam;
if( !( GetScrollConfig() & SCROLL_HORZ ) ) {
return;
}
GetClientRect( GetAppWnd(), &clrect );
scrollrect = GetScrollRect();
xdel = 0;
GetOffset( &offset );
switch( LOWORD(wparam) ) {
case SB_BOTTOM:
xdel = scrollrect.right - offset.x - clrect.right;
break;
case SB_LINEDOWN:
xdel = LN_SC_AMOUNT;
break;
case SB_LINEUP:
xdel = -LN_SC_AMOUNT;
break;
case SB_PAGEDOWN:
xdel = (long)clrect.right * PG_SC_PERCENT / 100;
break;
case SB_PAGEUP:
xdel = -(long)clrect.right * PG_SC_PERCENT / 100;
break;
case SB_THUMBPOSITION:
//xdel = GET_WM_VSCROLL_POS(wparam, lparam) - offset.x - clrect.right;
xdel = GET_WM_VSCROLL_POS(wparam, lparam) - offset.x;
break;
case SB_TOP:
xdel = -offset.x;
break;
default:
break;
}
// make sure we do not expose area's not in the scroll rect
if( ( clrect.right <= scrollrect.right ) &&
( clrect.left >= scrollrect.left ) ) {
if( xdel ) {
if( clrect.right + offset.x + xdel > scrollrect.right ) {
xdel = scrollrect.right - clrect.right - offset.x;
}
} else {
if( clrect.left + offset.x + xdel < scrollrect.left ) {
xdel = clrect.left + offset.x - scrollrect.left;
}
}
}
DoScroll( wnd, xdel, 0, TRUE );
}
extern void InitScroll( SCR_CONFIG scroll, HWND wnd )
/***************************************************/
{
RECT clrect;
POINT point;
SetScrollConfig( scroll );
GetClientRect( wnd, &clrect );
if( scroll & SCROLL_VERT ) {
SetScrollRange( wnd, SB_VERT, 0, clrect.bottom, FALSE );
SetScrollPos( wnd, SB_VERT, 0, TRUE );
}
if( scroll & SCROLL_HORZ ) {
SetScrollRange( wnd, SB_HORZ, 0, clrect.right, FALSE );
SetScrollPos( wnd, SB_HORZ, 0, TRUE );
}
point.x = 0;
point.y = 0;
SetOffset( point );
SetScrollRect( clrect );
}
extern void ScrollResize( HWND wnd, WPARAM lparam )
/***********************************************/
{
RECT newrect;
POINT offset;
RECT clrect;
if( GetScrollConfig() == SCROLL_NONE ) {
return;
}
clrect.left = 0;
clrect.top = 0;
clrect.right = LOWORD( lparam );
clrect.bottom = HIWORD( lparam );
newrect = clrect;
RequestScrollRect( &newrect );
SetScrollRect( newrect );
GetOffset( &offset );
if( GetScrollConfig() & SCROLL_HORZ ) {
SetScrollRange( wnd, SB_HORZ, newrect.left, newrect.right - clrect.right, FALSE );
SetScrollPos( wnd, SB_HORZ, offset.x, TRUE );
}
if( GetScrollConfig() & SCROLL_VERT ) {
SetScrollRange( wnd, SB_VERT, newrect.top, newrect.bottom - clrect.bottom, FALSE );
SetScrollPos( wnd, SB_VERT, offset.y, TRUE );
}
}
extern void AutoScroll( RECT eatom, POINT delta )
/***********************************************/
{
POINT offset;
RECT clrect;
HWND wnd;
int xdel;
int ydel;
POINT mouse;
eatom = eatom; /* ref'd to avoid warnings */
if( GetScrollConfig() == SCROLL_NONE ) {
return;
}
wnd = GetAppWnd();
GetClientRect( wnd, &clrect );
GetOffset( &offset );
OffsetRect( &clrect, offset.x, offset.y );
xdel = 0;
ydel = 0;
mouse = GetPrevMouse();
mouse.x += delta.x;
mouse.y += delta.y;
#define SLOW_DOWN_N 2
#define SLOW_DOWN_D 3
if( ( ( delta.x > 0 ) &&
( ( abs( mouse.x - clrect.right ) < GetHorizontalInc() ) ||
( mouse.x > clrect.right ) ) ) ||
( ( delta.x < 0 ) &&
( ( abs( mouse.x - clrect.left ) < GetHorizontalInc() ) ||
( mouse.x < clrect.left ) ) ) ) {
xdel = delta.x;
if( xdel > 0 ) {
xdel = max( 1, ( xdel * SLOW_DOWN_N ) /SLOW_DOWN_D );
} else {
xdel = min( -1, ( xdel * SLOW_DOWN_N ) /SLOW_DOWN_D );
}
}
if( ( ( delta.y > 0 ) &&
( ( abs( mouse.y - clrect.bottom ) < GetVerticalInc() ) ||
( mouse.y > clrect.bottom ) ) ) ||
( ( delta.y < 0 ) &&
( ( abs( mouse.y - clrect.top ) < GetVerticalInc() ) ||
( mouse.y < clrect.top ) ) ) ) {
ydel = delta.y;
if( ydel > 0 ) {
ydel = max( 1, ( ydel * SLOW_DOWN_N ) /SLOW_DOWN_D );
} else {
ydel = min( -1, ( ydel * SLOW_DOWN_N ) /SLOW_DOWN_D );
}
}
if( !(GetScrollConfig() & SCROLL_VERT) ) {
ydel = 0;
}
if( !(GetScrollConfig() & SCROLL_HORZ) ) {
xdel = 0;
}
DoScroll( wnd, xdel, ydel, TRUE );
UpdateWindow( wnd );
}
static int AdjustScroll( int curr, int low, int high, int delta )
/***************************************************************/
/* Adjust 'delta' to keep the scrolling in the current scrolling rect. */
/* 'low' and 'high' are the boundries of the scrolling rect */
{
if( curr + delta < low ) {
return( low - curr );
} else if( curr + delta > high ) {
return( high - curr );
} else {
return( delta );
}
} /* AdjustScroll */
#define _constrain_short( l ) \
(max( (long)SHRT_MIN, min( (long) SHRT_MAX, (l) )))
static void GetScrollBounds( LPRECT rect, BOOL lock )
/***************************************************/
// if this is a locked scrolling the scroll bound is the scroll rect,
// otherwise the bottom and right of bounds are the largest possible that
// will satisfy the following:
// 1. They are both shorts (i.e. in the range SHRT_MIN to SHRT_MAX).
// 2. The maximum distance that you can scroll away from the top, left
// corner of the scroll rect is SHRT_MAX - UNLOCK_SCROLL_FUDGE.
{
RECT clrect;
long bound;
*rect = GetScrollRect();
if( !lock ) {
GetClientRect( GetAppWnd(), &clrect );
bound = (long)rect->left + SHRT_MAX - clrect.right
- UNLOCK_SCROLL_FUDGE;
rect->right = _constrain_short( bound );
bound = (long)rect->top + SHRT_MAX - clrect.bottom
- UNLOCK_SCROLL_FUDGE;
rect->bottom = _constrain_short( bound );
}
} /* GetScrollBounds */
static void DoScroll( HWND wnd, int dx, int dy, BOOL lock )
/*********************************************************/
/* scroll 'wnd' by 'dx' and 'dy'. 'lock' says to lock the scrolling on the */
/* bottom and right into the scrolling rectangle */
{
POINT offset;
RECT srect;
GetOffset( &offset );
GetScrollBounds( &srect, lock );
dx = AdjustScroll( offset.x, srect.left, srect.right, dx );
dy = AdjustScroll( offset.y, srect.top, srect.bottom, dy );
if( dx != 0 || dy != 0 ) {
offset.x += dx;
offset.y += dy;
SetOffset( offset );
ScrollWindow( wnd, -dx, -dy, NULL, NULL );
if( GetScrollConfig() & SCROLL_HORZ ) {
SetScrollPos( wnd, SB_HORZ, offset.x, TRUE );
}
if( GetScrollConfig() & SCROLL_VERT ) {
SetScrollPos( wnd, SB_VERT, offset.y, TRUE );
}
}
} /* DoScroll */
void WINEXP UpdateScroll( void )
/******************************/
{
RECT newrect;
RECT clrect;
POINT offset;
HWND wnd;
if( GetScrollConfig() == SCROLL_NONE ) {
return;
}
wnd = GetAppWnd();
GetClientRect( wnd, &clrect );
newrect = clrect;
RequestScrollRect( &newrect );
SetScrollRect( newrect );
GetOffset( &offset );
if( GetScrollConfig() & SCROLL_HORZ ) {
SetScrollRange( wnd, SB_HORZ, newrect.left, newrect.right - clrect.right, FALSE );
SetScrollPos( wnd, SB_HORZ, offset.x, TRUE );
}
if( GetScrollConfig() & SCROLL_VERT ) {
SetScrollRange( wnd, SB_VERT, newrect.top, newrect.bottom - clrect.bottom, FALSE );
SetScrollPos( wnd, SB_VERT, offset.y, TRUE );
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?