graphcurses

Curses 2D graph generator
git clone git://git.christosmarg.xyz/graphcurses.git
Log | Files | Refs | README | LICENSE

commit 7a7b0064282012b506b69e86421e1275e5f7b149
parent 822895e0be32336e97b8afb42efe81de4ed905ea
Author: Christos Margiolis <christos@margiolis.net>
Date:   Mon, 19 Oct 2020 04:47:56 +0300

improved style, made indentation 8 spaces

Diffstat:
MMakefile | 54+++++++++++++++++++++++++++---------------------------
Mgraphcurses.c | 361+++++++++++++++++++++++++++++++++++++++++++------------------------------------
2 files changed, 225 insertions(+), 190 deletions(-)

diff --git a/Makefile b/Makefile @@ -13,10 +13,10 @@ SRC = ${wildcard *.${EXT}} OBJ = ${SRC:%.${EXT}=%.o} CC = gcc -INCS += -Iinclude -CPPFLAGS += -U__STRICT_ANSI__ -DVERSION=\"${VERSION}\" -CFLAGS += -Wall -std=c99 -pedantic -O3 ${INCS} ${CPPFLAGS} -LDFLAGS += -Llib -lm -lmatheval -lncurses +INCS = -Iinclude +CPPFLAGS = -U__STRICT_ANSI__ -DVERSION=\"${VERSION}\" +CFLAGS = -Wall -std=c99 -pedantic -O3 ${INCS} ${CPPFLAGS} +LDFLAGS = -Llib -lm -lmatheval -lncurses CP = cp -f RM = rm -f @@ -28,41 +28,41 @@ GZIP = gzip all: options ${BIN} options: - @echo ${BIN} build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" - @echo "CC = ${CC}" + @echo ${BIN} build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" ${BIN}: ${OBJ} - ${CC} ${LDFLAGS} $^ -o $@ + ${CC} ${LDFLAGS} $^ -o $@ -%.o: %.${EXT} - ${CC} ${CFLAGS} -c $< -o $@ +${OBJ}: ${SRC} + ${CC} ${CFLAGS} -c $< -o $@ dist: clean - ${MKDIR} ${DIST} - ${CP} -R ${SRC} LICENSE Makefile README.md ${DIST} - ${TAR} ${DIST}.tar ${DIST} - ${GZIP} ${DIST}.tar - ${RM_DIR} ${DIST} + ${MKDIR} ${DIST} + ${CP} -R ${SRC} LICENSE Makefile README.md ${DIST} + ${TAR} ${DIST}.tar ${DIST} + ${GZIP} ${DIST}.tar + ${RM_DIR} ${DIST} run: - ./${BIN} + ./${BIN} install: all - #${MKDIR} ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN_DIR} - ${MKDIR} ${DESTDIR}${BIN_DIR} - ${CP} ${BIN} ${BIN_DIR} - #${CP} ${MAN1} ${DESTDIR}${MAN_DIR} - #sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MAN_DIR}/${MAN1} - chmod 755 ${DESTDIR}${BIN_DIR}/${BIN} - #chmod 644 ${DESTDIR}${MAN_DIR}/${MAN1} + #${MKDIR} ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN_DIR} + ${MKDIR} ${DESTDIR}${BIN_DIR} + ${CP} ${BIN} ${BIN_DIR} + #${CP} ${MAN1} ${DESTDIR}${MAN_DIR} + #sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MAN_DIR}/${MAN1} + chmod 755 ${DESTDIR}${BIN_DIR}/${BIN} + #chmod 644 ${DESTDIR}${MAN_DIR}/${MAN1} uninstall: - ${RM} ${DESTDIR}${BIN_DIR}/${BIN} - #${RM} ${DESTDIR}${MAN_DIR}/${MAN1} + ${RM} ${DESTDIR}${BIN_DIR}/${BIN} + #${RM} ${DESTDIR}${MAN_DIR}/${MAN1} clean: - ${RM} ${BIN} ${OBJ} ${DIST}.tar.gz + ${RM} ${BIN} ${OBJ} ${DIST}.tar.gz .PHONY: all options clean dist install uninstall run diff --git a/graphcurses.c b/graphcurses.c @@ -21,12 +21,12 @@ #define YMAX() (getmaxy(stdscr)) #define XMAX() (getmaxx(stdscr)) #define CENTER(x, y) ((x) / 2 - (y) / 2) -#define PLANE_SCALE(val, omin, omax, nmin, nmax) \ - ((((val) - (omin)) / ((omax) - (omin))) * ((nmax) - (nmin)) + (nmin)) -#define PLANE_XSTEP(p, xstep) \ - xstep = (p->xmax - p->xmin) / (p->xmaxs + 1.0f); -#define PLANE_YSTEP(p, ystep) \ - ystep = (p->xmax - p->ymin) / (p->ymaxs + 1.0f); +#define PLANE_SCALE(val, omin, omax, nmin, nmax) \ + ((((val) - (omin)) / ((omax) - (omin))) * ((nmax) - (nmin)) + (nmin)) +#define PLANE_XSTEP(p, xstep) \ + xstep = (p->xmax - p->xmin) / (p->xmaxs + 1.0f); +#define PLANE_YSTEP(p, ystep) \ + ystep = (p->xmax - p->ymin) / (p->ymaxs + 1.0f); #define OPT_QUIT "q Quit" #define OPT_MOVE_UP "Up/k Move up" @@ -41,13 +41,13 @@ #define MSG_QUIT_MENU "Press any key to quit the menu" struct Plane { - float (*f)(float); - void *df; - float ymin, ymax; - float xmin, xmax; - float xscale, yscale; - int ymaxs, xmaxs; - int derivative_show; + float (*f)(float); + void *df; + float ymin, ymax; + float xmin, xmax; + float xscale, yscale; + int ymaxs, xmaxs; + int derivative_show; }; static void *f = NULL; @@ -70,229 +70,264 @@ static void menu_fill(struct _win_st *); void curses_init(void) { - initscr(); - cbreak(); - noecho(); - curs_set(0); - keypad(stdscr, 1); - start_color(); - init_pair(1, COLOR_WHITE, COLOR_BLACK); - init_pair(2, COLOR_CYAN, COLOR_BLACK); - init_pair(3, COLOR_RED, COLOR_BLACK); + initscr(); + cbreak(); + noecho(); + curs_set(0); + keypad(stdscr, 1); + start_color(); + init_pair(1, COLOR_WHITE, COLOR_BLACK); + init_pair(2, COLOR_CYAN, COLOR_BLACK); + init_pair(3, COLOR_RED, COLOR_BLACK); } void func_get(struct Plane *p, char *buf) { - move(0, 0); - clrtoeol(); - printw("f(x) = "); - echo(); - refresh(); - getnstr(buf, BUFFSIZE); - zoom_restore(p); - refresh(); - noecho(); + move(0, 0); + clrtoeol(); + printw("f(x) = "); + echo(); + refresh(); + getnstr(buf, BUFFSIZE); + zoom_restore(p); + refresh(); + noecho(); } void expression_validate(struct Plane *p) { - char *buf = (char *)malloc(BUFFSIZE + sizeof(char)); - func_get(p, buf); - while (!(f = evaluator_create(buf))) { - printw("Error in expression! Try again"); + char *buf; + + if ((buf = (char *)malloc(BUFFSIZE + sizeof(char))) == NULL) { + fputs("Cannot allocate memory. Exiting. . .\n", stderr); + exit(EXIT_FAILURE); + } func_get(p, buf); - refresh(); - } - p->df = evaluator_derivative_x(f); - free(buf); + while (!(f = evaluator_create(buf))) { + printw("Error in expression! Try again"); + func_get(p, buf); + refresh(); + } + p->df = evaluator_derivative_x(f); + free(buf); } float expression_evaluate(float x) { - return evaluator_evaluate_x(f, x); + return evaluator_evaluate_x(f, x); } void keys_handle(struct Plane *p, int key) { - switch (key) { - case 'k': case KEY_UP: plane_shift(p, 0.0f, SHIFT_STEP); break; - case 'j': case KEY_DOWN: plane_shift(p, 0.0f, -SHIFT_STEP); break; - case 'h': case KEY_LEFT: plane_shift(p, -SHIFT_STEP, 0.0f); break; - case 'l': case KEY_RIGHT: plane_shift(p, SHIFT_STEP, 0.0f); break; - case '+': zoom_handle(p, ZOOM_IN_FACTOR); break; - case '-': zoom_handle(p, ZOOM_OUT_FACTOR); break; - case 'd': p->derivative_show = !p->derivative_show; break; - case 'r': zoom_restore(p); break; - case 'f': expression_validate(p); break; - case 'm': menu_options(); break; - } + switch (key) { + case 'k': case KEY_UP: + plane_shift(p, 0.0f, SHIFT_STEP); + break; + case 'j': case KEY_DOWN: + plane_shift(p, 0.0f, -SHIFT_STEP); + break; + case 'h': case KEY_LEFT: + plane_shift(p, -SHIFT_STEP, 0.0f); + break; + case 'l': case KEY_RIGHT: + plane_shift(p, SHIFT_STEP, 0.0f); + break; + case '+': + zoom_handle(p, ZOOM_IN_FACTOR); + break; + case '-': + zoom_handle(p, ZOOM_OUT_FACTOR); + break; + case 'd': + p->derivative_show = !p->derivative_show; + break; + case 'r': + zoom_restore(p); + break; + case 'f': + expression_validate(p); + break; + case 'm': + menu_options(); + break; + } } void plane_init(struct Plane *p) { - p->xmin = XMIN_PLANE; - p->xmax = XMAX_PLANE; - p->ymin = YMIN_PLANE; - p->ymax = YMAX_PLANE; - p->xscale = XSCALE_PLANE; - p->yscale = YSCALE_PLANE; - p->xmaxs = XMAX(); - p->ymaxs = YMAX(); + p->xmin = XMIN_PLANE; + p->xmax = XMAX_PLANE; + p->ymin = YMIN_PLANE; + p->ymax = YMAX_PLANE; + p->xscale = XSCALE_PLANE; + p->yscale = YSCALE_PLANE; + p->xmaxs = XMAX(); + p->ymaxs = YMAX(); } void plane_shift(struct Plane *p, float xshift, float yshift) { - xshift *= (p->xmax - p->xmin) / 16.0f; - yshift *= (p->ymax - p->ymin) / 16.0f; - p->xmin += xshift; - p->xmax += xshift; - p->ymin += yshift; - p->ymax += yshift; + xshift *= (p->xmax - p->xmin) / 16.0f; + yshift *= (p->ymax - p->ymin) / 16.0f; + p->xmin += xshift; + p->xmax += xshift; + p->ymin += yshift; + p->ymax += yshift; } void zoom_restore(struct Plane *p) { - p->xmin = XMIN_PLANE; - p->xmax = XMAX_PLANE; - p->ymin = YMIN_PLANE; - p->ymax = YMAX_PLANE; - p->xscale = XSCALE_PLANE; - p->yscale = YSCALE_PLANE; + p->xmin = XMIN_PLANE; + p->xmax = XMAX_PLANE; + p->ymin = YMIN_PLANE; + p->ymax = YMAX_PLANE; + p->xscale = XSCALE_PLANE; + p->yscale = YSCALE_PLANE; } void zoom_handle(struct Plane *p, float factor) { - float xctr = (p->xmin + p->ymax) / 2.0f; - float yctr = (p->ymin + p->ymax) / 2.0f; - p->xmin = PLANE_SCALE(factor, 1.0f, 0.0f, p->xmin, xctr); - p->xmax = PLANE_SCALE(factor, 1.0f, 0.0f, p->xmax, xctr); - p->ymin = PLANE_SCALE(factor, 1.0f, 0.0f, p->ymin, yctr); - p->ymax = PLANE_SCALE(factor, 1.0f, 0.0f, p->ymax, yctr); + float xctr = (p->xmin + p->ymax) / 2.0f; + float yctr = (p->ymin + p->ymax) / 2.0f; + + p->xmin = PLANE_SCALE(factor, 1.0f, 0.0f, p->xmin, xctr); + p->xmax = PLANE_SCALE(factor, 1.0f, 0.0f, p->xmax, xctr); + p->ymin = PLANE_SCALE(factor, 1.0f, 0.0f, p->ymin, yctr); + p->ymax = PLANE_SCALE(factor, 1.0f, 0.0f, p->ymax, yctr); } void axes_draw(const struct Plane *p) { - float x0 = PLANE_SCALE(0.0f, p->xmin, p->xmax, 0.0f, p->xmaxs); - float y0 = PLANE_SCALE(0.0f, p->ymin, p->ymax, p->ymaxs, 0.0f); - float xstep, ystep, i; - PLANE_XSTEP(p, xstep); - PLANE_YSTEP(p, ystep); - for (i = 0.0f; i < p->xmaxs; i += xstep) { - float plotx = p->xmin + xstep * i; - int tick = fabs(fmod(plotx, p->xscale)) < xstep; - mvaddch(y0, i, tick ? ACS_PLUS : ACS_HLINE); - } - for (i = 0.0f; i < p->ymaxs; i += ystep) { - float ploty = p->ymin + ystep * i; - int tick = fabs(fmod(ploty, p->yscale)) < ystep; - mvaddch(i, x0, tick ? ACS_PLUS : ACS_VLINE); - } - mvaddch(y0, x0, ACS_PLUS); + float x0, y0, xstep, ystep, plotx, ploty, i; + int tick; + + x0 = PLANE_SCALE(0.0f, p->xmin, p->xmax, 0.0f, p->xmaxs); + y0 = PLANE_SCALE(0.0f, p->ymin, p->ymax, p->ymaxs, 0.0f); + PLANE_XSTEP(p, xstep); + PLANE_YSTEP(p, ystep); + for (i = 0.0f; i < p->xmaxs; i += xstep) { + plotx = p->xmin + xstep * i; + tick = fabs(fmod(plotx, p->xscale)) < xstep; + mvaddch(y0, i, tick ? ACS_PLUS : ACS_HLINE); + } + for (i = 0.0f; i < p->ymaxs; i += ystep) { + ploty = p->ymin + ystep * i; + tick = fabs(fmod(ploty, p->yscale)) < ystep; + mvaddch(i, x0, tick ? ACS_PLUS : ACS_VLINE); + } + mvaddch(y0, x0, ACS_PLUS); } void graph_draw(const struct Plane *p) { - float x, xstep; - PLANE_XSTEP(p, xstep); - for (x = p->xmin; x <= p->xmax; x += xstep) { - float y = p->f(x); - attron(COLOR_PAIR(2)); - graph_plot(p, x, y); - if (p->derivative_show) { - float dy = evaluator_evaluate_x(p->df, x); - attron(COLOR_PAIR(3)); - graph_plot(p, x, dy); + float x, y, dy, xstep; + + PLANE_XSTEP(p, xstep); + for (x = p->xmin; x <= p->xmax; x += xstep) { + y = p->f(x); + attron(COLOR_PAIR(2)); + graph_plot(p, x, y); + if (p->derivative_show) { + dy = evaluator_evaluate_x(p->df, x); + attron(COLOR_PAIR(3)); + graph_plot(p, x, dy); + } } - } - attroff(COLOR_PAIR(3)); - attroff(COLOR_PAIR(2)); + attroff(COLOR_PAIR(3)); + attroff(COLOR_PAIR(2)); } void graph_plot(const struct Plane *p, float x, float y) { - float xp = PLANE_SCALE(x, p->xmin, p->xmax, 0.0f, p->xmaxs); - float yp = PLANE_SCALE(y, p->ymin, p->ymax, p->ymaxs, 0.0f); - mvaddch(yp, xp, '.'); + float xp = PLANE_SCALE(x, p->xmin, p->xmax, 0.0f, p->xmaxs); + float yp = PLANE_SCALE(y, p->ymin, p->ymax, p->ymaxs, 0.0f); + + mvaddch(yp, xp, '.'); } void menu_options(void) { - int w = 33, h = 14; - int wy = CENTER(YMAX(), h); - int wx = CENTER(XMAX(), w); - WINDOW *opts = newwin(h, w, wy, wx); - werase(opts); - box(opts, 0, 0); - menu_fill(opts); - wrefresh(opts); - wgetch(opts); - werase(opts); - wrefresh(opts); - delwin(opts); + int w, h, wy, wh; + WINDOW *opts; + + w = 33; + h = 14; + wy = CENTER(YMAX(), h); + wx = CENTER(XMAX(), w); + opts = newwin(h, w, wy, wx); + werase(opts); + box(opts, 0, 0); + menu_fill(opts); + wrefresh(opts); + wgetch(opts); + werase(opts); + wrefresh(opts); + delwin(opts); } void menu_fill(WINDOW *opts) { - mvwprintw(opts, 1, 1, OPT_QUIT); - mvwprintw(opts, 2, 1, OPT_MOVE_UP); - mvwprintw(opts, 3, 1, OPT_MOVE_DOWN); - mvwprintw(opts, 4, 1, OPT_MOVE_LEFT); - mvwprintw(opts, 5, 1, OPT_MOVE_RIGHT); - mvwprintw(opts, 6, 1, OPT_SHOW_DERIVATIVE); - mvwprintw(opts, 7, 1, OPT_NEW_FUNCTION); - mvwprintw(opts, 8, 1, OPT_RESTORE_ZOOM); - mvwprintw(opts, 9, 1, OPT_ZOOM_IN); - mvwprintw(opts, 10, 1, OPT_ZOOM_OUT); - mvwprintw(opts, 12, 1, MSG_QUIT_MENU); + mvwprintw(opts, 1, 1, OPT_QUIT); + mvwprintw(opts, 2, 1, OPT_MOVE_UP); + mvwprintw(opts, 3, 1, OPT_MOVE_DOWN); + mvwprintw(opts, 4, 1, OPT_MOVE_LEFT); + mvwprintw(opts, 5, 1, OPT_MOVE_RIGHT); + mvwprintw(opts, 6, 1, OPT_SHOW_DERIVATIVE); + mvwprintw(opts, 7, 1, OPT_NEW_FUNCTION); + mvwprintw(opts, 8, 1, OPT_RESTORE_ZOOM); + mvwprintw(opts, 9, 1, OPT_ZOOM_IN); + mvwprintw(opts, 10, 1, OPT_ZOOM_OUT); + mvwprintw(opts, 12, 1, MSG_QUIT_MENU); } int main(int argc, char **argv) { #ifndef NCURSES_VERSION - fputs("ncurses is needed in order to run this program.\n", stderr); - return EXIT_FAILURE; + fputs("ncurses is needed in order to run this program.\n", stderr); + return EXIT_FAILURE; #endif /* NCURSES_VERSION */ - curses_init(); - struct Plane p; - plane_init(&p); - zoom_restore(&p); - expression_validate(&p); - p.derivative_show = 0; - p.f = expression_evaluate; + struct Plane p; + int key = 0; - int key = 0; - for (; key != 'q'; key = getch()) { - keys_handle(&p, key); - erase(); - attron(COLOR_PAIR(1)); - attron(A_REVERSE); - attron(A_BOLD); - mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f)); - if (p.derivative_show) - mvprintw(1, 0, "f'(x) = %s", evaluator_get_string(p.df)); - attroff(A_REVERSE); - attroff(A_BOLD); - axes_draw(&p); - attroff(COLOR_PAIR(1)); - graph_draw(&p); - refresh(); - } - - endwin(); - evaluator_destroy(f); - return EXIT_SUCCESS; + curses_init(); + plane_init(&p); + zoom_restore(&p); + expression_validate(&p); + p.derivative_show = 0; + p.f = expression_evaluate; + + for (; key != 'q'; key = getch()) { + keys_handle(&p, key); + erase(); + attron(COLOR_PAIR(1)); + attron(A_REVERSE); + attron(A_BOLD); + mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f)); + if (p.derivative_show) + mvprintw(1, 0, "f'(x) = %s", evaluator_get_string(p.df)); + attroff(A_REVERSE); + attroff(A_BOLD); + axes_draw(&p); + attroff(COLOR_PAIR(1)); + graph_draw(&p); + refresh(); + } + + endwin(); + evaluator_destroy(f); + return EXIT_SUCCESS; }