mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-22 04:15:02 +00:00
nconfig: add search support
Remove the old hotkeys feature, and replace it by an interactive string search. From nconfig help: Searching: pressing '/' triggers interactive search mode. nconfig performs a case insensitive search for the string in the menu prompts (no regex support). Pressing the up/down keys highlights the previous/next matching item. Backspace removes one character from the match string. Pressing either '/' again or ESC exits search mode. All other keys behave normally. Miscellaneous other changes (including Rundy's and Justin's input). Signed-off-by: Nir Tzachar <nir.tzachar@gmail.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Michal Marek <mmarek@suse.cz>
This commit is contained in:
parent
3643f849d7
commit
a72f3e2b82
3 changed files with 207 additions and 179 deletions
|
@ -5,9 +5,12 @@
|
||||||
* Derived from menuconfig.
|
* Derived from menuconfig.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <string.h>
|
||||||
#define LKC_DIRECT_LINK
|
#define LKC_DIRECT_LINK
|
||||||
#include "lkc.h"
|
#include "lkc.h"
|
||||||
#include "nconf.h"
|
#include "nconf.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
static const char nconf_readme[] = N_(
|
static const char nconf_readme[] = N_(
|
||||||
"Overview\n"
|
"Overview\n"
|
||||||
|
@ -23,7 +26,7 @@ static const char nconf_readme[] = N_(
|
||||||
" < > can be built in, modularized or removed\n"
|
" < > can be built in, modularized or removed\n"
|
||||||
" { } can be built in or modularized (selected by other feature)\n"
|
" { } can be built in or modularized (selected by other feature)\n"
|
||||||
" - - are selected by other feature,\n"
|
" - - are selected by other feature,\n"
|
||||||
" XXX cannot be selected. use Symbol Info to find out why,\n"
|
" XXX cannot be selected. Use Symbol Info to find out why,\n"
|
||||||
"while *, M or whitespace inside braces means to build in, build as\n"
|
"while *, M or whitespace inside braces means to build in, build as\n"
|
||||||
"a module or to exclude the feature respectively.\n"
|
"a module or to exclude the feature respectively.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -41,9 +44,13 @@ static const char nconf_readme[] = N_(
|
||||||
" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
|
" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
|
||||||
" Submenus are designated by \"--->\".\n"
|
" Submenus are designated by \"--->\".\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Shortcut: Press the option's highlighted letter (hotkey).\n"
|
" Searching: pressing '/' triggers interactive search mode.\n"
|
||||||
" Pressing a hotkey more than once will sequence\n"
|
" nconfig performs a case insensitive search for the string\n"
|
||||||
" through all visible items which use that hotkey.\n"
|
" in the menu prompts (no regex support).\n"
|
||||||
|
" Pressing the up/down keys highlights the previous/next\n"
|
||||||
|
" matching item. Backspace removes one character from the\n"
|
||||||
|
" match string. Pressing either '/' again or ESC exits\n"
|
||||||
|
" search mode. All other keys behave normally.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
||||||
" unseen options into view.\n"
|
" unseen options into view.\n"
|
||||||
|
@ -141,21 +148,21 @@ menu_no_f_instructions[] = N_(
|
||||||
" <Enter> or <right-arrow> selects submenus --->.\n"
|
" <Enter> or <right-arrow> selects submenus --->.\n"
|
||||||
" Capital Letters are hotkeys.\n"
|
" Capital Letters are hotkeys.\n"
|
||||||
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
||||||
" Pressing SpaceBar toggles between the above options\n"
|
" Pressing SpaceBar toggles between the above options.\n"
|
||||||
" Press <Esc> or <left-arrow> to go back one menu, \n"
|
" Press <Esc> or <left-arrow> to go back one menu,\n"
|
||||||
" <?> or <h> for Help, </> for Search.\n"
|
" <?> or <h> for Help, </> for Search.\n"
|
||||||
" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
|
" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
|
||||||
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
||||||
" <Esc> always leaves the current window\n"),
|
" <Esc> always leaves the current window.\n"),
|
||||||
menu_instructions[] = N_(
|
menu_instructions[] = N_(
|
||||||
" Arrow keys navigate the menu.\n"
|
" Arrow keys navigate the menu.\n"
|
||||||
" <Enter> or <right-arrow> selects submenus --->.\n"
|
" <Enter> or <right-arrow> selects submenus --->.\n"
|
||||||
" Capital Letters are hotkeys.\n"
|
" Capital Letters are hotkeys.\n"
|
||||||
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
||||||
" Pressing SpaceBar toggles between the above options\n"
|
" Pressing SpaceBar toggles between the above options\n"
|
||||||
" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n"
|
" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
|
||||||
" <?>, <F1> or <h> for Help, </> for Search.\n"
|
" <?>, <F1> or <h> for Help, </> for Search.\n"
|
||||||
" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
|
" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
|
||||||
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
||||||
" <Esc> always leaves the current window\n"),
|
" <Esc> always leaves the current window\n"),
|
||||||
radiolist_instructions[] = N_(
|
radiolist_instructions[] = N_(
|
||||||
|
@ -252,7 +259,6 @@ struct mitem {
|
||||||
char str[256];
|
char str[256];
|
||||||
char tag;
|
char tag;
|
||||||
void *usrptr;
|
void *usrptr;
|
||||||
int is_hot;
|
|
||||||
int is_visible;
|
int is_visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -275,14 +281,6 @@ static int items_num;
|
||||||
static int global_exit;
|
static int global_exit;
|
||||||
/* the currently selected button */
|
/* the currently selected button */
|
||||||
const char *current_instructions = menu_instructions;
|
const char *current_instructions = menu_instructions;
|
||||||
/* this array is used to implement hot keys. it is updated in item_make and
|
|
||||||
* resetted in clean_items. It would be better to use a hash, but lets keep it
|
|
||||||
* simple... */
|
|
||||||
#define MAX_SAME_KEY MAX_MENU_ITEMS
|
|
||||||
struct {
|
|
||||||
int count;
|
|
||||||
int ptrs[MAX_MENU_ITEMS];
|
|
||||||
} hotkeys[1<<(sizeof(char)*8)];
|
|
||||||
|
|
||||||
static void conf(struct menu *menu);
|
static void conf(struct menu *menu);
|
||||||
static void conf_choice(struct menu *menu);
|
static void conf_choice(struct menu *menu);
|
||||||
|
@ -292,6 +290,7 @@ static void conf_save(void);
|
||||||
static void show_help(struct menu *menu);
|
static void show_help(struct menu *menu);
|
||||||
static int do_exit(void);
|
static int do_exit(void);
|
||||||
static void setup_windows(void);
|
static void setup_windows(void);
|
||||||
|
static void search_conf(void);
|
||||||
|
|
||||||
typedef void (*function_key_handler_t)(int *key, struct menu *menu);
|
typedef void (*function_key_handler_t)(int *key, struct menu *menu);
|
||||||
static void handle_f1(int *key, struct menu *current_item);
|
static void handle_f1(int *key, struct menu *current_item);
|
||||||
|
@ -302,6 +301,7 @@ static void handle_f5(int *key, struct menu *current_item);
|
||||||
static void handle_f6(int *key, struct menu *current_item);
|
static void handle_f6(int *key, struct menu *current_item);
|
||||||
static void handle_f7(int *key, struct menu *current_item);
|
static void handle_f7(int *key, struct menu *current_item);
|
||||||
static void handle_f8(int *key, struct menu *current_item);
|
static void handle_f8(int *key, struct menu *current_item);
|
||||||
|
static void handle_f9(int *key, struct menu *current_item);
|
||||||
|
|
||||||
struct function_keys {
|
struct function_keys {
|
||||||
const char *key_str;
|
const char *key_str;
|
||||||
|
@ -310,7 +310,7 @@ struct function_keys {
|
||||||
function_key_handler_t handler;
|
function_key_handler_t handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int function_keys_num = 8;
|
static const int function_keys_num = 9;
|
||||||
struct function_keys function_keys[] = {
|
struct function_keys function_keys[] = {
|
||||||
{
|
{
|
||||||
.key_str = "F1",
|
.key_str = "F1",
|
||||||
|
@ -320,13 +320,13 @@ struct function_keys function_keys[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.key_str = "F2",
|
.key_str = "F2",
|
||||||
.func = "Symbol Info",
|
.func = "Sym Info",
|
||||||
.key = F_SYMBOL,
|
.key = F_SYMBOL,
|
||||||
.handler = handle_f2,
|
.handler = handle_f2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.key_str = "F3",
|
.key_str = "F3",
|
||||||
.func = "Instructions",
|
.func = "Insts",
|
||||||
.key = F_INSTS,
|
.key = F_INSTS,
|
||||||
.handler = handle_f3,
|
.handler = handle_f3,
|
||||||
},
|
},
|
||||||
|
@ -356,9 +356,15 @@ struct function_keys function_keys[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.key_str = "F8",
|
.key_str = "F8",
|
||||||
|
.func = "Sym Search",
|
||||||
|
.key = F_SEARCH,
|
||||||
|
.handler = handle_f8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.key_str = "F9",
|
||||||
.func = "Exit",
|
.func = "Exit",
|
||||||
.key = F_EXIT,
|
.key = F_EXIT,
|
||||||
.handler = handle_f8,
|
.handler = handle_f9,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -444,8 +450,15 @@ static void handle_f7(int *key, struct menu *current_item)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exit */
|
/* search */
|
||||||
static void handle_f8(int *key, struct menu *current_item)
|
static void handle_f8(int *key, struct menu *current_item)
|
||||||
|
{
|
||||||
|
search_conf();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exit */
|
||||||
|
static void handle_f9(int *key, struct menu *current_item)
|
||||||
{
|
{
|
||||||
do_exit();
|
do_exit();
|
||||||
return;
|
return;
|
||||||
|
@ -479,110 +492,44 @@ static void clean_items(void)
|
||||||
free_item(curses_menu_items[i]);
|
free_item(curses_menu_items[i]);
|
||||||
bzero(curses_menu_items, sizeof(curses_menu_items));
|
bzero(curses_menu_items, sizeof(curses_menu_items));
|
||||||
bzero(k_menu_items, sizeof(k_menu_items));
|
bzero(k_menu_items, sizeof(k_menu_items));
|
||||||
bzero(hotkeys, sizeof(hotkeys));
|
|
||||||
items_num = 0;
|
items_num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the index of the next hot item, or -1 if no such item exists */
|
typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
|
||||||
static int get_next_hot(int c)
|
FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
|
||||||
|
|
||||||
|
/* return the index of the matched item, or -1 if no such item exists */
|
||||||
|
static int get_mext_match(const char *match_str, match_f flag)
|
||||||
{
|
{
|
||||||
static int hot_index;
|
int match_start = item_index(current_item(curses_menu));
|
||||||
static int hot_char;
|
int index;
|
||||||
|
|
||||||
if (c < 0 || c > 255 || hotkeys[c].count <= 0)
|
if (flag == FIND_NEXT_MATCH_DOWN)
|
||||||
return -1;
|
++match_start;
|
||||||
|
else if (flag == FIND_NEXT_MATCH_UP)
|
||||||
|
--match_start;
|
||||||
|
|
||||||
if (hot_char == c) {
|
index = match_start;
|
||||||
hot_index = (hot_index+1)%hotkeys[c].count;
|
index = (index + items_num) % items_num;
|
||||||
return hotkeys[c].ptrs[hot_index];
|
while (true) {
|
||||||
} else {
|
char *str = k_menu_items[index].str;
|
||||||
hot_char = c;
|
if (strcasestr(str, match_str) != 0)
|
||||||
hot_index = 0;
|
return index;
|
||||||
return hotkeys[c].ptrs[0];
|
if (flag == FIND_NEXT_MATCH_UP ||
|
||||||
|
flag == MATCH_TINKER_PATTERN_UP)
|
||||||
|
--index;
|
||||||
|
else
|
||||||
|
++index;
|
||||||
|
index = (index + items_num) % items_num;
|
||||||
|
if (index == match_start)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
|
/* Make a new item. */
|
||||||
static int canbhot(char c)
|
|
||||||
{
|
|
||||||
c = tolower(c);
|
|
||||||
return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
|
|
||||||
c != 'n' && c != '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if str already contains a hot key. */
|
|
||||||
static int is_hot(int index)
|
|
||||||
{
|
|
||||||
return k_menu_items[index].is_hot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the first possible hot key, and mark it.
|
|
||||||
* index is the index of the item in the menu
|
|
||||||
* return 0 on success*/
|
|
||||||
static int make_hot(char *dest, int len, const char *org, int index)
|
|
||||||
{
|
|
||||||
int position = -1;
|
|
||||||
int i;
|
|
||||||
int tmp;
|
|
||||||
int c;
|
|
||||||
int org_len = strlen(org);
|
|
||||||
|
|
||||||
if (org == NULL || is_hot(index))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* make sure not to make hot keys out of markers.
|
|
||||||
* find where to start looking for a hot key
|
|
||||||
*/
|
|
||||||
i = 0;
|
|
||||||
/* skip white space */
|
|
||||||
while (i < org_len && org[i] == ' ')
|
|
||||||
i++;
|
|
||||||
if (i == org_len)
|
|
||||||
return -1;
|
|
||||||
/* if encountering '(' or '<' or '[', find the match and look from there
|
|
||||||
**/
|
|
||||||
if (org[i] == '[' || org[i] == '<' || org[i] == '(') {
|
|
||||||
i++;
|
|
||||||
for (; i < org_len; i++)
|
|
||||||
if (org[i] == ']' || org[i] == '>' || org[i] == ')')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == org_len)
|
|
||||||
return -1;
|
|
||||||
for (; i < org_len; i++) {
|
|
||||||
if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
|
|
||||||
position = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (position == -1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* ok, char at org[position] should be a hot key to this item */
|
|
||||||
c = tolower(org[position]);
|
|
||||||
tmp = hotkeys[c].count;
|
|
||||||
hotkeys[c].ptrs[tmp] = index;
|
|
||||||
hotkeys[c].count++;
|
|
||||||
/*
|
|
||||||
snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
|
|
||||||
&org[position+1]);
|
|
||||||
*/
|
|
||||||
/* make org[position] uppercase, and all leading letter small case */
|
|
||||||
strncpy(dest, org, len);
|
|
||||||
for (i = 0; i < position; i++)
|
|
||||||
dest[i] = tolower(dest[i]);
|
|
||||||
dest[position] = toupper(dest[position]);
|
|
||||||
k_menu_items[index].is_hot = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a new item. Add a hotkey mark in the first possible letter.
|
|
||||||
* As ncurses does not allow any attributes inside menue item, we mark the
|
|
||||||
* hot key as the first capitalized letter in the string */
|
|
||||||
static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char tmp_str[256];
|
|
||||||
|
|
||||||
if (items_num > MAX_MENU_ITEMS-1)
|
if (items_num > MAX_MENU_ITEMS-1)
|
||||||
return;
|
return;
|
||||||
|
@ -597,16 +544,13 @@ static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
||||||
k_menu_items[items_num].is_visible = 1;
|
k_menu_items[items_num].is_visible = 1;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap);
|
vsnprintf(k_menu_items[items_num].str,
|
||||||
if (!k_menu_items[items_num].is_visible)
|
sizeof(k_menu_items[items_num].str),
|
||||||
memcpy(tmp_str, "XXX", 3);
|
fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (make_hot(
|
|
||||||
k_menu_items[items_num].str,
|
if (!k_menu_items[items_num].is_visible)
|
||||||
sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0)
|
memcpy(k_menu_items[items_num].str, "XXX", 3);
|
||||||
strncpy(k_menu_items[items_num].str,
|
|
||||||
tmp_str,
|
|
||||||
sizeof(k_menu_items[items_num].str));
|
|
||||||
|
|
||||||
curses_menu_items[items_num] = new_item(
|
curses_menu_items[items_num] = new_item(
|
||||||
k_menu_items[items_num].str,
|
k_menu_items[items_num].str,
|
||||||
|
@ -638,11 +582,9 @@ static void item_add_str(const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
snprintf(tmp_str, sizeof(tmp_str), "%s%s",
|
snprintf(tmp_str, sizeof(tmp_str), "%s%s",
|
||||||
k_menu_items[index].str, new_str);
|
k_menu_items[index].str, new_str);
|
||||||
if (make_hot(k_menu_items[index].str,
|
strncpy(k_menu_items[index].str,
|
||||||
sizeof(k_menu_items[index].str), tmp_str, index) != 0)
|
tmp_str,
|
||||||
strncpy(k_menu_items[index].str,
|
sizeof(k_menu_items[index].str));
|
||||||
tmp_str,
|
|
||||||
sizeof(k_menu_items[index].str));
|
|
||||||
|
|
||||||
free_item(curses_menu_items[index]);
|
free_item(curses_menu_items[index]);
|
||||||
curses_menu_items[index] = new_item(
|
curses_menu_items[index] = new_item(
|
||||||
|
@ -1027,23 +969,18 @@ static void reset_menu(void)
|
||||||
static void center_item(int selected_index, int *last_top_row)
|
static void center_item(int selected_index, int *last_top_row)
|
||||||
{
|
{
|
||||||
int toprow;
|
int toprow;
|
||||||
int maxy, maxx;
|
|
||||||
|
|
||||||
scale_menu(curses_menu, &maxy, &maxx);
|
|
||||||
set_top_row(curses_menu, *last_top_row);
|
set_top_row(curses_menu, *last_top_row);
|
||||||
toprow = top_row(curses_menu);
|
toprow = top_row(curses_menu);
|
||||||
if (selected_index >= toprow && selected_index < toprow+maxy) {
|
if (selected_index < toprow ||
|
||||||
/* we can only move the selected item. no need to scroll */
|
selected_index >= toprow+mwin_max_lines) {
|
||||||
set_current_item(curses_menu,
|
toprow = max(selected_index-mwin_max_lines/2, 0);
|
||||||
curses_menu_items[selected_index]);
|
if (toprow >= item_count(curses_menu)-mwin_max_lines)
|
||||||
} else {
|
|
||||||
toprow = max(selected_index-maxy/2, 0);
|
|
||||||
if (toprow >= item_count(curses_menu)-maxy)
|
|
||||||
toprow = item_count(curses_menu)-mwin_max_lines;
|
toprow = item_count(curses_menu)-mwin_max_lines;
|
||||||
set_top_row(curses_menu, toprow);
|
set_top_row(curses_menu, toprow);
|
||||||
set_current_item(curses_menu,
|
|
||||||
curses_menu_items[selected_index]);
|
|
||||||
}
|
}
|
||||||
|
set_current_item(curses_menu,
|
||||||
|
curses_menu_items[selected_index]);
|
||||||
*last_top_row = toprow;
|
*last_top_row = toprow;
|
||||||
post_menu(curses_menu);
|
post_menu(curses_menu);
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
|
@ -1075,7 +1012,7 @@ static void show_menu(const char *prompt, const char *instructions,
|
||||||
/* position the menu at the middle of the screen */
|
/* position the menu at the middle of the screen */
|
||||||
scale_menu(curses_menu, &maxy, &maxx);
|
scale_menu(curses_menu, &maxy, &maxx);
|
||||||
maxx = min(maxx, mwin_max_cols-2);
|
maxx = min(maxx, mwin_max_cols-2);
|
||||||
maxy = mwin_max_lines-2;
|
maxy = mwin_max_lines;
|
||||||
menu_window = derwin(main_window,
|
menu_window = derwin(main_window,
|
||||||
maxy,
|
maxy,
|
||||||
maxx,
|
maxx,
|
||||||
|
@ -1099,10 +1036,77 @@ static void show_menu(const char *prompt, const char *instructions,
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void adj_match_dir(match_f *match_direction)
|
||||||
|
{
|
||||||
|
if (*match_direction == FIND_NEXT_MATCH_DOWN)
|
||||||
|
*match_direction =
|
||||||
|
MATCH_TINKER_PATTERN_DOWN;
|
||||||
|
else if (*match_direction == FIND_NEXT_MATCH_UP)
|
||||||
|
*match_direction =
|
||||||
|
MATCH_TINKER_PATTERN_UP;
|
||||||
|
/* else, do no change.. */
|
||||||
|
}
|
||||||
|
|
||||||
|
struct match_state
|
||||||
|
{
|
||||||
|
int in_search;
|
||||||
|
match_f match_direction;
|
||||||
|
char pattern[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return 0 means I have handled the key. In such a case, ans should hold the
|
||||||
|
* item to center, or -1 otherwise.
|
||||||
|
* Else return -1 .
|
||||||
|
*/
|
||||||
|
static int do_match(int key, struct match_state *state, int *ans)
|
||||||
|
{
|
||||||
|
char c = (char) key;
|
||||||
|
int terminate_search = 0;
|
||||||
|
*ans = -1;
|
||||||
|
if (key == '/' || (state->in_search && key == 27)) {
|
||||||
|
move(0, 0);
|
||||||
|
refresh();
|
||||||
|
clrtoeol();
|
||||||
|
state->in_search = 1-state->in_search;
|
||||||
|
bzero(state->pattern, sizeof(state->pattern));
|
||||||
|
state->match_direction = MATCH_TINKER_PATTERN_DOWN;
|
||||||
|
return 0;
|
||||||
|
} else if (!state->in_search)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (isalnum(c) || isgraph(c) || c == ' ') {
|
||||||
|
state->pattern[strlen(state->pattern)] = c;
|
||||||
|
state->pattern[strlen(state->pattern)] = '\0';
|
||||||
|
adj_match_dir(&state->match_direction);
|
||||||
|
*ans = get_mext_match(state->pattern,
|
||||||
|
state->match_direction);
|
||||||
|
} else if (key == KEY_DOWN) {
|
||||||
|
state->match_direction = FIND_NEXT_MATCH_DOWN;
|
||||||
|
*ans = get_mext_match(state->pattern,
|
||||||
|
state->match_direction);
|
||||||
|
} else if (key == KEY_UP) {
|
||||||
|
state->match_direction = FIND_NEXT_MATCH_UP;
|
||||||
|
*ans = get_mext_match(state->pattern,
|
||||||
|
state->match_direction);
|
||||||
|
} else if (key == KEY_BACKSPACE || key == 127) {
|
||||||
|
state->pattern[strlen(state->pattern)-1] = '\0';
|
||||||
|
adj_match_dir(&state->match_direction);
|
||||||
|
} else
|
||||||
|
terminate_search = 1;
|
||||||
|
|
||||||
|
if (terminate_search) {
|
||||||
|
state->in_search = 0;
|
||||||
|
bzero(state->pattern, sizeof(state->pattern));
|
||||||
|
move(0, 0);
|
||||||
|
refresh();
|
||||||
|
clrtoeol();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void conf(struct menu *menu)
|
static void conf(struct menu *menu)
|
||||||
{
|
{
|
||||||
char pattern[256];
|
|
||||||
struct menu *submenu = 0;
|
struct menu *submenu = 0;
|
||||||
const char *prompt = menu_get_prompt(menu);
|
const char *prompt = menu_get_prompt(menu);
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
@ -1110,8 +1114,11 @@ static void conf(struct menu *menu)
|
||||||
int res;
|
int res;
|
||||||
int current_index = 0;
|
int current_index = 0;
|
||||||
int last_top_row = 0;
|
int last_top_row = 0;
|
||||||
|
struct match_state match_state = {
|
||||||
bzero(pattern, sizeof(pattern));
|
.in_search = 0,
|
||||||
|
.match_direction = MATCH_TINKER_PATTERN_DOWN,
|
||||||
|
.pattern = "",
|
||||||
|
};
|
||||||
|
|
||||||
while (!global_exit) {
|
while (!global_exit) {
|
||||||
reset_menu();
|
reset_menu();
|
||||||
|
@ -1124,7 +1131,22 @@ static void conf(struct menu *menu)
|
||||||
_(menu_instructions),
|
_(menu_instructions),
|
||||||
current_index, &last_top_row);
|
current_index, &last_top_row);
|
||||||
keypad((menu_win(curses_menu)), TRUE);
|
keypad((menu_win(curses_menu)), TRUE);
|
||||||
while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
|
while (!global_exit) {
|
||||||
|
if (match_state.in_search) {
|
||||||
|
mvprintw(0, 0,
|
||||||
|
"searching: %s", match_state.pattern);
|
||||||
|
clrtoeol();
|
||||||
|
}
|
||||||
|
refresh_all_windows(main_window);
|
||||||
|
res = wgetch(menu_win(curses_menu));
|
||||||
|
if (!res)
|
||||||
|
break;
|
||||||
|
if (do_match(res, &match_state, ¤t_index) == 0) {
|
||||||
|
if (current_index != -1)
|
||||||
|
center_item(current_index,
|
||||||
|
&last_top_row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (process_special_keys(&res,
|
if (process_special_keys(&res,
|
||||||
(struct menu *) item_data()))
|
(struct menu *) item_data()))
|
||||||
break;
|
break;
|
||||||
|
@ -1155,19 +1177,13 @@ static void conf(struct menu *menu)
|
||||||
if (res == 10 || res == 27 ||
|
if (res == 10 || res == 27 ||
|
||||||
res == 32 || res == 'n' || res == 'y' ||
|
res == 32 || res == 'n' || res == 'y' ||
|
||||||
res == KEY_LEFT || res == KEY_RIGHT ||
|
res == KEY_LEFT || res == KEY_RIGHT ||
|
||||||
res == 'm' || res == '/')
|
res == 'm')
|
||||||
break;
|
break;
|
||||||
else if (canbhot(res)) {
|
|
||||||
/* check for hot keys: */
|
|
||||||
int tmp = get_next_hot(res);
|
|
||||||
if (tmp != -1)
|
|
||||||
center_item(tmp, &last_top_row);
|
|
||||||
}
|
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
/* if ESC or left*/
|
/* if ESC or left*/
|
||||||
if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
|
if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1235,9 +1251,6 @@ static void conf(struct menu *menu)
|
||||||
if (item_is_tag('t'))
|
if (item_is_tag('t'))
|
||||||
sym_set_tristate_value(sym, mod);
|
sym_set_tristate_value(sym, mod);
|
||||||
break;
|
break;
|
||||||
case '/':
|
|
||||||
search_conf();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1268,6 +1281,11 @@ static void conf_choice(struct menu *menu)
|
||||||
int selected_index = 0;
|
int selected_index = 0;
|
||||||
int last_top_row = 0;
|
int last_top_row = 0;
|
||||||
int res, i = 0;
|
int res, i = 0;
|
||||||
|
struct match_state match_state = {
|
||||||
|
.in_search = 0,
|
||||||
|
.match_direction = MATCH_TINKER_PATTERN_DOWN,
|
||||||
|
.pattern = "",
|
||||||
|
};
|
||||||
|
|
||||||
active = sym_get_choice_value(menu->sym);
|
active = sym_get_choice_value(menu->sym);
|
||||||
/* this is mostly duplicated from the conf() function. */
|
/* this is mostly duplicated from the conf() function. */
|
||||||
|
@ -1294,7 +1312,22 @@ static void conf_choice(struct menu *menu)
|
||||||
_(radiolist_instructions),
|
_(radiolist_instructions),
|
||||||
selected_index,
|
selected_index,
|
||||||
&last_top_row);
|
&last_top_row);
|
||||||
while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
|
while (!global_exit) {
|
||||||
|
if (match_state.in_search) {
|
||||||
|
mvprintw(0, 0, "searching: %s",
|
||||||
|
match_state.pattern);
|
||||||
|
clrtoeol();
|
||||||
|
}
|
||||||
|
refresh_all_windows(main_window);
|
||||||
|
res = wgetch(menu_win(curses_menu));
|
||||||
|
if (!res)
|
||||||
|
break;
|
||||||
|
if (do_match(res, &match_state, &selected_index) == 0) {
|
||||||
|
if (selected_index != -1)
|
||||||
|
center_item(selected_index,
|
||||||
|
&last_top_row);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (process_special_keys(
|
if (process_special_keys(
|
||||||
&res,
|
&res,
|
||||||
(struct menu *) item_data()))
|
(struct menu *) item_data()))
|
||||||
|
@ -1324,13 +1357,8 @@ static void conf_choice(struct menu *menu)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (res == 10 || res == 27 || res == ' ' ||
|
if (res == 10 || res == 27 || res == ' ' ||
|
||||||
res == KEY_LEFT)
|
res == KEY_LEFT){
|
||||||
break;
|
break;
|
||||||
else if (canbhot(res)) {
|
|
||||||
/* check for hot keys: */
|
|
||||||
int tmp = get_next_hot(res);
|
|
||||||
if (tmp != -1)
|
|
||||||
center_item(tmp, &last_top_row);
|
|
||||||
}
|
}
|
||||||
refresh_all_windows(main_window);
|
refresh_all_windows(main_window);
|
||||||
}
|
}
|
||||||
|
@ -1485,7 +1513,7 @@ void setup_windows(void)
|
||||||
/* set up the menu and menu window */
|
/* set up the menu and menu window */
|
||||||
main_window = newwin(LINES-2, COLS-2, 2, 1);
|
main_window = newwin(LINES-2, COLS-2, 2, 1);
|
||||||
keypad(main_window, TRUE);
|
keypad(main_window, TRUE);
|
||||||
mwin_max_lines = LINES-6;
|
mwin_max_lines = LINES-7;
|
||||||
mwin_max_cols = COLS-6;
|
mwin_max_cols = COLS-6;
|
||||||
|
|
||||||
/* panels order is from bottom to top */
|
/* panels order is from bottom to top */
|
||||||
|
@ -1532,9 +1560,10 @@ int main(int ac, char **av)
|
||||||
/* set btns menu */
|
/* set btns menu */
|
||||||
curses_menu = new_menu(curses_menu_items);
|
curses_menu = new_menu(curses_menu_items);
|
||||||
menu_opts_off(curses_menu, O_SHOWDESC);
|
menu_opts_off(curses_menu, O_SHOWDESC);
|
||||||
menu_opts_off(curses_menu, O_SHOWMATCH);
|
menu_opts_on(curses_menu, O_SHOWMATCH);
|
||||||
menu_opts_on(curses_menu, O_ONEVALUE);
|
menu_opts_on(curses_menu, O_ONEVALUE);
|
||||||
menu_opts_on(curses_menu, O_NONCYCLIC);
|
menu_opts_on(curses_menu, O_NONCYCLIC);
|
||||||
|
menu_opts_on(curses_menu, O_IGNORECASE);
|
||||||
set_menu_mark(curses_menu, " ");
|
set_menu_mark(curses_menu, " ");
|
||||||
set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
|
set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
|
||||||
set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
|
set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
|
||||||
|
@ -1550,8 +1579,6 @@ int main(int ac, char **av)
|
||||||
_(menu_no_f_instructions));
|
_(menu_no_f_instructions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* do the work */
|
/* do the work */
|
||||||
while (!global_exit) {
|
while (!global_exit) {
|
||||||
conf(&rootmenu);
|
conf(&rootmenu);
|
||||||
|
|
|
@ -167,7 +167,7 @@ void print_in_middle(WINDOW *win,
|
||||||
length = strlen(string);
|
length = strlen(string);
|
||||||
temp = (width - length) / 2;
|
temp = (width - length) / 2;
|
||||||
x = startx + (int)temp;
|
x = startx + (int)temp;
|
||||||
wattrset(win, color);
|
(void) wattrset(win, color);
|
||||||
mvwprintw(win, y, x, "%s", string);
|
mvwprintw(win, y, x, "%s", string);
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
@ -297,11 +297,11 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
|
||||||
set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
|
set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
|
||||||
set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
|
set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
|
||||||
|
|
||||||
wattrset(win, attributes[DIALOG_BOX]);
|
(void) wattrset(win, attributes[DIALOG_BOX]);
|
||||||
box(win, 0, 0);
|
box(win, 0, 0);
|
||||||
|
|
||||||
/* print message */
|
/* print message */
|
||||||
wattrset(msg_win, attributes[DIALOG_TEXT]);
|
(void) wattrset(msg_win, attributes[DIALOG_TEXT]);
|
||||||
fill_window(msg_win, msg);
|
fill_window(msg_win, msg);
|
||||||
|
|
||||||
set_menu_win(menu, win);
|
set_menu_win(menu, win);
|
||||||
|
@ -392,16 +392,16 @@ int dialog_inputbox(WINDOW *main_window,
|
||||||
form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
|
form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
|
||||||
keypad(form_win, TRUE);
|
keypad(form_win, TRUE);
|
||||||
|
|
||||||
wattrset(form_win, attributes[INPUT_FIELD]);
|
(void) wattrset(form_win, attributes[INPUT_FIELD]);
|
||||||
|
|
||||||
wattrset(win, attributes[INPUT_BOX]);
|
(void) wattrset(win, attributes[INPUT_BOX]);
|
||||||
box(win, 0, 0);
|
box(win, 0, 0);
|
||||||
wattrset(win, attributes[INPUT_HEADING]);
|
(void) wattrset(win, attributes[INPUT_HEADING]);
|
||||||
if (title)
|
if (title)
|
||||||
mvwprintw(win, 0, 3, "%s", title);
|
mvwprintw(win, 0, 3, "%s", title);
|
||||||
|
|
||||||
/* print message */
|
/* print message */
|
||||||
wattrset(prompt_win, attributes[INPUT_TEXT]);
|
(void) wattrset(prompt_win, attributes[INPUT_TEXT]);
|
||||||
fill_window(prompt_win, prompt);
|
fill_window(prompt_win, prompt);
|
||||||
|
|
||||||
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
|
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
|
||||||
|
@ -531,7 +531,7 @@ void show_scroll_win(WINDOW *main_window,
|
||||||
|
|
||||||
/* create the pad */
|
/* create the pad */
|
||||||
pad = newpad(total_lines+10, total_cols+10);
|
pad = newpad(total_lines+10, total_cols+10);
|
||||||
wattrset(pad, attributes[SCROLLWIN_TEXT]);
|
(void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
|
||||||
fill_window(pad, text);
|
fill_window(pad, text);
|
||||||
|
|
||||||
win_lines = min(total_lines+4, LINES-2);
|
win_lines = min(total_lines+4, LINES-2);
|
||||||
|
@ -546,9 +546,9 @@ void show_scroll_win(WINDOW *main_window,
|
||||||
win = newwin(win_lines, win_cols, y, x);
|
win = newwin(win_lines, win_cols, y, x);
|
||||||
keypad(win, TRUE);
|
keypad(win, TRUE);
|
||||||
/* show the help in the help window, and show the help panel */
|
/* show the help in the help window, and show the help panel */
|
||||||
wattrset(win, attributes[SCROLLWIN_BOX]);
|
(void) wattrset(win, attributes[SCROLLWIN_BOX]);
|
||||||
box(win, 0, 0);
|
box(win, 0, 0);
|
||||||
wattrset(win, attributes[SCROLLWIN_HEADING]);
|
(void) wattrset(win, attributes[SCROLLWIN_HEADING]);
|
||||||
mvwprintw(win, 0, 3, " %s ", title);
|
mvwprintw(win, 0, 3, " %s ", title);
|
||||||
panel = new_panel(win);
|
panel = new_panel(win);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,8 @@ typedef enum {
|
||||||
F_BACK = 5,
|
F_BACK = 5,
|
||||||
F_SAVE = 6,
|
F_SAVE = 6,
|
||||||
F_LOAD = 7,
|
F_LOAD = 7,
|
||||||
F_EXIT = 8
|
F_SEARCH = 8,
|
||||||
|
F_EXIT = 9,
|
||||||
} function_key;
|
} function_key;
|
||||||
|
|
||||||
void set_colors(void);
|
void set_colors(void);
|
||||||
|
|
Loading…
Reference in a new issue