📄 menu.c
字号:
/*
** $Id: menu.c,v 1.52 2004/10/25 04:04:17 snig Exp $
**
** menu.c: The Menu module.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 1999 ~ 2002 Wei Yongming.
**
** Create date: 1999.04.09
**
** Current maintainer: Wei Yongming.
**
** Used abbreviations in this file:
** Menu: mnu
** Popup: ppp
** Identifier: id
** Mnemonic: mnic
** Normal: nml
** Item: itm
** Modify records:
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
** TODO:
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "gal.h"
#include "internals.h"
#include "blockheap.h"
#include "menu.h"
/************************* MENUBAR allocation ********************************/
static BLOCKHEAP MBHeap;
inline static void InitFreeMBList (void)
{
InitBlockDataHeap (&MBHeap, sizeof (MENUBAR), SIZE_MB_HEAP);
}
inline static PMENUBAR MenuBarAlloc (void)
{
return (PMENUBAR) BlockDataAlloc (&MBHeap);
}
inline static void FreeMenuBar (PMENUBAR pmb)
{
BlockDataFree (&MBHeap, pmb);
}
inline static void DestroyFreeMBList (void)
{
DestroyBlockDataHeap (&MBHeap);
}
/************************* MENUITEM allocation *******************************/
static BLOCKHEAP MIHeap;
inline static void InitFreeMIList (void)
{
InitBlockDataHeap (&MIHeap, sizeof (MENUITEM), SIZE_MI_HEAP);
}
inline static PMENUITEM MenuItemAlloc (void)
{
return (PMENUITEM) BlockDataAlloc (&MIHeap);
}
inline static void FreeMenuItem (MENUITEM* pmi)
{
BlockDataFree (&MIHeap, pmi);
}
inline static void DestroyFreeMIList (void)
{
DestroyBlockDataHeap (&MIHeap);
}
/************************* TRACKMENUITEM heap *******************************/
static BLOCKHEAP TMIHeap;
inline static void InitFreeTMIList (void)
{
InitBlockDataHeap (&TMIHeap, sizeof (TRACKMENUINFO), SIZE_TMI_HEAP);
}
inline static PTRACKMENUINFO TrackMenuInfoAlloc (void)
{
return (PTRACKMENUINFO) BlockDataAlloc (&TMIHeap);
}
inline static void FreeTrackMenuInfo (TRACKMENUINFO* ptmi)
{
BlockDataFree (&TMIHeap, ptmi);
}
inline static void DestroyFreeTMIList(void)
{
DestroyBlockDataHeap (&TMIHeap);
}
/************************* Module initialization *****************************/
static BITMAP bmp_menuitem;
BOOL InitMenu (void)
{
InitFreeMBList ();
InitFreeMIList ();
InitFreeTMIList ();
return InitBitmap (HDC_SCREEN, 16, 12, 0, NULL, &bmp_menuitem);
}
/************************* Module termination *******************************/
void TerminateMenu (void)
{
DestroyFreeTMIList ();
DestroyFreeMBList ();
DestroyFreeMIList ();
UnloadBitmap (&bmp_menuitem);
}
/***************************** Menu creation *******************************/
HMENU GUIAPI LoadMenuFromFile (const char* filename, int id)
{
return 0;
}
HMENU GUIAPI CreateMenu (void)
{
PMENUBAR pmb;
if (!(pmb = MenuBarAlloc ()))
return 0;
pmb->category = TYPE_HMENU;
pmb->type = TYPE_MENUBAR;
pmb->head = NULL;
return (HMENU)pmb;
}
HMENU GUIAPI CreatePopupMenu (PMENUITEMINFO pmii)
{
PMENUITEM pmi;
if (!(pmi = MenuItemAlloc ()))
return 0;
pmi->category = TYPE_HMENU;
pmi->type = TYPE_PPPMENU;
pmi->next = NULL;
pmi->submenu = NULL;
pmi->mnutype = pmii->type;
pmi->mnustate = pmii->state;
pmi->id = pmii->id;
pmi->hbmpChecked = pmii->hbmpChecked;
pmi->hbmpUnchecked = pmii->hbmpUnchecked;
pmi->itemdata = pmii->itemdata;
// copy string.
if (pmii->type == MFT_STRING || pmii->type == MFT_BMPSTRING) {
int len = strlen ((char*)pmii->typedata);
pmi->typedata = (DWORD)FixStrAlloc (len);
if (len > 0)
strcpy ((char*)pmi->typedata, (char*)pmii->typedata);
}
else
pmi->typedata = pmii->typedata;
return (HMENU)pmi;
}
HMENU GUIAPI CreateSystemMenu (HWND hwnd, DWORD dwStyle)
{
HMENU hmnu;
MENUITEMINFO mii;
memset (&mii, 0, sizeof(MENUITEMINFO));
mii.type = MFT_STRING;
mii.id = 0;
mii.typedata = (DWORD)GetSysText(SysText[5]);
hmnu = CreatePopupMenu (&mii);
memset (&mii, 0, sizeof(MENUITEMINFO));
if (dwStyle & WS_MINIMIZEBOX) {
mii.type = MFT_STRING;
mii.state = 0;
mii.id = SC_MINIMIZE;
mii.typedata = (DWORD)GetSysText(SysText[6]);
InsertMenuItem(hmnu, 0, TRUE, &mii);
}
if (dwStyle & WS_MAXIMIZEBOX) {
mii.type = MFT_STRING;
if (dwStyle & WS_MAXIMIZE)
mii.state = MFS_DISABLED;
else
mii.state = 0;
mii.id = SC_MAXIMIZE;
mii.typedata = (DWORD)GetSysText(SysText[7]);
InsertMenuItem(hmnu, 1, TRUE, &mii);
mii.type = MFT_STRING;
if (dwStyle & WS_MAXIMIZE)
mii.state = 0;
else
mii.state = MFS_DISABLED;
mii.id = SC_RESTORE;
mii.typedata = (DWORD)GetSysText(SysText[8]);
InsertMenuItem(hmnu, 2, TRUE, &mii);
}
mii.type = MFT_SEPARATOR;
mii.state = 0;
mii.id = 0;
mii.typedata = 0;
InsertMenuItem(hmnu, 3, TRUE, &mii);
mii.type = MFT_STRING;
mii.state = 0;
mii.id = SC_CLOSE;
mii.typedata = (DWORD)GetSysText(SysText[9]);
InsertMenuItem(hmnu, 4, TRUE, &mii);
return hmnu;
}
static BOOL mnuInsertMenuItem (PMENUITEM pmi, PMENUITEM pnewmi,
int item, BOOL flag)
{
PMENUITEM ptmpmi;
int index;
if (flag) {
// Insert this new menu item at the start.
if (item == 0) {
pnewmi->next = pmi;
return TRUE;
}
index = 1;
while (pmi->next) {
if (index == item) {
ptmpmi = pmi->next;
pmi->next = pnewmi;
pnewmi->next = ptmpmi;
return FALSE;
}
index ++;
pmi = pmi->next;
}
}
else {
if (item == pmi->id) {
pnewmi->next = pmi;
return TRUE;
}
while (pmi->next) {
if (pmi->next->id == item) {
ptmpmi = pmi->next;
pmi->next = pnewmi;
pnewmi->next = ptmpmi;
return FALSE;
}
pmi = pmi->next;
}
}
// append this new menu item at the end.
pmi->next = pnewmi;
return FALSE;
}
int GUIAPI InsertMenuItem (HMENU hmnu, int item,
BOOL flag, PMENUITEMINFO pmii)
{
PMENUBAR pmb;
PMENUITEM pnewmi, pmi;
pmb = (PMENUBAR) hmnu;
if (pmb->category != TYPE_HMENU)
return ERR_INVALID_HANDLE;
if (!(pnewmi = MenuItemAlloc ()))
return ERR_RES_ALLOCATION;
pnewmi->category = TYPE_HMENU;
pnewmi->type = TYPE_NMLMENU;
pnewmi->mnutype = pmii->type;
pnewmi->mnustate = pmii->state;
pnewmi->id = pmii->id;
pnewmi->hbmpChecked = pmii->hbmpChecked;
pnewmi->hbmpUnchecked = pmii->hbmpUnchecked;
pnewmi->itemdata = pmii->itemdata;
pnewmi->next = NULL;
pnewmi->submenu = (PMENUITEM)(pmii->hsubmenu);
// copy string.
if (pmii->type == MFT_STRING || pmii->type == MFT_BMPSTRING) {
int len = strlen ((char*)pmii->typedata);
pnewmi->typedata = (DWORD)FixStrAlloc (len);
if (len > 0)
strcpy ((char*)pnewmi->typedata, (char*)pmii->typedata);
}
else
pnewmi->typedata = pmii->typedata;
if (pmb->type == TYPE_MENUBAR) {
pmi = pmb->head;
if (!pmi)
pmb->head = pnewmi;
else {
if (mnuInsertMenuItem (pmb->head, pnewmi, item, flag))
pmb->head = pnewmi;
}
}
else if (pmb->type == TYPE_PPPMENU) {
pmi = (PMENUITEM)hmnu;
if (!pmi->submenu)
pmi->submenu = pnewmi;
else {
if (mnuInsertMenuItem (pmi->submenu, pnewmi, item, flag))
pmi->submenu = pnewmi;
}
}
else
return ERR_INVALID_HMENU;
return 0;
}
static void mnuDeleteMenuItem (PMENUITEM pmi)
{
PMENUITEM ptmpmi;
PMENUITEM psubmi;
if (pmi->submenu) {
psubmi = pmi->submenu;
while (psubmi) {
ptmpmi = psubmi->next;
mnuDeleteMenuItem (psubmi);
psubmi = ptmpmi;
}
}
if (pmi->mnutype == MFT_STRING || pmi->mnutype == MFT_BMPSTRING)
FreeFixStr ((void*)pmi->typedata);
FreeMenuItem (pmi);
}
static PMENUITEM mnuRemoveMenuItem (PMENUITEM phead, int item, BOOL flag)
{
int index;
PMENUITEM pmi, ptmpmi;
if (!phead) return NULL;
if (flag) {
if (item == 0) {
pmi = phead->next;
if (!phead->submenu)
mnuDeleteMenuItem (phead);
return pmi;
}
pmi = phead;
index = 1;
while (pmi->next) {
if (index == item) {
ptmpmi = pmi->next;
pmi->next = pmi->next->next;
if (!ptmpmi->submenu)
mnuDeleteMenuItem (ptmpmi);
return phead;
}
index ++;
pmi = pmi->next;
}
}
else {
if (phead->id == item) {
pmi = phead->next;
if (!phead->submenu)
mnuDeleteMenuItem (phead);
return pmi;
}
pmi = phead;
while (pmi->next) {
if (pmi->next->id == item) {
ptmpmi = pmi->next;
pmi->next = pmi->next->next;
if (!ptmpmi->submenu)
mnuDeleteMenuItem (ptmpmi);
return phead;
}
pmi = pmi->next;
}
}
return phead;
}
int GUIAPI RemoveMenu (HMENU hmnu, int item, UINT flags)
{
PMENUBAR pmb;
PMENUITEM pmi;
pmb = (PMENUBAR) hmnu;
if (pmb->category != TYPE_HMENU)
return ERR_INVALID_HANDLE;
if (pmb->type == TYPE_MENUBAR)
pmb->head = mnuRemoveMenuItem (pmb->head, item,
flags & MF_BYPOSITION);
else if (pmb->type == TYPE_PPPMENU) {
pmi = (PMENUITEM) hmnu;
pmi->submenu = mnuRemoveMenuItem (pmi->submenu, item,
flags & MF_BYPOSITION);
}
else
return ERR_INVALID_HMENU; // this is a normal menu item.
return 0;
}
static PMENUITEM mnuDeleteMenu (PMENUITEM phead, int item, BOOL flag)
{
int index;
PMENUITEM pmi, ptmpmi;
if (!phead) return NULL;
if (flag) {
if (item == 0) {
pmi = phead->next;
mnuDeleteMenuItem (phead);
return pmi;
}
pmi = phead;
index = 1;
while (pmi->next) {
if (index == item) {
ptmpmi = pmi->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -