?? wmenu.c
字號:
/* CXL - Copyright (c) 1987-1989 by Mike Smedley - All Rights Reserved */
/* WMENU.C - wmenubeg() starts a menu definition
wmenuitem() defines a menu item
wmenuend() ends a menu definition
wmenuget() processes the defined menu */
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "cxldef.h"
#include "cxlkey.h"
#include "cxlmou.h"
#include "cxlvid.h"
#include "cxlwin.h"
/* prototypes for local functions */
static int calc_bar_width(struct _menu_t *wmenu,
struct _item_t *witem);
static int calc_center_item(struct _item_t *item);
static void call_after(struct _item_t *citem);
static void call_before(struct _item_t *citem);
static void call_func(void (*func)(void));
static void close_window(WINDOW w);
static void disp_item(struct _item_t *witem,int bar);
static struct _item_t *down_item(struct _item_t *curr);
static struct _item_t *first_item(void);
static void free_menu(struct _menu_t *wmenu);
static struct _item_t *goto_item(struct _item_t *citem,int which);
static void hide_mouse_cursor(void);
static struct _item_t *last_item(void);
static struct _item_t *left_item(struct _item_t *curr);
static struct _item_t *mouse_on_item(struct _menu_t *menu,int mrow,int mcol);
static void post_move(struct _item_t *citem);
static void pre_exit(WINDOW w,int close);
static void pre_move(struct _item_t *citem);
static int read_mouse(struct _item_t *citem);
static struct _item_t *right_item(struct _item_t *curr);
static void show_mouse_cursor(void);
static struct _item_t *up_item(struct _item_t *curr);
/*---------------------------------------------------------------------------*/
/* menu item movement definitions */
#define ITM_LT 0
#define ITM_RT 1
#define ITM_UP 2
#define ITM_DN 3
#define ITM_FR 4
#define ITM_LS 5
/*---------------------------------------------------------------------------*/
/* array of function pointers to some of the item movement functions */
static struct _item_t *(*funcs[4])(struct _item_t *) =
{ left_item,right_item,up_item,down_item };
/* flag used for initial display of menu selections */
static int _Near _Cdecl dispdesc=YES;
/*---------------------------------------------------------------------------*/
int wmenubeg(int srow,int scol,int erow,int ecol,int btype,int battr,
int wattr,void (*open)(void))
{
struct _menu_t *wmenu;
/* if this is a submenu, then make sure that it is under a menu item */
if(_winfo.mlevel>_winfo.ilevel) return(_winfo.errno=W_NOITMDEF);
/* allocate memory for new menu record */
if((wmenu=malloc(sizeof(struct _menu_t)))==NULL)
return(_winfo.errno=W_ALLOCERR);
/* if menu is not a submenu, make it a new base menu record */
if(!_winfo.mlevel) {
if(_winfo.menu!=NULL) _winfo.menu->next=wmenu;
wmenu->prev=_winfo.menu;
wmenu->next=NULL;
wmenu->parent=NULL;
_winfo.menu=_winfo.cmenu=wmenu;
}
else {
wmenu->parent=_winfo.cmenu;
_winfo.cmenu=_winfo.cmenu->item->child=wmenu;
}
/* save info in menu record */
wmenu->srow=srow;
wmenu->scol=scol;
wmenu->erow=erow;
wmenu->ecol=ecol;
wmenu->btype=btype;
wmenu->battr=mapattr(battr);
wmenu->wattr=mapattr(wattr);
wmenu->open=open;
wmenu->usecurr=NO;
wmenu->item=NULL;
/* increment menu level */
_winfo.mlevel++;
/* return normally */
return(_winfo.errno=W_NOERROR);
}
/*---------------------------------------------------------------------------*/
int wmenuitem(int wrow,int wcol,char *str,int schar,int tagid,int fmask,
void (*select)(void),unsigned hotkey,int help)
{
struct _item_t *witem;
/* make sure that wmenubeg() or wmenubegc() has been called */
if(!_winfo.mlevel) return(_winfo.errno=W_NOMNUBEG);
/* allocate memory for new item record */
if((witem=malloc(sizeof(struct _item_t)))==NULL)
return(_winfo.errno=W_ALLOCERR);
/* add new menu item record to linked list */
if(_winfo.cmenu->item!=NULL) _winfo.cmenu->item->next=witem;
witem->prev=_winfo.cmenu->item;
witem->next=NULL;
_winfo.cmenu->item=witem;
/* save info in item record */
witem->wrow = wrow;
witem->wcol = wcol;
witem->str = str;
witem->schar = schar;
witem->tagid = tagid;
witem->fmask = fmask;
witem->select = select;
witem->hotkey = hotkey;
witem->desc = NULL;
witem->dwrow = 0;
witem->dwcol = 0;
witem->dattr = 0;
witem->redisp = NO;
witem->help = help;
witem->child = NULL;
witem->before =
witem->after = NULL;
/* set item level == menu level */
_winfo.ilevel=_winfo.mlevel;
/* return normally */
return(_winfo.errno=W_NOERROR);
}
/*---------------------------------------------------------------------------*/
int wmenuend(int taginit,int menutype,int barwidth,int textpos,
int textattr,int scharattr,int noselattr,int barattr)
{
struct _item_t *item;
int w_width,border,found;
/* make sure at least 1 menu item has been defined */
if(!_winfo.mlevel||_winfo.mlevel>_winfo.ilevel)
return(_winfo.errno=W_NOITMDEF);
/* make sure that the specified initial tagid matches the */
/* tagid of one of the defined menu items in this menu */
for(found=NO,item=_winfo.cmenu->item;item!=NULL;item=item->prev) {
if(item->tagid==taginit) {
found=YES;
break;
}
}
if(!found) return(_winfo.errno=W_INVTAGID);
/* if bar width > window width, then bar width = window width */
border=(_winfo.cmenu->btype==5)?0:1;
w_width=(_winfo.cmenu->ecol-border)-(_winfo.cmenu->scol+border)+1;
if(barwidth>w_width) barwidth=w_width;
/* add rest of menu information to menu record */
_winfo.cmenu->citem = NULL;
_winfo.cmenu->tagcurr = taginit;
_winfo.cmenu->menutype = menutype;
_winfo.cmenu->barwidth = barwidth;
_winfo.cmenu->textpos = barwidth?textpos:0;
_winfo.cmenu->textattr = mapattr(textattr);
_winfo.cmenu->scharattr = mapattr(scharattr);
_winfo.cmenu->noselattr = mapattr(noselattr);
_winfo.cmenu->barattr = _vinfo.mapattr?revsattr(_winfo.cmenu->textattr):
barattr;
/* set current menu pointer to parent menu */
if((_winfo.cmenu=_winfo.cmenu->parent)==NULL) _winfo.cmenu=_winfo.menu;
/* decrement menu and item levels */
_winfo.mlevel--;
_winfo.ilevel--;
/* return with no error */
return(_winfo.errno=W_NOERROR);
}
/*---------------------------------------------------------------------------*/
int wmenuget(void)
{
register unsigned int xch;
register struct _item_t *citem;
struct _item_t *item;
int valid,pulldown=NO,menuerr,winerr,err;
char ch;
WINDOW w;
/* make sure we have a defined menu */
if(_winfo.cmenu==NULL) {
_winfo.errno=W_NOMNUDEF;
return(-1);
}
/* make sure that wmenuend() was called */
if(_winfo.mlevel||_winfo.ilevel) {
_winfo.errno=W_NOMNUEND;
return(-1);
}
/* open menu's window (unless menu is to use current window) */
if(!_winfo.cmenu->usecurr) {
w=whandle();
hide_mouse_cursor();
if(!wopen(_winfo.cmenu->srow,_winfo.cmenu->scol,_winfo.cmenu->erow
,_winfo.cmenu->ecol,_winfo.cmenu->btype,_winfo.cmenu->battr
,_winfo.cmenu->wattr)) return(-1);
show_mouse_cursor();
/* save environment info, call menu open */
/* function, then restore environment info */
if(_winfo.cmenu->open!=NULL) call_func(_winfo.cmenu->open);
}
/* if mouse cursor mode is on, show cursor */
show_mouse_cursor();
/* find first item in linked list */
if((item=_winfo.cmenu->item)!=NULL) for(;item->prev!=NULL;item=item->prev);
/* display all menu items */
dispdesc=NO;
valid=NO;
while(item!=NULL) {
disp_item(item,0);
if(!(item->fmask&M_NOSEL)) valid=YES;
item=item->next;
}
dispdesc=YES;
/* make sure there is at least 1 selectable menu item */
if(!valid) {
pre_exit(w,YES);
_winfo.errno=W_NOSELECT;
return(-1);
}
/* search linked list of item records for the item matching */
/* the last item. If there was no last item, search for */
/* the initial tag ID position. If no initial tag ID position */
/* was specified, then find the upper-leftmost menu item. */
citem=NULL;
if(_winfo.cmenu->menutype&M_SAVE) {
for(citem=_winfo.cmenu->item;citem!=NULL;citem=citem->prev) {
if((_winfo.cmenu->citem==citem)&&
(!(citem->fmask&M_NOSEL)))
break;
}
}
if(citem==NULL) {
citem=wmenuifind(_winfo.cmenu->tagcurr);
if((citem==NULL)||(citem->fmask&M_NOSEL)) citem=first_item();
}
/* call the current menu item's 'before' */
/* function and display current menu item */
post_move(citem);
/* main process of function */
for(;;) {
/* update current menu item and help category */
_winfo.cmenu->citem=citem;
_winfo.help=citem->help;
/* read mouse/keyboard for keypress, then test the keypress */
_kbinfo.inmenu=TRUE;
xch=read_mouse(citem);
citem=_winfo.cmenu->citem;
if(!xch) xch=getxch();
_kbinfo.inmenu=FALSE;
switch(xch) {
case 0x011b: /* Esc */
/* if Esc checking is on, erase selection bar, */
/* free menu records and return to caller */
if(_winfo.esc||(_winfo.cmenu!=_winfo.menu)) {
pre_move(citem);
pre_exit(w,YES);
_winfo.errno=W_ESCPRESS;
return(-1);
}
break;
case 0x4700: /* Home */
/* hide selection bar and find upper-leftmost menu item */
citem=goto_item(citem,ITM_FR);
break;
case 0x4b00: /* LeftArrow */
/* if current menu is a pull-down menu, */
/* then erase selection bar, free menu records, */
/* and return special code to caller */
if(_winfo.cmenu->menutype&M_PD) {
pre_move(citem);
pre_exit(w,YES);
_winfo.errno=W_NOERROR;
return(M_PREVPD);
}
/* if current menu is a horizontal menu, then hide */
/* selection bar and find menu item to the left */
if(_winfo.cmenu->menutype&M_HORZ)
citem=goto_item(citem,ITM_LT);
/* if pull-down menu flag is set, select this item */
if(pulldown&&citem->child!=NULL) goto enter;
break;
case 0x4800: /* UpArrow */
/* if current menu is a vertical menu, then hide */
/* selection bar and find menu item upwards */
if(_winfo.cmenu->menutype&(M_VERT|M_PD))
citem=goto_item(citem,ITM_UP);
break;
case 0x4d00: /* RightArrow */
/* if current menu is a pull-down menu, */
/* then erase selection bar, free menu records, */
/* and return special code to caller */
if(_winfo.cmenu->menutype&M_PD) {
pre_move(citem);
pre_exit(w,YES);
_winfo.errno=W_NOERROR;
return(M_NEXTPD);
}
/* if current menu is a horizontal menu, then hide */
/* selection bar and find menu item to the right */
if(_winfo.cmenu->menutype&M_HORZ)
citem=goto_item(citem,ITM_RT);
/* if pulldown flag is set, then select this item */
if(pulldown&&citem->child!=NULL) goto enter;
break;
case 0x5000: /* DownArrow */
/* if current item has a pull-down menu, select it */
if(citem->fmask&M_HASPD) goto enter;
/* if current menu is a vertical menu, then hide */
/* selection bar and find menu item downwards */
if(_winfo.cmenu->menutype&(M_VERT|M_PD))
citem=goto_item(citem,ITM_DN);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -