⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.c

📁 dos 1.0 其中包含quick basic源代码、内存管理himem emm386 发展历史
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	SCCSWHAT() */
/*
	COW : Character Oriented Windows

	menu.c : menu handler
*/

#define COW
#include <cow.h>

#include <umenu.h>
#include <uwindow.h>
#include <uisa.h>
#include <uevent.h>
#include <vkey.h>
#include <uscreen.h>
#include <uutil.h>
#include <kkeyboar.h>

#include "dialog.h"
#include "event.h"
#include "window.h"
#include "screen.h"
#include "util.h"
#include "case.h"
#include "overlap.h"
#include "shadow.h"

#ifdef DUAL
#include <os2.h>
extern	WORD	fProtectMode;
#else
#ifdef DOS5
#include <os2.h>
#endif
#endif

#include "menu.h"
#include "_menu.h"


#ifdef KANJI
PUBLIC BOOL fKanaAccel = FALSE;		/* Kana accelerators ?? */
#endif /*KANJI*/


#define FShowMenuBar()	(pmenubarCur != NULL)
STATIC PMENUBAR pmenubarCur; 		/* current menu bar being displayed */
STATIC ARC arcMenu;
STATIC PWND pwndMenu;

STATIC BYTE FAR *lpbMenu;	/* where the screen image under menu is kept */

#ifdef ACCEL_MULTIPLE
BOOL	fOneOfMultiple;		/* => if one of multiple matching accelerators */
#endif /*ACCEL_MULTIPLE*/

#ifdef	MULTIPLE_ACTION
WORD	vkActionPrim = VK_MENU;		/* Primary Action Key */
WORD	vkActionSec = VK_F11;		/* Secondary Action Key */
WORD	vkCancelPrim = LOBYTE(VK_ESCAPE);	/* Primary Cancel Key */
WORD	vkCancelSec = VK_F12;		/* Secondary Cancel Key */
#endif	/* MULTIPLE_ACTION */

/* Menu Info : see note in MENU.H */
extern	MNI mniCur;
/* PRIVATE MNI mniCur = { imenuNil, iitemNil, NULL, FALSE, FALSE, FALSE }; */



STATIC MENU *pmenuFound;
/* set by FindMenuItem to indicate which menu contains
   the item that was found */


/* forward */
STATIC PMENUITEM PmenuitemOfPmenu(PMENU);

/* menus */
STATIC VOID	SelectMenu(WORD);
STATIC VOID	HiliteMenuTitle(BOOL);
STATIC VOID	ReportMenuInactive(void);
STATIC VOID	OpenMenuCur(void);
#ifdef	DIALOG_NOSAVE
STATIC VOID	DrawMenuCur(void);
#endif	// DIALOG_NOSAVE
STATIC VOID	CloseMenuCur(BOOL);

/* menu title selection */
STATIC VOID	HiliteMenuMnem(BOOL);
STATIC BOOL	FMakeSelection(void);
STATIC WORD	ImenuPickVk(WORD);
STATIC WORD	ImenuPickMsp(MSP);

/* menu items */
STATIC VOID	DrawMenuItem(AX, AX, AY, PMENUITEM);
STATIC VOID	HiliteItem(BOOL);
STATIC BOOL	FSelectItem(WORD);
STATIC BOOL	FMatchItemVk(WORD);
STATIC BOOL	FSelectItemMsp(MSP);
STATIC BOOL	FInsideMenuMsp(AX, AY);

/* filter */
STATIC VOID	SetIdleState(void);

/* utilities */
STATIC BOOL	FTranslateAccelerator(WORD, WORD);
STATIC BOOL	FMatchVkCh(WORD, char);
STATIC char *	SzItem(PMENUITEM);

STATIC VOID	SendMenuHelp(WORD);

#ifdef	MENU_NOSAVE
extern VOID	FAR PASCAL	ScreenRedraw(VOID);
#endif	// MENU_NOSAVE




STATIC PMENUITEM
PmenuitemOfPmenu(pmenu)
/*
  -- return address of first menu item in menu
*/
REGISTER PMENU pmenu;
	{
	return (pmenu->fHandle ? *(pmenu->u.prgmenuitem) : pmenu->u.rgmenuitem);
	}



