-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmmenu.h
119 lines (110 loc) · 2.36 KB
/
mmenu.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdlib.h>
#include <ncurses.h>
#include <locale.h>
#ifndef MAX_STR_SIZE // Of user input
#define MAX_STR_SIZE 128
#endif
int str_in_str(char* substr, char* str) {
if(str[0] == '\0') return 0; // Never match empty strings.
int i = 0, j = 0;
do {
if(str[i] == substr[j]) j++;
else j = 0;
if(substr[j] == '\0') return 1;
i++;
}
while(str[i] != '\0');
return 0;
}
int str_len(char* str) {
//does not include '\0'
int i = 0;
while(str[i] != '\0') i++;
return i;
}
int mmenu(char** options, int options_len, char* prompt) {
setlocale(LC_ALL, "");
FILE* f = fopen("/dev/tty", "r+");
SCREEN* screen = newterm(NULL, f, f);
set_term(screen);
cbreak();
noecho();
keypad(stdscr, TRUE);
int rows, cols;
getmaxyx(stdscr, rows, cols);
char* str = malloc(MAX_STR_SIZE * sizeof(char));
if(str == NULL) exit(1);
int len = 0;
int chr;
int selection = 1;
printw(prompt);
int prompt_len = str_len(prompt);
for(int i = 0; i < rows - 1 && i < options_len; i++) {
move(i + 1, 0);
if(i == 0) attron(A_STANDOUT);
printw("%.*s", cols, options[i]);
if(i == 0) attroff(A_STANDOUT);
}
move(0, prompt_len + len); // Move cursor back to text.
refresh();
while((chr = getch()) != 27) {
if(chr == '\n') {
int filtered = 0;
for(int i = 0; i < options_len; i++){
if(str_in_str(str, options[i])) {
filtered++;
if(filtered == selection) {
endwin();
free(str);
return i;
}
}
}
break; //exit 0
}
switch(chr){
case KEY_BACKSPACE: // Backspace
case KEY_LEFT: // For when backspace breaks
if(len > 0) {
len--;
str[len] = '\0';
}
break;
case KEY_UP:
if(selection > 1)
selection--;
break;
case KEY_DOWN:
if(selection < rows - 1)
selection++;
break;
case '\n':
break;
case KEY_RIGHT: break;
default:
if(len != MAX_STR_SIZE - 1 && chr < 255) {
str[len] = chr;
len++;
}
selection = 1;
break;
}
move(0, prompt_len);
clrtobot();
printw(str);
for(int i = 0, line = 0; i < options_len && line < rows; i++) {
if(str_in_str(str, options[i])) {
line++;
move(line, 0);
if(line == selection) attron(A_STANDOUT);
printw("%.*s", cols, options[i]);
if(line == selection) attroff(A_STANDOUT);
}
}
move(0, prompt_len + len); // Move cursor back to text.
refresh();
}
endwin();
free(str);
return -1;
}