guimenu.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 902 行 · 第 1/2 页
C
902 行
/****************************************************************************
*
* 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 "guisysme.h"
#include "guimenu.h"
#include "guihook.h"
#include "guirmenu.h"
#include <string.h>
extern MENUITEM *GUIPopupMenu;
extern bool GUIXCreateFixedToolbar( gui_window *wnd );
static gui_menu_struct GUISeparator = {
NULL, 0, GUI_SEPARATOR
};
static void SetChecked( MENUITEM *menu, bool check )
{
if( menu != NULL ) {
if( check ) {
menu->flags |= ITEM_CHECKED;
} else {
menu->flags &= ~ITEM_CHECKED;
}
}
}
static bool IsChecked( MENUITEM *menu )
{
if( menu != NULL ) {
return( menu->flags & ITEM_CHECKED );
}
return( FALSE );
}
/*
* MenuConvert -- returns a copy of text with the first amp removed and
* assigns *flags to indicate the location of the amp (base 0)
* and if checked or not
*/
static bool MenuConvert( char *text, unsigned short *flags, char **new,
bool checked )
{
char *end;
int length;
int end_length;
char *new_str;
int char_offset;
if( flags != NULL ) {
*flags &= ~ITEM_CHAR_OFFSET; /* cancel prev info */
if( checked ) {
*flags |= ITEM_CHECKED;
}
}
if( text == NULL ) {
*new = NULL;
return( TRUE );
}
end = strchr( text, '&' );
length = strlen( text );
if( end == NULL ) {
end_length = 0;
} else {
end_length = strlen( end );
}
if( flags != NULL ) {
char_offset = length - end_length;
*flags |= ( char_offset & ITEM_CHAR_OFFSET );
}
if( end == NULL ) {
length ++; /* no & so need room for NULL as it doesn't replace & */
}
new_str = (char * )GUIMemAlloc( length );
*new = new_str;
if( new_str == NULL ) {
return( FALSE );
}
if( length == end_length ) {
end++; /* & at start */
strcpy( new_str, end );
} else {
strncpy( new_str, text, length - end_length );
if( end != NULL ) {
end++; /* past & */
strncpy( new_str + length - end_length, end, end_length - 1);
}
new_str[length - 1] = NULLCHAR;
}
return( TRUE );
}
/*
* GUIFreeMenuItems -- frees exactly what was allocated by GUICreateMenuItems
*/
void GUIFreeMenuItems( MENUITEM *menus )
{
int j;
if( menus == NULL ) return;
for( j = 0; !MENUENDMARKER( menus[j] ); j++ ) {
GUIMemFree( menus[j].name );
if( menus[j].popup != NULL ) {
GUIFreeMenuItems( menus[j].popup );
}
}
GUIMemFree( menus );
}
MENUITEM *GUIAllocMenuItems( int num_menus )
{
MENUITEM *menu;
menu = (MENUITEM *)GUIMemAlloc( sizeof( MENUITEM ) * ( num_menus + 1 ) );
if( menu != NULL ) {
memset( menu, 0, sizeof( MENUITEM ) * ( num_menus + 1 ) );
}
return( menu );
}
/*
* GetNumItems -- count the number of items in the menu array, excluding
* the end marker
*/
static int GetNumItems( MENUITEM *menu )
{
int i;
int prev_num;
if( menu == NULL ) {
return( 0 );
}
prev_num = 0;
for( i = 0; !MENUENDMARKER( menu[i] ); i++ ) {
prev_num++;
}
return( prev_num );
}
static bool GetMenu( int *depth, int num_menus, MENUITEM *menu, unsigned id,
MENUITEM **pmenu, int *index, MENUITEM ***to_replace )
{
int i;
int num_popup_menus;
for( i = 0; i < num_menus; i++ ) {
uiyield();
if( menu[i].event == id ) {
*pmenu = &menu[i];
if( index != NULL ) {
*index = i;
}
return( TRUE );
}
if( depth ) {
(*depth)++;
}
if( menu[i].popup != NULL ) {
num_popup_menus = GetNumItems( menu[i].popup );
if( GetMenu( depth, num_popup_menus, menu[i].popup, id,
pmenu, index, to_replace ) ) {
if( ( to_replace != NULL ) && ( *to_replace == NULL ) ) {
*to_replace = &menu[i].popup;
}
return( TRUE );
}
}
if( depth ) {
(*depth)--;
}
}
return( FALSE );
}
/*
* GUIGetMenu -- get the MENUITEM * for the given id. Return TRUE if it
* was found in the vbarmenu.
*/
static bool GUIGetMenu( gui_window *wnd, int id, MENUITEM **menu, int *index,
MENUITEM ***to_replace, bool floating )
{
MENUITEM **the_menu;
bool num_menus;
bool vbar;
int depth;
if( to_replace != NULL ) {
*to_replace = NULL;
}
if( index != NULL ) {
*index = 0;
}
if( menu == NULL ) {
return( FALSE );
} else {
*menu = NULL;
}
vbar = FALSE;
if( floating ) {
the_menu = &GUIPopupMenu;
} else {
if( wnd->menu != NULL ) {
the_menu = &wnd->menu;
} else {
if( wnd->vbarmenu == NULL ) {
return( FALSE );
}
the_menu = &wnd->vbarmenu->titles;
vbar = TRUE;
}
}
num_menus = GetNumItems( *the_menu );
depth = 0;
if( GetMenu( &depth, num_menus, *the_menu, id, menu, index, to_replace ) ) {
if( ( to_replace != NULL ) && ( *to_replace == NULL ) ) {
*to_replace = the_menu;
}
if ( vbar && depth ) {
vbar = FALSE;
}
return( vbar );
}
return( FALSE );
}
int GUIGetMenuPopupCount( gui_window *wnd, int id )
{
MENUITEM *menu;
GUIGetMenu( wnd, id + GUI_FIRST_USER_EVENT, &menu, NULL, NULL, FALSE );
if( menu && menu->popup ) {
return( GetNumItems( menu->popup ) );
} else {
return( -1 );
}
}
bool GUIEnableMenuItem( gui_window *wnd, int id, bool enable, bool floating )
{
MENUITEM *menu;
bool vbar;
vbar = GUIGetMenu( wnd, id + GUI_FIRST_USER_EVENT, &menu, NULL, NULL, floating );
if( menu == NULL ) {
return( FALSE );
}
if( enable ) {
GUIChangeMenu( menu, GUI_ENABLED );
} else {
GUIChangeMenu( menu, GUI_GRAYED );
}
if( vbar ) {
/* if the menu item changed was in the top bar of menus,
* tell ui that it has changed.
*/
uimenubar( wnd->vbarmenu );
} else {
uisetmenudesc();
}
return( TRUE );
}
bool GUISetMenuText( gui_window *wnd, int id, char *text, bool floating )
{
MENUITEM *menu;
bool vbar;
char *new;
bool checked;
vbar = GUIGetMenu( wnd, id + GUI_FIRST_USER_EVENT, &menu, NULL, NULL, floating );
if( menu == NULL ) {
return( FALSE );
}
checked = IsChecked( menu );
if( !MenuConvert( text, &menu->flags, &new, checked ) ) {
return( FALSE );
}
GUIMemFree( menu->name );
menu->name = new;
if( vbar ) {
/* if the menu item changed was in the top bar of menus,
* tell ui that it has changed.
*/
uimenubar( wnd->vbarmenu );
} else {
uisetmenudesc();
}
return( TRUE );
}
bool GUICheckMenuItem( gui_window *wnd, int id, bool check, bool floating )
{
bool vbar;
MENUITEM *menu;
vbar = GUIGetMenu( wnd, id + GUI_FIRST_USER_EVENT, &menu, NULL, NULL, floating );
if( menu == NULL ) {
return( FALSE );
}
SetChecked( menu, check );
if( vbar ) {
/* if the menu item changed was in the top bar of menus,
* tell ui that it has changed.
*/
uimenubar( wnd->vbarmenu );
} else {
uisetmenudesc();
}
return( TRUE );
}
void GUIChangeMenu( MENUITEM *menu, gui_menu_styles style )
{
if( style & GUI_GRAYED ) {
menu->flags |= ITEM_GRAYED;
} else {
menu->flags &= ~ITEM_GRAYED;
}
}
static bool GUISetMenuItems( int num_menus, MENUITEM *menu,
gui_menu_struct *info )
{
int i;
int j;
j = 0;
for( i = 0; i < num_menus; i ++ ) {
uiyield();
if( !(info[i].style & GUI_IGNORE) ) {
if( info[i].style & GUI_SEPARATOR ) {
menu[j].flags |= ITEM_SEPARATOR;
} else {
if( !MenuConvert( info[i].label, &menu[j].flags, &menu[j].name,
info[i].style & GUI_MENU_CHECKED ) ) {
return( FALSE );
}
GUIChangeMenu( &menu[j], info[i].style );
}
menu[j].event = GUI_FIRST_USER_EVENT + info[i].id;
j++;
}
}
return( TRUE );
}
int GUIGetNumIgnore( gui_menu_struct *info, int num_menus )
{
int num_ignore;
int i;
num_ignore = 0;
for( i = 0; i < num_menus; i++ ) {
if( info[i].style & GUI_IGNORE ) {
num_ignore++;
}
}
return( num_ignore );
}
/*
* GUICreateMenuItems -- converts the gui_menu_struct to an array of MENUITEM
*/
bool GUICreateMenuItems( int num_menus, gui_menu_struct *info,
MENUITEM **pmenu )
{
int num_ignore;
int i;
int j;
MENUITEM *menu;
if( num_menus <= 0 ) {
*pmenu = NULL;
return( TRUE );
}
num_ignore = GUIGetNumIgnore( info, num_menus );
if( num_ignore >= num_menus ) {
*pmenu = NULL;
return( TRUE );
}
*pmenu = GUIAllocMenuItems( num_menus - num_ignore );
menu = *pmenu;
if( menu == NULL ) {
return( FALSE );
}
if( !GUISetMenuItems( num_menus, menu, info ) ) {
return( FALSE );
}
j = 0;
for( i = 0; i < num_menus; i++ ) {
uiyield();
if( !( info[i].style & GUI_IGNORE ) ) {
if( info[i].num_child_menus > 0 ) {
if( !GUICreateMenuItems( info[i].num_child_menus,
info[i].child, &menu[j].popup ) ) {
return( FALSE );
}
}
j++;
}
}
return( TRUE );
}
bool GUIAllocVBarMenu( VBARMENU **pmenu )
{
VBARMENU *menu;
if( pmenu == NULL ) {
return( FALSE );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?