PUBLIC PMENUITEM FARPUBLIC
FindMenuItem(id)
WORD id;
/* FindMenuItem - Find specified menu item in tree */
	{
	StartPublic();
	PMENU pmenu = pmenubarCur->rgmenu;
	WORD cmenu = pmenubarCur->cmenu;

	while (cmenu--)
		{
		REGISTER PMENUITEM pmenuitem = PmenuitemOfPmenu(pmenu);
		REGISTER WORD citem = pmenu->citem;
		
		while (citem--)
			{
			if (pmenuitem->idItem == id &&
			    !pmenuitem->fSeparator)
				{
				pmenuFound = pmenu;
				ReturnPublic(pmenuitem, PMENUITEM);
				}
			pmenuitem++;
			}
		pmenu++;
		}
	ReturnPublic(NULL, PMENUITEM);
	}




PUBLIC VOID FARPUBLIC
InitMenu(pwnd, pmenubar)
/*
  -- initialize menu state
*/
REGISTER PWND pwnd;
PMENUBAR pmenubar;
	{
	StartPublic();

	CloseMenuCur(TRUE);
	ReportMenuInactive();

	AssertSz(mniCur.imenu == imenuNil, "Init Menu while another menu still active");
	mniCur.iitem = iitemNil;
	mniCur.fMouse = FALSE;
	pwndMenu = pwnd;
	pmenubarCur = pmenubar;
	FEnableMenuBar(pwnd != NULL);
	DrawMenubar();
	StopPublic();
	}



PUBLIC VOID FARPUBLIC
DrawMenubar()
/*
  -- Draw Menu Bar and optionally fill with MENU item strings
*/
	{
	StartPublic();
	REGISTER PMENU pmenu;
	REGISTER WORD imenu;

	if (!FShowMenuBar())
		return;

	DrawThisWnd(NULL);

	FillArc(axMenuMin, ayMenu, axMenuMac, ayMenu+1, ' ', isaMenu);

	for (imenu = 0, pmenu = pmenubarCur->rgmenu;
	    imenu < pmenubarCur->cmenu;
	    imenu++, pmenu++)
		{
		WORD di = pmenu->fEnabled ? dmTextOnly :
			DiNormal(isaDisabledMenuItem);

		TextOutAbs(axMenuMin + pmenu->rxTitle, ayMenu,
		    pmenu->pchTitle, pmenu->cchTitle, di);
#ifdef KANJI
		/* kana accelerator at start ? */
		if (fKanaAccel)
			CharOutAbs(axMenuMin + pmenu->rxTitle, ayMenu,
			    pmenu->chKanaAccel, di);
#endif
		}

#ifdef DEBUG
	/* special stuff if we want to redraw menubar while not idle,
		i.e. for the HELLO application.
	*/
	if (FMenuActive())
		HiliteMenuTitle(TRUE);
#endif /*DEBUG*/

	StopPublic();
	}

/*****************************************************************************/


STATIC VOID
SelectMenu(imenu)
/*
  -- select the specified menu (may be imenuNil)
  -- clears old menu title
  -- modifies mniCur.imenu
*/
WORD imenu;
	{
	Assert(mniCur.pmenuOpen == NULL);	/* no drop downs open */

	/* if we don't have a menubar -- get one !! */
	if (pmenubarCur == NULL)
		{
		SendMessageShort(pwndMenu, WM_MENUSTART);
		AssertSz(pmenubarCur != NULL, "WM_MENUSTART error");
		}

	if (imenu != mniCur.imenu)
		{
		/* close old */
		CloseMenuCur(TRUE);		/* close current */
		HiliteMenuTitle(FALSE);	/* & clear title */
		mniCur.imenu = imenu;
		mniCur.iitem = iitemNil;
		HiliteMenuTitle(TRUE);	/* hilite new title */
		}
	}



