uipopup.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 651 行 · 第 1/2 页
C
651 行
/****************************************************************************
*
* 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 <string.h>
#include <ctype.h>
#include "uidef.h"
#include "uimenu.h"
#define NO_SELECT -1
static int ScrollPos = NO_SELECT;
static int PrevScrollPos = NO_SELECT;
static EVENT PopupEvents[] = {
EV_FIRST_EDIT_CHAR, EV_LAST_EDIT_CHAR,
EV_ALT_Q, EV_ALT_M, // JD - handle alt keys
EV_NO_EVENT,
EV_ALT_PRESS,
EV_ALT_RELEASE,
EV_CURSOR_UP,
EV_CURSOR_DOWN,
EV_CURSOR_RIGHT,
EV_ESCAPE,
EV_RETURN,
EV_MOUSE_MOVE,
EV_MOUSE_DCLICK,
EV_MOUSE_DCLICK_R,
EV_MENU_ACTIVE,
EV_NO_EVENT
};
static EVENT ListToClose[] = {
EV_NO_EVENT,
EV_CURSOR_LEFT,
EV_NO_EVENT,
};
static EVENT LeftMouseEvents[] = {
EV_NO_EVENT,
EV_MOUSE_PRESS,
EV_MOUSE_DRAG,
EV_MOUSE_RELEASE
};
static EVENT RightMouseEvents[] = {
EV_NO_EVENT,
EV_MOUSE_PRESS_R,
EV_MOUSE_DRAG_R,
EV_MOUSE_RELEASE_R
};
static bool InArea( ORD row, ORD col, SAREA *area )
{
return( ( ( row >= area->row ) && ( row < ( area->row + area->height ) ) &&
( col >= area->col ) && ( col < ( area->col+ area->width ) ) ) );
}
/*
* DrawMenuText -- display the line of menu text
*/
static void DrawMenuText( int index, MENUITEM *menu, bool curr, DESCMENU *desc )
{
uidisplayitem( &menu[index], desc, index + 1, curr );
uimenucurr( &menu[index] );
}
static bool okvert( SAREA *area, SAREA *keep_inside )
{
return( ( area->row + area->height ) <=
( keep_inside->row + keep_inside->height ) );
}
static bool okhorz( SAREA *area, SAREA *keep_inside )
{
return( ( area->col + area->width ) <=
( keep_inside->col + keep_inside->width ) );
}
/*
* RepositionBox -- reposition the box as needed fit on screen
*/
static bool RepositionBox( SAREA *area, SAREA *keep_inside, SAREA *keep_visible )
{
bool horz_ok;
bool vert_ok;
ORD row;
ORD col;
if( area->width > keep_inside->width ) {
return( FALSE );
}
if( area->height > keep_inside->height ) {
return( FALSE );
}
horz_ok = FALSE;
vert_ok = FALSE;
if( keep_visible != NULL ) {
row = area->row;
area->row = keep_visible->row - 1;
vert_ok = okvert( area, keep_inside );
if( !vert_ok ) {
area->row = keep_visible->row - area->height + 1;
vert_ok = okvert( area, keep_inside );
if( !vert_ok ) {
area->row = row;
}
}
col = area->col;
area->col = keep_visible->col + keep_visible->width;
horz_ok = okhorz( area, keep_inside );
if( !horz_ok ) {
area->col = keep_visible->col - area->width + 1;
horz_ok = okhorz( area, keep_inside );
if( !horz_ok ) {
area->col = col;
}
}
}
horz_ok = okhorz( area, keep_inside );
vert_ok = okvert( area, keep_inside );
if( !horz_ok ) { /* too far to right, move left as far as needed */
area->col = keep_inside->col + keep_inside->width - area->width;
}
if( !vert_ok ) { /* too close to bottom, move above point */
if( area->row <= area->height + 1 ) {
/* no room to go completely above */
area->row = keep_inside->row + keep_inside->height -
area->height;
} else {
/* go completely above */
area->row -= area->height + 1;
}
}
return( TRUE );
}
/*
* GetNewPos -- calculate new position based on circular menu
*/
static int GetNewPos( int pos, int num )
{
if( pos >= num ) {
return( 0 );
} else if( pos < 0 ) {
return( num - 1 );
} else {
return( pos );
}
}
/*
* SkipSeparators -- calculate new position, skipping separators
*/
static int SkipSeparators( int diff, int num, MENUITEM *menu )
{
int pos;
pos = GetNewPos( ScrollPos + diff, num );
while( MENUSEPARATOR( menu[pos] ) ) {
pos = GetNewPos( pos + diff, num );
}
return( pos );
}
static void ChangePos( int new_pos, MENUITEM *menu, DESCMENU *desc )
{
ScrollPos = new_pos;
if( PrevScrollPos != NO_SELECT ) {
DrawMenuText( PrevScrollPos, menu, FALSE, desc );
}
PrevScrollPos = ScrollPos;
DrawMenuText( ScrollPos, menu, TRUE, desc );
}
/*
* Scroll -- Scroll which item is selected in the floating popup
* Draw old selection normally, hightlight new selection
*/
static void Scroll( int pos, int num, MENUITEM *menu, DESCMENU *desc )
{
ChangePos( GetNewPos( pos, num ), menu, desc );
}
static void DoEnd( UI_WINDOW *window )
{
uiclosepopup( window );
}
/*
* SendEvent -- calculate event to return, return whether or not to end
* popup menu
*/
static bool SendEvent( int num, MENUITEM *menu, int index,
UI_WINDOW *window, EVENT *ev )
{
*ev = EV_NO_EVENT;
if( ( index < num ) && ( index >= 0 ) ) {
DoEnd( window );
if( !( MENUGRAYED( menu[index] ) ) ) {
*ev = menu[index].event;
return( TRUE );
}
return( TRUE );
} else {
return( FALSE );
}
}
/*
* KeyboardSelect -- See if the pressed key selects one of the menu items
*/
static bool KeyboardSelect( EVENT ev, int num, MENUITEM *menu, DESCMENU *desc )
{
int i;
char up, alt_char;
int offset;
// JD - don't check uimenugetaltpressed. The menu code may not have seen
// the alt key go down.
alt_char = uialtchar( ev );
if ( alt_char ) {
up = toupper ( alt_char );
} else {
up = toupper( ev );
}
for( i = 0; i < num; i++ ) {
if( !MENUSEPARATOR( menu[i] ) && !MENUGRAYED( menu[i] ) ) {
offset = CHAROFFSET( menu[i] );
if( ( offset < strlen( menu[i].name ) ) &&
( toupper( menu[i].name[offset] ) == up ) ) {
ChangePos( i, menu, desc );
return( TRUE );
}
}
}
return( FALSE );
}
global EVENT uicreatepopupdesc( MENUITEM *menu, DESCMENU *desc, bool left,
bool right, EVENT curr_item, bool sub )
{
SAREA keep_inside;
keep_inside.row = 0;
keep_inside.col = 0;
keep_inside.width = UIData->width;
keep_inside.height = UIData->height;
return( uicreatepopupinarea( menu, desc, left, right, curr_item,
&keep_inside, sub ) );
}
static bool createsubpopup( MENUITEM *menu, bool left, bool right,
SAREA *keep_inside, EVENT *new_ev, UI_WINDOW *window,
DESCMENU *desc, bool set_default )
{
SAREA keep_visible;
int this_scroll_pos;
int this_prev_scroll_pos;
EVENT ev;
ORD row;
ORD col;
int curr_row;
DESCMENU sub_desc;
int num;
EVENT default_event;
MENUITEM *curr_popup;
if ( MENUGRAYED(menu[ScrollPos]) ) {
curr_popup = NULL;
} else {
curr_popup = menu[ScrollPos].popup;
}
if( curr_popup != NULL ) {
row = desc->area.row + ScrollPos;
col = desc->area.col + desc->area.width - 2;
keep_visible.row = row + 1;
keep_visible.col = desc->area.col;
keep_visible.width = desc->area.width - 2;
keep_visible.height = 1;
uiposfloatingpopup( curr_popup, &sub_desc, row, col,
keep_inside, &keep_visible );
this_scroll_pos = ScrollPos;
this_prev_scroll_pos = PrevScrollPos;
if( set_default && ( curr_popup != NULL ) ) {
default_event = curr_popup[0].event;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?