Skip to content

Instantly share code, notes, and snippets.

@cjgajard
Created September 18, 2020 09:47
Show Gist options
  • Save cjgajard/aaaf0bff27b19a873f43be8e7dfe9975 to your computer and use it in GitHub Desktop.
Save cjgajard/aaaf0bff27b19a873f43be8e7dfe9975 to your computer and use it in GitHub Desktop.
Template for command line with ncurses in C
#include <ctype.h>
#include <curses.h>
#include <locale.h>
#include <string.h>
#include <time.h>
#define CTRL(c) ((c) & 0x1f)
#define FPS 30
static int columns = 80;
static int lines = 24;
static char character = 'A';
static char boxsiz = 5;
#define BOXWY ((lines - boxsiz) / 2)
#define BOXWX ((columns - boxsiz) / 2)
char input[512] = {0};
size_t ix = 0;
size_t ilen = 0;
time_t pvtime = 0;
int main (void)
{
/* SETUP */
setlocale(LC_ALL, "");
initscr();
noecho();
nonl();
getmaxyx(stdscr, lines, columns);
bool boxw_dirty = TRUE;
WINDOW *boxw = newwin(boxsiz, 2 * boxsiz, BOXWY, BOXWX);
bool inputw_dirty = TRUE;
WINDOW *inputw = newwin(1, columns, lines - 1, 0);
nodelay(inputw, TRUE);
keypad(inputw, TRUE);
pvtime = time(NULL);
while (1) {
/* DRAW */
curs_set(FALSE);
if (boxw_dirty) {
wbkgdset(boxw, character);
wclear(boxw);
wrefresh(boxw);
boxw_dirty = FALSE;
}
if (inputw_dirty) {
mvwprintw(inputw, 0, 0, ":%s", input);
wclrtoeol(inputw);
wrefresh(inputw);
inputw_dirty = FALSE;
}
wmove(inputw, 0, ix + 1);
curs_set(TRUE);
/* EVENT */
bool exec_flag = FALSE;
int byte;
while ((byte = wgetch(inputw)) != ERR) {
if (byte == EOF) {
break;
}
else if (byte == CTRL('m') || byte == '\n') {
exec_flag = TRUE;
break;
}
else if (byte == 0x7F /* ascii-DEL */) {
if (ix > 0)
input[--ix] = 0;
boxw_dirty = TRUE;
continue;
}
else if (byte == KEY_RESIZE) {
clear();
refresh();
getmaxyx(stdscr, lines, columns);
mvwin(boxw, BOXWY, BOXWX);
boxw_dirty = TRUE;
mvwin(inputw, lines - 1, 0);
inputw_dirty = TRUE;
continue;
}
else if (!isprint(byte)) {
continue;
}
if (ix >= sizeof(input) - 1) {
continue;
}
input[ix++] = (char)byte & 0xff;
input[ix] = 0;
ilen++;
inputw_dirty = TRUE;
}
if (exec_flag) {
if (!strcmp(input, "q"))
break;
if (!strcmp(input, "quit"))
break;
ix = ilen = 0;
input[ix] = 0;
inputw_dirty = TRUE;
}
/* NEXT */
napms(1000.0 / FPS);
/* UPDATE */
time_t t = time(NULL);
if (t - pvtime >= 1) {
if (++character > 'Z')
character = 'A';
pvtime = t;
boxw_dirty = TRUE;
}
}
/* CLOSE */
delwin(boxw);
delwin(inputw);
endwin();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment