?? wmenu.c
字號:
break;
case 0x4f00: /* End */
/* hide selection bar and find */
/* lower-rightmost menu item */
citem=goto_item(citem,ITM_LS);
break;
case 0x1c0d: /* Enter */
enter:
/* if current menu item has a pull-down menu */
/* attached, then set the pulldown flag */
if(citem->fmask&M_HASPD) pulldown=YES;
/* display menu item with selection bar */
disp_item(citem,1);
menuerr=0;
/* if current menu item has a child menu */
if(citem->child!=NULL) {
/* save environment info, process child */
/* menu, then restore environment info */
_winfo.cmenu=citem->child;
hide_mouse_cursor();
err=whelpush();
menuerr=wmenuget();
winerr=_winfo.errno;
if(!err) whelpop();
show_mouse_cursor();
_winfo.cmenu=_winfo.cmenu->parent;
/* if an error was returned by */
/* child menu, free menu records */
/* and pass error code to caller */
if(menuerr==-1&&winerr!=W_ESCPRESS) {
call_after(citem);
menuerr=winerr;
pre_exit(w,YES);
_winfo.errno=menuerr;
return(-1);
}
}
/* if the M_CLOSB feature is on, then close the menu's */
/* window before the selection function is called. */
if(citem->fmask&M_CLOSB) close_window(w);
/* this is used as a flag to see if the selection bar's */
/* position has been changed by the select function. */
_winfo.cmenu->tagcurr=-1;
/* if current menu item has a select function, call it */
if(citem->select!=NULL) call_func(citem->select);
/* if the M_CLOSB feature is on, then free the current */
/* menu a before the selection function is called. */
if(citem->fmask&M_CLOSB) {
call_after(citem);
pre_exit(w,NO);
_winfo.errno=W_NOERROR;
return(citem->tagid);
}
/* check all menu items in current menu to */
/* see if their redisplay flag has been set */
for(item=_winfo.cmenu->item;item!=NULL;item=item->prev) {
if(item->redisp) {
disp_item(item,(item==citem));
item->redisp=NO;
}
}
/* see if selection bar position was changed by select */
/* function. if so, then move selection bar to new item */
if(_winfo.cmenu->tagcurr!=-1) {
item=wmenuifind(_winfo.cmenu->tagcurr);
if(item!=NULL&&(!(item->fmask&M_NOSEL))) {
pre_move(citem);
post_move(_winfo.cmenu->citem=citem=item);
break;
}
}
/* if current menu item has a pull-down attached */
if(citem->fmask&M_HASPD) {
/* if child menu returned previous pull-down menu */
/* flag, find menu item to the left and select it */
if(menuerr==M_PREVPD) {
citem=goto_item(citem,ITM_LT);
if(citem->fmask&M_HASPD) goto enter;
break;
}
/* if child menu returned next pull-down menu */
/* flag, find menu item to the right and select it */
if(menuerr==M_NEXTPD) {
citem=goto_item(citem,ITM_RT);
if(citem->fmask&M_HASPD) goto enter;
break;
}
}
/* turn off pulldown flag */
pulldown=NO;
/* if child menu returned an exit-all-menus flag, */
/* then free menu records and pass exit-all-menus */
/* flag onto caller */
if((menuerr==M_EXITALL)||(citem->fmask&M_CLALL)) {
disp_item(citem,1);
call_after(citem);
pre_exit(w,YES);
_winfo.errno=W_NOERROR;
return(M_EXITALL);
}
/* unless an exit-this-menu flag was returned by the */
/* child menu, or current item has close-menu */
/* specified, free menu records, and return tag */
/* identifier of current menu item */
if(citem->child!=NULL||citem->select!=NULL)
if((menuerr!=M_EXIT)&&(!(citem->fmask&M_CLOSE)))
break;
call_after(citem);
pre_exit(w,YES);
_winfo.errno=W_NOERROR;
return(citem->tagid);
default:
/* separate ASCII code from keypress code, if ASCII */
/* code is zero, then it must be an extended key */
ch=(char)xch;
if(!ch) break;
/* scan through list of items for one that */
/* has a tag identifier matching keypress */
valid=YES;
item=citem->next;
for(;;) {
while(item!=NULL) {
if((toupper(ch)==toupper(item->schar))&&(!(item->fmask
&M_NOSEL))) goto farbreak;
if(citem==item) {
valid=NO;
goto farbreak;
}
item=item->next;
}
for(item=_winfo.cmenu->item;item->prev!=NULL;
item=item->prev);
}
farbreak:
/* if a matching tag identifier was found, */
/* then hide selection bar, and if quick-key */
/* selection is allowed, select the found menu item */
if(valid) {
if(item!=citem) {
pre_move(citem);
post_move(_winfo.cmenu->citem=citem=item);
}
if(!(_winfo.cmenu->menutype&M_NOQS)) goto enter;
}
}
}
}
/*---------------------------------------------------------------------------*/
/* this function will calculate the width of the selection bar */
static int calc_bar_width(struct _menu_t *wmenu,struct _item_t *witem)
{
register int width;
width=strlen(witem->str);
if(wmenu->barwidth) width=wmenu->barwidth;
return(width);
}
/*---------------------------------------------------------------------------*/
/* this function will calculate the window column */
/* at the center of the given menu item */
static int calc_center_item(struct _item_t *item)
{
return( ((int)item->wcol) + (strlen(item->str)/2) );
}
/*---------------------------------------------------------------------------*/
/* this function will call a menu item's "after" function if it exists */
static void call_after(struct _item_t *citem)
{
if(citem->after!=NULL) call_func(citem->after);
}
/*---------------------------------------------------------------------------*/
/* this function will call a menu item's "before" function if it exists */
static void call_before(struct _item_t *citem)
{
if(citem->before!=NULL) call_func(citem->before);
}
/*---------------------------------------------------------------------------*/
/* this function calls the given function */
static void call_func(void (*func)(void))
{
struct _menu_t *menu;
WINDOW w;
int err;
hide_mouse_cursor();
menu=_winfo.cmenu;
w=whandle();
err=whelpush();
(*func)();
wactiv(w);
if(!err) whelpop();
_winfo.cmenu=menu;
show_mouse_cursor();
}
/*---------------------------------------------------------------------------*/
/* this function closes the current menu's window and reactivates */
/* the menu window open prior to opening the current menu window */
static void close_window(WINDOW w)
{
if(!_winfo.cmenu->usecurr) {
hide_mouse_cursor();
wclose();
wactiv(w);
show_mouse_cursor();
}
}
/*---------------------------------------------------------------------------*/
/* this function displays a menu selection, using selection bar if specified */
static void disp_item(struct _item_t *witem,int bar)
{
register char *p;
register int i;
int ch,textend,width,chattr,wcol,found=NO;
/* if mouse cursor is on, temporarily hide it */
hide_mouse_cursor();
/* initialize width of output and end of text */
p=witem->str;
width=calc_bar_width(_winfo.cmenu,witem);
textend=_winfo.cmenu->textpos+strlen(p)-1;
wgotoxy(witem->wrow,wcol=witem->wcol);
/* display menu item including selection bar */
for(i=0;i<width;i++) {
/* see if currently in bar region. if so, then use */
/* a space for the character. otherwise use the */
/* character from the current position in the string */
ch=(i<_winfo.cmenu->textpos||i>textend)?' ':(*p++);
/* select attribute of character to be displayed based upon if */
/* selection bar was specified, if the menu item is non-selectable, */
/* if the character is a tag character, or none of the above. */
if(bar)
chattr=_winfo.cmenu->barattr;
else if(witem->fmask&M_NOSEL)
chattr=_winfo.cmenu->noselattr;
else if((ch==witem->schar)&&!found) {
found=YES;
chattr=_winfo.cmenu->scharattr;
}
else
chattr=_winfo.cmenu->textattr;
/* display character in selected attribute */
wprintc(witem->wrow,wcol++,chattr,ch);
}
/* display text description, if one exists */
if(witem->desc!=NULL&&dispdesc) {
wgotoxy(witem->dwrow,witem->dwcol);
wtextattr(witem->dattr);
wputs(witem->desc);
wclreol();
}
/* if mouse cursor is hidden, unhide it */
show_mouse_cursor();
}
/*---------------------------------------------------------------------------*/
/* this function finds the next menu selection down */
static struct _item_t *down_item(struct _item_t *curr)
{
struct _item_t *best,*temp;
int brow,bcol,tcol,trow,crow,ccol,tdist,bdist;
/* initialize best record to NULL */
best=NULL;
brow=bcol=32767;
/* calculate window column at center of current item */
crow=(int)curr->wrow;
ccol=calc_center_item(curr);
/* search backwards through linked list, testing each item */
for(temp=_winfo.cmenu->item;temp!=NULL;temp=temp->prev) {
/* calculate window column at center of test item */
trow=(int)temp->wrow;
tcol=calc_center_item(temp);
if(trow>crow) {
tdist=abs((ccol-tcol));
bdist=abs((ccol-bcol));
if((trow<brow)||((trow==brow&&tdist<bdist))) {
best=temp;
brow=trow;
bcol=tcol;
}
}
}
/* if there wasn't an item downwards, then wrap around */
if(best==NULL) {
if((temp=malloc(sizeof(struct _item_t)))==NULL) {
best=curr;
}
else {
*temp=*curr;
temp->wrow=-1;
best=down_item(temp);
free(temp);
}
}
else
/* see if menu selection is non-selectable */
if(best->fmask&M_NOSEL)
best=down_item(best);
/* return best record */
return(best);
}
/*---------------------------------------------------------------------------*/
/* this function finds the upper-leftmost menu selection */
static struct _item_t *first_item(void)
{
struct _item_t *best,*temp;
/* initialize best record to highest record in linked list */
best=_winfo.cmenu->item;
/* search backwards through linked list, testing each item */
for(temp=best->prev;temp!=NULL;temp=temp->prev) {
if( (temp->wrow<best->wrow) ||
( (temp->wrow==best->wrow) && (temp->wcol<best->wcol) ) )
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -