make tab cycle through matched items
This commit is contained in:
parent
7bdb3b0bf8
commit
693735f7eb
86
xmenu.c
86
xmenu.c
|
@ -1158,19 +1158,53 @@ append(char *text, char *buf, size_t textsize, size_t buflen)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get item in menu matching text */
|
/* get item in menu matching text from given direction (or from beginning, if dir = 0) */
|
||||||
static struct Item *
|
static struct Item *
|
||||||
matchitem(struct Menu *menu, char *text)
|
matchitem(struct Menu *menu, char *text, int dir)
|
||||||
{
|
{
|
||||||
struct Item *item;
|
struct Item *item, *lastitem;
|
||||||
char *s;
|
char *s;
|
||||||
size_t textlen;
|
size_t textlen;
|
||||||
|
|
||||||
|
for (lastitem = menu->list; lastitem && lastitem->next; lastitem = lastitem->next)
|
||||||
|
;
|
||||||
textlen = strlen(text);
|
textlen = strlen(text);
|
||||||
for (item = menu->list; item; item = item->next)
|
if (dir < 0) {
|
||||||
|
if (menu->selected && menu->selected->prev)
|
||||||
|
item = menu->selected->prev;
|
||||||
|
else
|
||||||
|
item = lastitem;
|
||||||
|
} else if (dir > 0) {
|
||||||
|
if (menu->selected && menu->selected->next)
|
||||||
|
item = menu->selected->next;
|
||||||
|
else
|
||||||
|
item = menu->list;
|
||||||
|
} else {
|
||||||
|
item = menu->list;
|
||||||
|
}
|
||||||
|
/* find next item from selected item */
|
||||||
|
for ( ; item; item = (dir < 0) ? item->prev : item->next)
|
||||||
for (s = item->label; s && *s; s++)
|
for (s = item->label; s && *s; s++)
|
||||||
if (strncasecmp(s, text, textlen) == 0)
|
if (strncasecmp(s, text, textlen) == 0)
|
||||||
return item;
|
return item;
|
||||||
|
/* if not found, try to find from the beginning/end of list */
|
||||||
|
if (dir > 0) {
|
||||||
|
for (item = menu->list ; item; item = item->next) {
|
||||||
|
for (s = item->label; s && *s; s++) {
|
||||||
|
if (strncasecmp(s, text, textlen) == 0) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (item = lastitem ; item; item = item->prev) {
|
||||||
|
for (s = item->label; s && *s; s++) {
|
||||||
|
if (strncasecmp(s, text, textlen) == 0) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,7 +1248,7 @@ run(struct Menu *currmenu)
|
||||||
} else {
|
} else {
|
||||||
currmenu = menu;
|
currmenu = menu;
|
||||||
}
|
}
|
||||||
action = ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
|
action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
|
||||||
break;
|
break;
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
if (!isclickbutton(ev.xbutton.button))
|
if (!isclickbutton(ev.xbutton.button))
|
||||||
|
@ -1233,7 +1267,7 @@ enteritem:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
select = currmenu->list;
|
select = currmenu->list;
|
||||||
action = ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
|
action = ACTION_CLEAR | ACTION_SELECT | ACTION_MAP | ACTION_DRAW;
|
||||||
break;
|
break;
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
menu = getmenu(currmenu, ev.xbutton.window);
|
menu = getmenu(currmenu, ev.xbutton.window);
|
||||||
|
@ -1264,12 +1298,24 @@ enteritem:
|
||||||
item = NULL;
|
item = NULL;
|
||||||
if (ksym == XK_Home || ksym == KSYMFIRST) {
|
if (ksym == XK_Home || ksym == KSYMFIRST) {
|
||||||
item = itemcycle(currmenu, ITEMFIRST);
|
item = itemcycle(currmenu, ITEMFIRST);
|
||||||
|
action = ACTION_CLEAR;
|
||||||
} else if (ksym == XK_End || ksym == KSYMLAST) {
|
} else if (ksym == XK_End || ksym == KSYMLAST) {
|
||||||
item = itemcycle(currmenu, ITEMLAST);
|
item = itemcycle(currmenu, ITEMLAST);
|
||||||
|
action = ACTION_CLEAR;
|
||||||
} else if (ksym == XK_ISO_Left_Tab || ksym == XK_Up || ksym == KSYMUP) {
|
} else if (ksym == XK_ISO_Left_Tab || ksym == XK_Up || ksym == KSYMUP) {
|
||||||
item = itemcycle(currmenu, ITEMPREV);
|
if (*text) {
|
||||||
|
item = matchitem(currmenu, text, -1);
|
||||||
|
} else {
|
||||||
|
item = itemcycle(currmenu, ITEMPREV);
|
||||||
|
action = ACTION_CLEAR;
|
||||||
|
}
|
||||||
} else if (ksym == XK_Tab || ksym == XK_Down || ksym == KSYMDOWN) {
|
} else if (ksym == XK_Tab || ksym == XK_Down || ksym == KSYMDOWN) {
|
||||||
item = itemcycle(currmenu, ITEMNEXT);
|
if (*text) {
|
||||||
|
item = matchitem(currmenu, text, 1);
|
||||||
|
} else {
|
||||||
|
item = itemcycle(currmenu, ITEMNEXT);
|
||||||
|
action = ACTION_CLEAR;
|
||||||
|
}
|
||||||
} else if (ksym >= XK_1 && ksym <= XK_9){
|
} else if (ksym >= XK_1 && ksym <= XK_9){
|
||||||
item = itemcycle(currmenu, ITEMFIRST);
|
item = itemcycle(currmenu, ITEMFIRST);
|
||||||
lastitem = itemcycle(currmenu, ITEMLAST);
|
lastitem = itemcycle(currmenu, ITEMLAST);
|
||||||
|
@ -1277,6 +1323,7 @@ enteritem:
|
||||||
currmenu->selected = item;
|
currmenu->selected = item;
|
||||||
item = itemcycle(currmenu, ITEMNEXT);
|
item = itemcycle(currmenu, ITEMNEXT);
|
||||||
}
|
}
|
||||||
|
action = ACTION_CLEAR;
|
||||||
} else if ((ksym == XK_Return || ksym == XK_Right || ksym == KSYMRIGHT) &&
|
} else if ((ksym == XK_Return || ksym == XK_Right || ksym == KSYMRIGHT) &&
|
||||||
currmenu->selected != NULL) {
|
currmenu->selected != NULL) {
|
||||||
item = currmenu->selected;
|
item = currmenu->selected;
|
||||||
|
@ -1285,18 +1332,19 @@ enteritem:
|
||||||
currmenu->parent != NULL) {
|
currmenu->parent != NULL) {
|
||||||
item = currmenu->parent->selected;
|
item = currmenu->parent->selected;
|
||||||
currmenu = currmenu->parent;
|
currmenu = currmenu->parent;
|
||||||
action = ACTION_MAP;
|
action = ACTION_CLEAR | ACTION_MAP;
|
||||||
|
} else if (ksym == XK_BackSpace || ksym == XK_Clear || ksym == XK_Delete) {
|
||||||
|
action = ACTION_CLEAR;
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
append:
|
append:
|
||||||
if (append(text, buf, sizeof text, len)) {
|
if (append(text, buf, sizeof text, len)) {
|
||||||
if ((currmenu->selected = matchitem(currmenu, text))) {
|
if (!(item = matchitem(currmenu, text, 0))) {
|
||||||
action = ACTION_DRAW;
|
item = NULL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else if (len == 0) {
|
||||||
|
break; /* we may have pressed a dead key */
|
||||||
}
|
}
|
||||||
select = NULL;
|
|
||||||
action = ACTION_SELECT | ACTION_DRAW;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
select = item;
|
select = item;
|
||||||
action |= ACTION_SELECT | ACTION_DRAW;
|
action |= ACTION_SELECT | ACTION_DRAW;
|
||||||
|
@ -1304,7 +1352,7 @@ append:
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
previtem = NULL;
|
previtem = NULL;
|
||||||
select = NULL;
|
select = NULL;
|
||||||
action = ACTION_SELECT | ACTION_DRAW;
|
action = ACTION_CLEAR | ACTION_SELECT | ACTION_DRAW;
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
menu = getmenu(currmenu, ev.xconfigure.window);
|
menu = getmenu(currmenu, ev.xconfigure.window);
|
||||||
|
@ -1324,10 +1372,10 @@ append:
|
||||||
action = ACTION_MAP;
|
action = ACTION_MAP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (action & ACTION_SELECT) {
|
if (action & ACTION_CLEAR)
|
||||||
currmenu->selected = select;
|
|
||||||
text[0] = '\0';
|
text[0] = '\0';
|
||||||
}
|
if (action & ACTION_SELECT)
|
||||||
|
currmenu->selected = select;
|
||||||
if (action & ACTION_MAP)
|
if (action & ACTION_MAP)
|
||||||
mapmenu(currmenu);
|
mapmenu(currmenu);
|
||||||
if (action & ACTION_DRAW)
|
if (action & ACTION_DRAW)
|
||||||
|
|
7
xmenu.h
7
xmenu.h
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
/* Actions for the main loop */
|
/* Actions for the main loop */
|
||||||
#define ACTION_NOP 0
|
#define ACTION_NOP 0
|
||||||
#define ACTION_SELECT 1<<0 /* select item and clear text */
|
#define ACTION_CLEAR 1<<0 /* clear text */
|
||||||
#define ACTION_MAP 1<<1 /* remap menu windows */
|
#define ACTION_SELECT 1<<1 /* select item */
|
||||||
#define ACTION_DRAW 1<<2 /* redraw menu windows */
|
#define ACTION_MAP 1<<2 /* remap menu windows */
|
||||||
|
#define ACTION_DRAW 1<<3 /* redraw menu windows */
|
||||||
|
|
||||||
/* enum for keyboard menu navigation */
|
/* enum for keyboard menu navigation */
|
||||||
enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };
|
enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };
|
||||||
|
|
Loading…
Reference in New Issue
Block a user