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

📄 wmenu.c

📁 详细介绍了一篇关于pci开发的接口芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
                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) ) )

⌨️ 快捷键说明

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