Last active
October 26, 2017 06:47
-
-
Save alan-mushi/375a569833f67724322b to your computer and use it in GitHub Desktop.
Very simple pop-up using ncurses form and menu library (not CDK) in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Very simple pop-up using ncurses form and menu library (not CDK). | |
* | |
* The buttons are made from items and the fields are made from... well fields. | |
* | |
* How to run: | |
* gcc -o test -lmenu -lform -lncurses ncurses-simple-pop-up.c -g && ./test | |
*/ | |
// Depending on your OS you might need to remove 'ncurses/' from the include path. | |
#include <ncurses/form.h> | |
#include <ncurses/menu.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <string.h> | |
/* | |
+-------------------------------+ <-- win_body | |
|+-----------------------------+| | |
|| || | |
|| || | |
|| win_form || | |
|| || | |
|| || | |
|+-----------------------------+| | |
|+-----------------------------+| | |
|| win_menu || | |
|+-----------------------------+| | |
+-------------------------------+ | |
*/ | |
WINDOW *win_body, *win_form, *win_menu; | |
FORM *form; | |
FIELD **fields; | |
MENU *menu; | |
ITEM **items; | |
bool is_on_button; // Used to know the "case" we're in | |
void new_popup(int rows, int cols, int posy, int posx, char **buttons, | |
int nb_buttons, char **requests, int nb_fields) | |
{ | |
int i, cury = 0, curx = 1, tmp; | |
WINDOW *inner; | |
win_body = newwin(rows, cols, posy, posx); | |
assert(win_body != NULL); | |
box(win_body, 0, 0); | |
items = malloc(sizeof(ITEM *) * (nb_buttons+1)); | |
assert(items); | |
for (i = 0; i < nb_buttons; i++) { | |
items[i] = new_item(buttons[i], ""); | |
assert(items[i] != NULL); | |
} | |
items[i] = NULL; | |
menu = new_menu(items); | |
win_menu = derwin(win_body, 3, cols-2, rows-4, 1); | |
assert(menu != NULL && win_menu != NULL); | |
box(win_menu, 0, 0); | |
set_menu_win(menu, win_menu); | |
set_menu_format(menu, 1, nb_buttons); | |
tmp = menu->fcols * (menu->namelen + menu->spc_rows); | |
tmp--; | |
inner = derwin(win_menu, 1, tmp, 1, (cols-3-tmp)/2); | |
assert(inner != NULL); | |
set_menu_sub(menu, inner); | |
set_menu_mark(menu, ""); | |
fields = malloc(sizeof(FIELD *) * (nb_fields+1)); | |
assert(fields); | |
for (i = 0; i < nb_fields; i++) { | |
fields[i] = new_field(1, 10, cury, curx, 0, 0); | |
assert(fields[i] != NULL); | |
set_field_buffer(fields[i], 0, requests[i]); | |
if (i % 2 == 1) { | |
cury = cury+1; | |
curx = 1; | |
field_opts_on(fields[i], O_ACTIVE); | |
field_opts_on(fields[i], O_EDIT); | |
set_field_back(fields[i], A_UNDERLINE); | |
} else { | |
curx = 20; | |
field_opts_off(fields[i], O_ACTIVE); | |
field_opts_off(fields[i], O_EDIT); | |
} | |
} | |
fields[i] = NULL; | |
form = new_form(fields); | |
assert(form != NULL); | |
win_form = derwin(win_body, rows-5, cols-2, 1, 1); | |
box(win_form, 0, 0); | |
assert(form != NULL && win_form != NULL); | |
set_form_win(form, win_form); | |
inner = derwin(win_form, form->rows+1, form->cols+1, 1, 1); | |
assert(inner != NULL); | |
set_form_sub(form, inner); | |
assert(post_form(form) == E_OK); | |
assert(post_menu(menu) == E_OK); | |
is_on_button = true; | |
pos_menu_cursor(menu); | |
} | |
void delete_popup(void) | |
{ | |
int i; | |
unpost_form(form); | |
unpost_menu(menu); | |
for (i = 0; fields[i] != NULL; i++) { | |
free_field(fields[i]); | |
} | |
for (i = 0; items[i] != NULL; i++) { | |
free_item(items[i]); | |
} | |
free_menu(menu); | |
free_form(form); | |
delwin(win_form); | |
delwin(win_menu); | |
delwin(win_body); | |
} | |
/* | |
* Actions for 'return' on a button | |
*/ | |
void driver_buttons(ITEM *item) | |
{ | |
const char *name = item_name(item); | |
int i; | |
if (strcmp(name, "OK") == 0) { | |
mvprintw(LINES-2, 1, "[*] OK clicked:\t"); | |
for (i = 0; i < form->maxfield; i++) { | |
printw("%s", field_buffer(fields[i], 0)); | |
if (field_opts(fields[i]) & O_ACTIVE) | |
printw("\t"); | |
} | |
} else if (strcmp(name, "QUIT") == 0) | |
mvprintw(LINES-2, 1, "[*] QUIT clicked, 'F1' to quit\n"); | |
refresh(); | |
} | |
/* | |
* When you want to change between the form and the buttons | |
*/ | |
void switch_to_buttons(void) | |
{ | |
// Those 2 lines allow the field buffer to be set | |
form_driver(form, REQ_PREV_FIELD); | |
form_driver(form, REQ_NEXT_FIELD); | |
menu_driver(menu, REQ_FIRST_ITEM); | |
is_on_button = true; | |
set_menu_fore(menu, A_REVERSE); // "show" the button | |
} | |
void driver(int ch) | |
{ | |
switch (ch) { | |
case KEY_DOWN: | |
if (is_on_button) | |
break; | |
if (form->current == fields[form->maxfield-1]) | |
switch_to_buttons(); | |
else | |
form_driver(form, REQ_NEXT_FIELD); | |
break; | |
case KEY_UP: | |
if (is_on_button) { | |
is_on_button = false; | |
set_menu_fore(menu, A_NORMAL); // "hide" the button | |
} else | |
form_driver(form, REQ_PREV_FIELD); | |
break; | |
case KEY_LEFT: | |
if (is_on_button) | |
menu_driver(menu, REQ_LEFT_ITEM); | |
else | |
form_driver(form, REQ_LEFT_FIELD); | |
break; | |
case KEY_RIGHT: | |
if (is_on_button) | |
menu_driver(menu, REQ_RIGHT_ITEM); | |
else | |
form_driver(form, REQ_RIGHT_FIELD); | |
break; | |
case 10: | |
if (!is_on_button) | |
switch_to_buttons(); | |
else | |
driver_buttons(current_item(menu)); | |
break; | |
default: | |
if (!is_on_button) | |
form_driver(form, ch); | |
break; | |
} | |
if (is_on_button) | |
pos_menu_cursor(menu); | |
else | |
pos_form_cursor(form); | |
wrefresh(win_body); | |
} | |
int main() | |
{ | |
char *buttons[] = { "OK", "QUIT" }; | |
char *requests[] = { "Password:", "pass", "Id:", "id" }; | |
int ch; | |
initscr(); | |
noecho(); | |
cbreak(); | |
keypad(stdscr, TRUE); | |
new_popup(24, 80, (LINES-25)/2, (COLS-81)/2, buttons, 2, requests, 4); | |
refresh(); | |
wrefresh(win_body); | |
wrefresh(win_form); | |
wrefresh(win_menu); | |
while ((ch = getch()) != KEY_F(1)) | |
driver(ch); | |
delete_popup(); | |
endwin(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks.
Your one example is enough to start off with making forms.