Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

343 lines
6.6 KiB

/*
* menu.c - String menu functions
*
* routines to deal with menu's by string name
*
* a menu string name has the following format
*
* popup.popup.item
*
* NOTE all tabs, &, and spaces are ignored when seaching for a menu
* the last period of a series "..." is the delimiter
*
* IE
* &File.Open... - "Open..." in the File menu
* Color.fill.red - "red" in the "fill" popup of the Color menu
* &Run! - "Run!" top level menu
*/
#include <windows.h>
#include "menu.h"
static int FindItem(HMENU hmenu, PTSTR sz);
static HMENU FindMenu(HMENU hmenu, PTSTR sz, int *ppos);
static void PSStrip(PTSTR sz);
/*
* AppendMenuSz() - add a new menu item to a menu
*
* hmenu menu to add item to
* szMenu menu item to add.
* id menu id
* mf menu flags
*
* returns 0 - insert failed
* 1 - insert ok
* 2 - item added and a new top level popup was created
*/
BOOL AppendMenuSz(HMENU hmenu, PTSTR szMenu, UINT id, UINT mf)
{
HMENU hmenuSub;
int pos;
TCHAR buf[80];
PTSTR pch;
mf &= (MF_CHECKED|MF_UNCHECKED|MF_ENABLED|MF_GRAYED|MF_DISABLED);
/*
* find the first period
* buf will contain popup menu name and pch will point to the rest
*/
lstrcpy(buf,szMenu);
for (pch = buf; *pch && *pch != TEXT('.'); pch++)
;
// handle items that end in periods (like "File.Open...")
while (pch[0]==TEXT('.') && pch[1]==TEXT('.')) // skip a run of .'s
pch++;
if (pch[1]==0)
pch++;
if (*pch)
*pch++ = 0;
/*
* is the popup menu there?
*/
pos = FindItem(hmenu,buf);
/*
* popup was found, now add item to popup
*/
if (pos != -1)
return AppendMenuSz(GetSubMenu(hmenu,pos),pch,id,mf);
/*
* popup was NOT found, now add new popup or item
*/
if (*pch)
{
/*
* we need to add a popup
*/
BOOL f;
hmenuSub = CreateMenu();
f = AppendMenu(hmenu,MF_STRING|MF_POPUP,(UINT)hmenuSub,buf);
/*
* now recurse and add the rest of the menu item to the popup
*/
if (f && AppendMenuSz(hmenuSub,pch,id,mf))
return 2; // return fact that a new popup was added
else
return FALSE;
}
else
{
if (buf[0] == TEXT('-'))
mf |= MF_SEPARATOR;
else
mf |= MF_STRING;
return AppendMenu(hmenu,mf,id,buf);
}
}
/*
* CheckMenuSz() - check/uncheck a menu given it's name
*
* hmenu menu
* szMenu menu item name.
* mf menu flags
*/
BOOL CheckMenuSz(HMENU hmenu, PTSTR szMenu, BOOL f)
{
int pos;
if (hmenu = FindMenu(hmenu,szMenu,&pos))
return CheckMenuItem(hmenu, pos, (f ? MF_CHECKED : MF_UNCHECKED) | MF_BYPOSITION);
return 0;
}
/*
* EnableMenuSz() - enable/disable menu given it's name
*
* hmenu menu
* szMenu menu item name.
* mf menu flags
*/
BOOL EnableMenuSz(HMENU hmenu, PTSTR szMenu, BOOL f)
{
int pos;
if (hmenu = FindMenu(hmenu,szMenu,&pos))
return EnableMenuItem(hmenu, pos, (f ? MF_ENABLED : MF_GRAYED) | MF_BYPOSITION);
return 0;
}
/*
* DeleteMenuSz() - delete a menu given it's name
*
* hmenu menu
* szMenu menu item name.
*/
BOOL DeleteMenuSz(HMENU hmenu, PTSTR szMenu)
{
int pos;
if (hmenu = FindMenu(hmenu,szMenu,&pos))
return DeleteMenu(hmenu, pos, MF_BYPOSITION);
return 0;
}
/*
* FindItem()
*
* find a menu item given the item name
*
* IE "Open"
*
* returns item number (0 based) or -1 if not found.
*
*/
static int FindItem(HMENU hmenu, PTSTR sz)
{
TCHAR ach[128];
TCHAR buf[80];
int i,n;
if (sz == NULL || !*sz || !hmenu)
return -1;
lstrcpy(buf,sz);
PSStrip(buf);
n = GetMenuItemCount(hmenu);
for(i=0; i<=n; i++)
{
// if (GetMenuState(hmenu,i,MF_BYPOSITION) & MF_SEPARATOR)
// continue;
ach[0] = 0;
GetMenuString(hmenu,i,ach,sizeof(ach)/sizeof(ach[0]),MF_BYPOSITION);
PSStrip(ach);
if (!lstrcmpi(buf,ach))
return i;
}
return -1;
}
/*
* FindMenu()
*
* find a menu item given the menu name and the item name separated by
* a period.
*
* IE "File.Open"
*
*/
static HMENU FindMenu(HMENU hmenu, PTSTR sz, int *ppos)
{
TCHAR buf[80];
PTSTR pch;
int pos;
if (!sz || !*sz || !hmenu)
return NULL;
lstrcpy(buf,sz);
for (pch = buf; *pch && *pch != TEXT('.'); pch++)
;
while (pch[0]==TEXT('.') && pch[1]==TEXT('.'))
pch++;
if (*pch)
*pch++ = 0;
/*
* buf is the menu name and pch is the item name
*/
pos = FindItem(hmenu,buf);
*ppos = pos;
if (pos == -1)
return NULL;
if (*pch)
{
hmenu = GetSubMenu(hmenu,pos);
return FindMenu(hmenu,pch,ppos);
}
return hmenu;
}
/*
* PSStrip()
*
* remove all nasty characters from a menu string that would inhibit
* comparison. all '&' and spaces are removed allong with truncating
* the string at the first tab found.
*
*/
static void PSStrip(PTSTR sz)
{
PTSTR pch;
#define chDOT TEXT('\xB7')
AnsiUpper(sz);
for (pch = sz; *sz && *sz != TEXT('\t'); sz++)
{
if (*sz != TEXT('&') && *sz != 0x08 && *sz != TEXT(' '))
*pch++ = *sz;
}
*pch = 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
typedef struct _CMD {
struct _CMD * next;
UINT id;
LPARAM lParam;
CMDPROC CmdProc;
} CMD;
UINT NextCmdId = CMDID_START;
CMD* CmdList;
CMD *NewCmd(CMDPROC CmdProc, LPARAM lParam)
{
CMD *pc;
pc = (CMD*)LocalAlloc(LPTR, sizeof(CMD));
if (pc == NULL)
return 0;
pc->id = NextCmdId++;
pc->lParam = lParam;
pc->CmdProc = CmdProc;
pc->next = CmdList;
CmdList = pc;
return pc;
}
CMD *FindCmd(UINT id)
{
CMD *pc;
for (pc = CmdList; pc; pc=pc->next)
{
if (pc->id == id)
return pc;
}
return NULL;
}
/*
* AddMenuCmd()
*/
UINT AddMenuCmd(HWND hwnd, PTSTR szMenu, CMDPROC CmdProc, LPARAM lParam)
{
CMD *pc;
HMENU hmenu;
hmenu = GetMenu(hwnd);
if (hmenu == NULL)
{
hmenu = CreateMenu();
SetMenu(hwnd, hmenu);
}
pc = NewCmd(CmdProc, lParam);
if (pc == NULL)
return 0;
if (AppendMenuSz(hmenu, szMenu, pc->id, MF_ENABLED) == 2)
DrawMenuBar(hwnd);
return pc->id;
}
LRESULT HandleCommand(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CMD *pc;
switch (msg)
{
case WM_COMMAND:
if ((pc = FindCmd(LOWORD(wParam))) && pc->CmdProc)
{
pc->CmdProc(hwnd, pc->lParam);
}
break;
}
return 0;
}