-
-
Save alan-mushi/c8a6f34d1df18574f643 to your computer and use it in GitHub Desktop.
/* | |
* Simple ncurses form example with fields that actually behaves like fields. | |
* | |
* How to run: | |
* gcc -Wall -Werror -g -pedantic -o test fields_magic.c -lform -lncurses | |
*/ | |
#include <ncurses/ncurses.h> | |
#include <ncurses/form.h> | |
#include <assert.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <ctype.h> | |
static FORM *form; | |
static FIELD *fields[5]; | |
static WINDOW *win_body, *win_form; | |
/* | |
* This is useful because ncurses fill fields blanks with spaces. | |
*/ | |
static char* trim_whitespaces(char *str) | |
{ | |
char *end; | |
// trim leading space | |
while(isspace(*str)) | |
str++; | |
if(*str == 0) // all spaces? | |
return str; | |
// trim trailing space | |
end = str + strnlen(str, 128) - 1; | |
while(end > str && isspace(*end)) | |
end--; | |
// write new null terminator | |
*(end+1) = '\0'; | |
return str; | |
} | |
static void driver(int ch) | |
{ | |
int i; | |
switch (ch) { | |
case KEY_F(2): | |
// Or the current field buffer won't be sync with what is displayed | |
form_driver(form, REQ_NEXT_FIELD); | |
form_driver(form, REQ_PREV_FIELD); | |
move(LINES-3, 2); | |
for (i = 0; fields[i]; i++) { | |
printw("%s", trim_whitespaces(field_buffer(fields[i], 0))); | |
if (field_opts(fields[i]) & O_ACTIVE) | |
printw("\"\t"); | |
else | |
printw(": \""); | |
} | |
refresh(); | |
pos_form_cursor(form); | |
break; | |
case KEY_DOWN: | |
form_driver(form, REQ_NEXT_FIELD); | |
form_driver(form, REQ_END_LINE); | |
break; | |
case KEY_UP: | |
form_driver(form, REQ_PREV_FIELD); | |
form_driver(form, REQ_END_LINE); | |
break; | |
case KEY_LEFT: | |
form_driver(form, REQ_PREV_CHAR); | |
break; | |
case KEY_RIGHT: | |
form_driver(form, REQ_NEXT_CHAR); | |
break; | |
// Delete the char before cursor | |
case KEY_BACKSPACE: | |
case 127: | |
form_driver(form, REQ_DEL_PREV); | |
break; | |
// Delete the char under the cursor | |
case KEY_DC: | |
form_driver(form, REQ_DEL_CHAR); | |
break; | |
default: | |
form_driver(form, ch); | |
break; | |
} | |
wrefresh(win_form); | |
} | |
int main() | |
{ | |
int ch; | |
initscr(); | |
noecho(); | |
cbreak(); | |
keypad(stdscr, TRUE); | |
win_body = newwin(24, 80, 0, 0); | |
assert(win_body != NULL); | |
box(win_body, 0, 0); | |
win_form = derwin(win_body, 20, 78, 3, 1); | |
assert(win_form != NULL); | |
box(win_form, 0, 0); | |
mvwprintw(win_body, 1, 2, "Press F1 to quit and F2 to print fields content"); | |
fields[0] = new_field(1, 10, 0, 0, 0, 0); | |
fields[1] = new_field(1, 40, 0, 15, 0, 0); | |
fields[2] = new_field(1, 10, 2, 0, 0, 0); | |
fields[3] = new_field(1, 40, 2, 15, 0, 0); | |
fields[4] = NULL; | |
assert(fields[0] != NULL && fields[1] != NULL && fields[2] != NULL && fields[3] != NULL); | |
set_field_buffer(fields[0], 0, "label1"); | |
set_field_buffer(fields[1], 0, "val1"); | |
set_field_buffer(fields[2], 0, "label2"); | |
set_field_buffer(fields[3], 0, "val2"); | |
set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_AUTOSKIP); | |
set_field_opts(fields[1], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE); | |
set_field_opts(fields[2], O_VISIBLE | O_PUBLIC | O_AUTOSKIP); | |
set_field_opts(fields[3], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE); | |
set_field_back(fields[1], A_UNDERLINE); | |
set_field_back(fields[3], A_UNDERLINE); | |
form = new_form(fields); | |
assert(form != NULL); | |
set_form_win(form, win_form); | |
set_form_sub(form, derwin(win_form, 18, 76, 1, 1)); | |
post_form(form); | |
refresh(); | |
wrefresh(win_body); | |
wrefresh(win_form); | |
while ((ch = getch()) != KEY_F(1)) | |
driver(ch); | |
unpost_form(form); | |
free_form(form); | |
free_field(fields[0]); | |
free_field(fields[1]); | |
free_field(fields[2]); | |
free_field(fields[3]); | |
delwin(win_form); | |
delwin(win_body); | |
endwin(); | |
return 0; | |
} |
Please accept a constructive criticism from a CS professor:
No contribution to community knowledge is complete without adequate comments.
With that said, thank you for this example.
What should I do to change the color of text input fields ? set_field_fore/back functions changed the color of field names, I.e. label1 label 2 etc, I want only the input text fields to be colored differently, so as to distinguish them from the rest.
You could add the following lines to the driver function to support POS1 and END:
case KEY_HOME:
form_driver(form, REQ_BEG_LINE);
break;
case KEY_END:
form_driver(form, REQ_END_LINE);
break;
I need help. How i can to store field[5] value to char array[5][],
How can we delete the subwindow which is created on line 145 using derwin function?
If you need help with designing the front end of your form (in particular coordinates) then you can try our form designer utility. It is not fully featured but it can save a lot of time putting in wrong coordinates, building, moving things around, rebuilding etc. ssh [email protected] password is "nc". If you want to know how to use it then head over to https://level2.support?_req=form_designer.
It only does the basics though because the rest need our library (which currently needs to much work to release into the wild and has a bucket load of dependencies).
To answer you question in your blog post, lines 51, 52 may be replaced by
form_driver(form, REQ_VALIDATION);
(from last line of the section "Direct Field Buffer Manipulation" in http://invisible-island.net/ncurses/ncurses-intro.html#fbuffer