(续)AIX仿真SCO UNIX的MENU驱动
王光红
static void start_line(MENU *m)
{
if(m->curitem->index < m->toprow + m->height * m->cols
&& m->curitem->index >m->toprow) return;
if(m->nitems>=m->height+m->curitem->index){
if(m->toprow >=m->curitem->index)
m->toprow=m->curitem->index;
else
m->toprow +=m->cols;
}
else{
m->toprow=m->nitems - m->height;
}
}
static int compute_seat(MENU *m)
{
int n, y, x, t;
for(n=0; n < m->nitems; n++){
t=n-1;
if(t<0) m->items[n]->left=m->items[m->nitems-1];
else m->items[n]->left=m->items[t];
t=n+1;
if(t>=m->nitems) m->items[n]->right=m->items[0];
else m->items[n]->right=m->items[t];
t=n - m->cols;
if(t<0) m->items[n]->up=m->items[m->nitems-1];
else m->items[n]->up=m->items[t];
t=n + m->cols;
if(t>=m->nitems) m->items[n]->down=m->items[0];
else m->items[n]->down=m->items[t];
}
}
int post_menu(MENU *m)
{
touch_menu(m);
wrefresh(m->sub);
}
int touch_menu(MENU *m)
{
int y, x, s, cy, cx;
char *lable;
chtype attrs;
if(m==NULL) return -1;
if(m->sub==NULL) return -2;
unpost_menu(m);
start_line(m);
for(s=m->toprow, y=0;y<m->height;y++)
for(x=0;x<m->cols;x++){
lable=menu_lable(s, m);
if(s==m->curitem->index){
attrs=m->sub->_attrs;
wattrset(m->sub, A_REVERSE|m->sub->_attrs);
mvwprintw(m->sub, y, x*(m->itemlen), "%s%s", m->mark, lable);
cy=y, cx=x*(m->itemlen);
wattrset(m->sub, attrs);
}
else
mvwprintw(m->sub, y, x*(m->itemlen)+m->marklen, lable);
s++;
}
wmove(m->sub, cy, cx);
wmove(m->win, cy+1, cx+1);
compute_seat(m);
}
int unpost_menu(MENU *m)
{
werase(m->sub);
wrefresh(m->win);
}
ITEM **menu_items(MENU *m)
{
return m->items;
}
ITEM *current_item(MENU *m)
{
return m->curitem;
}
int item_index(ITEM *i)
{
return i->index;
}
int free_item(ITEM *i)
{
free(i);
return 0;
}
int free_menu(MENU *m)
{
free(m);
return 0;
}
int menu_driver(MENU *m, int c)
{
switch(c){
case REQ_LEFT_ITEM:
if(m->curitem->left){
m->curitem=m->curitem->left;
touch_menu(m);
}
break;
case REQ_RIGHT_ITEM:
if(m->curitem->right){
m->curitem=m->curitem->right;
touch_menu(m);
}
break;
case REQ_UP_ITEM:
if(m->curitem->up){
m->curitem=m->curitem->up;
touch_menu(m);
}
break;
case REQ_DOWN_ITEM:
if(m->curitem->down){
m->curitem=m->curitem->down;
touch_menu(m);
}
break;
case REQ_SCR_ULINE:
case REQ_SCR_DLINE:
case REQ_SCR_DPAGE:
case REQ_SCR_UPAGE:
case REQ_FIRST_ITEM:
m->curitem=m->items[0];
touch_menu(m);
break;
case REQ_LAST_ITEM:
break;
case REQ_NEXT_ITEM:
if(m->curitem->index<m->nitems)
m->curitem=m->items[m->curitem->index + 1];
else
m->curitem=m->items[0];
touch_menu(m);
break;
case REQ_PREV_ITEM:
if(m->curitem->index>0)
m->curitem=m->items[m->curitem->index - 1];
else
m->curitem=m->items[m->nitems-1];
touch_menu(m);
break;
case REQ_TOGGLE_ITEM:
case REQ_CLEAR_PATTERN:
case REQ_BACK_PATTERN:
case REQ_NEXT_MATCH:
case REQ_PREV_MATCH:
break;
}
wrefresh(m->sub);
return E_OK;
}