STATIC VOID
HiliteMenuTitle(fHilite)
/*
  -- hilite/unhilite the menu title "hilite" characters, for current menu
  -- do nothing if no current menu
  -- menu should not be open.
*/
BOOL fHilite;		/* hilite ? */
	{
	REGISTER AX ax;
	REGISTER PMENU pmenu;
	AX axRight;

	if (!FShowMenuBar() || mniCur.imenu == imenuNil)
		return;

	DrawThisWnd(NULL);

	Assert(mniCur.imenu != imenuNil);
	Assert(!FMenuOpen());
	MoveHardwareCursor(0, 0, FALSE);

	/* 1 character before & after */
	pmenu = &pmenubarCur->rgmenu[mniCur.imenu];
	ax = ((AX) pmenu->rxTitle) - daxBorder;
	axRight = ax + pmenu->cchTitle + 2;
	/* Pin hilite to edges of screen */
	if (pmenu->rxTitle == 0)
		ax = 0;
	if (axRight > axMax)
		axRight = axMax;

	FillArc(ax, ayMenu, axRight, ayMenu + 1, '\0',
	     (fHilite) ? (dmAttrOnly | isaMenuSelected) :
	      ((pmenu->fEnabled) ? (dmAttrOnly | isaMenu) :
				   (dmAttrOnly | isaDisabledMenuItem) ));
	ax = ((AX) pmenu->rxTitle) + (BYTE) pmenu->ichHilite;
	Assert(ax < axMax);	/* Hilited character must be on screen */
	/* only single width characters for accelerators */
	if (mniCur.fMenuMnem)
		FillArc(ax, ayMenu, ax + 1, ayMenu + 1, '\0',
		    (fHilite) ? (dmAttrOnly | isaMenuHiliteSel) :
		     (dmAttrOnly | isaMenuHilite));

	if (fHilite)
		SendMessage(pwndMenu, WM_MENUSELECT, pmenu->idMenu,
		    MAKELONG(pmenu, mmdMenu));
	}



STATIC VOID
ReportMenuInactive()
/*
  -- send a MENUSELECT message with NULL pmenuitem
  -- normally application will clear the help line
*/
	{
	Assert(mmdItem == 0);
	if (pwndMenu != NULL)
		SendMessageShort(pwndMenu, WM_MENUSELECT);
	}




STATIC VOID
OpenMenuCur()
/*
  -- open current menu (mniCur.imenu)
  -- all other menus must be closed
  -- turn of mnemonics in menu titles
  -- if imenuNil then do nothing
  -- if items, select first one
*/
	{
	REGISTER PMENU pmenu;
	AX axLeft, axRight;
#ifdef	DIALOG_NOSAVE
	AY ayBottom, ayTop;
#else
	AY ay, ayBottom, ayTop;
	WORD citem;
#endif

	Assert(mniCur.pmenuOpen == NULL);
	DrawThisWnd(NULL);
	HiliteMenuMnem(FALSE);

	if (mniCur.imenu == imenuNil)
		return;

	pmenu = mniCur.pmenuOpen = &pmenubarCur->rgmenu[mniCur.imenu];

	SendMessage(pwndMenu, WM_INITMENUPOPUP, pmenu->idMenu,
	    MAKELONG(pmenu, 0));	/* Must not enter dialogs */

	BeginDraw();

	if (pmenu->citem)
		{
#ifndef DIALOG_NOSAVE
		REGISTER PMENUITEM pmenuitem;
#endif	// DIALOG_NOSAVE
		WORD	cw;

		arcMenu.axLeft = axLeft = (AX) pmenu->rxTitle + daxMenuBox;
			/* to left side of box */
		arcMenu.axRight = axRight = (AX) pmenu->rxTitle +
		    pmenu->cchitemMax + 2;
			/* bord+gap+"text"+gap+bord */

		/* adjust for too near screen borders */
		if (axRight > axMac - daxShadow)
			{
			/* adjust for too large (too near right) */
			arcMenu.axLeft = axLeft = axLeft - (axRight - 
						(axMac - daxShadow));
			arcMenu.axRight = axRight = (axMac - daxShadow);
			}
		if (pmenu->rxTitle < -daxMenuBox)
			{
			/* adjust for too small (too near left) */
			arcMenu.axRight = axRight - axLeft;
			arcMenu.axLeft = 0;
			}

		arcMenu.ayTop = ayTop = ayMenu + 1;
			/* 1 for menu title */
		arcMenu.ayBottom = ayBottom = ayTop + pmenu->citem + 2;
			/* 2 for top and bottom sides of menu box */

		cw = (WORD) (ayBottom - ayTop + dayShadow) *
		    (WORD) (axRight - axLeft + daxShadow + daxDbcs * 2);
#ifdef SCREEN_FFONT
		if (fFontAvailable)
			cw *= 2;
#endif /*SCREEN_FFONT*/

#ifndef MENU_NOSAVE

		SaveArc(axLeft - daxDbcs, ayTop, axRight + daxShadow + daxDbcs,
		    ayBottom + dayShadow,
		    lpbMenu = LpbAllocWorkFar(cw * 2));

#endif	// MENU_NOSAVE

#ifdef	DIALOG_NOSAVE
		/* Hilite first item if not in mouse mode */
		if (!mniCur.fMouse)
			{
			mniCur.iitem = 0;
			}
		DrawMenuCur();
#else	// !DIALOG_NOSAVE
		FillArc(axLeft, ayTop, axRight, ayBottom, ' ',
		    DiNormal(isaEnabledMenuItem));
		DrawBoxArc(&boxSingle, &arcMenu, isaMenuBox,
			TRUE, TRUE, NULL);
		ShadowArc(&arcMenu);
		pmenuitem = PmenuitemOfPmenu(pmenu);
		citem = pmenu->citem;
		ay = ayTop + 1;
		while (citem--)
			{
			if (pmenuitem->fSeparator)
				{
				/* draw a separator */
				FillArc(axLeft + daxBorder, ay,
				    axRight - daxBorder, ay + dayBorder,
				    (ACHAR) chTopSide1,
				    DiNormal(isaMenuBox));
				CharOutAbs(axRight - daxBorder, ay,
				    (ACHAR) chMiddleRight1,
				     DiNormal(isaMenuBox));
				CharOutAbs(axLeft, ay, (ACHAR) chMiddleLeft1,
				    DiNormal(isaMenuBox));
				}
			else
				{
				DrawMenuItem(axLeft, ay,
				   (AX) axRight - daxBorder, pmenuitem);
				}
			ay++;
			pmenuitem++;
			}
		/* Hilite first item if not in mouse mode */
		if (!mniCur.fMouse)
			{
			mniCur.iitem = 0;
			HiliteItem(TRUE);
			}
#endif	// DIALOG_NOSAVE
		}
	else
		{
		/* no items => no mouse selection of items */
		arcMenu.ayTop = 0;
		arcMenu.ayBottom = 1;
		mniCur.iitem = iitemNil;
		}

	EndDraw();

	/* just to be sure */
	Assert(pmenu == mniCur.pmenuOpen);
	}

