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 + -
显示快捷键?