#ifdef	DIALOG_NOSAVE
STATIC VOID
DrawMenuCur()
	{
	WORD citem;
	REGISTER PMENUITEM pmenuitem;
	AX axLeft = arcMenu.axLeft;
	AX axRight = arcMenu.axRight;
	AY ayTop = arcMenu.ayTop;
	AY ayBottom = arcMenu.ayBottom;
	AY ay;

	if (mniCur.pmenuOpen == NULL)
		{
		HiliteMenuTitle(TRUE);
		return;
		}

	FillArc(axLeft, ayTop, axRight, ayBottom, ' ',
	    DiNormal(isaEnabledMenuItem));
	DrawBoxArc(&boxSingle, &arcMenu, isaMenuBox,
		TRUE, TRUE, NULL);
	ShadowArc(&arcMenu);
	pmenuitem = PmenuitemOfPmenu(mniCur.pmenuOpen);
	citem = mniCur.pmenuOpen->citem;
	ay = ayTop + 1;
	while (citem--)
		{
		if (pmenuitem->fSeparator)
			{
			/* draw a separator */
			FillArc(axLeft + daxBorder, ay,
			    axRight - daxBorder, ay + dayBorder,
			    (ACHAR) chTopSide1,
			    DiNormal(isaMenuBox));
			CharOutAbs(axRight - daxBorder, ay,
			    (ACHAR) chMiddleRight1,
			     DiNormal(isaMenuBox));
			CharOutAbs(axLeft, ay, (ACHAR) chMiddleLeft1,
			    DiNormal(isaMenuBox));
			}
		else
			{
			DrawMenuItem(axLeft, ay,
			   (AX) axRight - daxBorder, pmenuitem);
			}
		ay++;
		pmenuitem++;
		}
	HiliteItem(TRUE);
	}
#endif	// DIALOG_NOSAVE


STATIC VOID
CloseMenuCur(fMessage)
BOOL fMessage;	/* send WM_COMMAND message? */
/*
  -- close the body of current menu
  -- can be called if menu not open (do nothing)
*/
	{
	if (mniCur.imenu == imenuNil || mniCur.pmenuOpen == NULL)
		return;		/* not open */

	Assert(mniCur.pmenuOpen == &pmenubarCur->rgmenu[mniCur.imenu]);

#ifndef MENU_NOSAVE

	DrawThisWnd(NULL);
	if (mniCur.pmenuOpen->citem)
		{
#ifdef KANJI
		fRestoreDbcs = TRUE;
#endif	/*KANJI*/

		RestoreArc(arcMenu.axLeft - daxDbcs, arcMenu.ayTop,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -