commit 067ba1b4855ea7ba50964d411bfabb87ddbba706
parent eda41ce995fbd41f7b3f6ef5a9dc2efcf9a23b34
Author: Christos Margiolis <christos@margiolis.net>
Date: Wed, 26 May 2021 19:01:03 +0300
i don't know
Diffstat:
M | LICENSE | | | 41 | ++++++++++++++++------------------------- |
M | Makefile | | | 42 | +++++++++++++++++++++--------------------- |
M | README.md | | | 4 | ++-- |
M | config.mk | | | 26 | +++++++------------------- |
M | graphcurses.1 | | | 8 | ++++---- |
M | graphcurses.c | | | 565 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
6 files changed, 341 insertions(+), 345 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -1,29 +1,20 @@
-BSD 3-Clause License
+MIT License
-Copyright (c) 2020-present, Christos Margiolis.
-All rights reserved.
+(c) 2020-Present Christos Margiolis <christos@margiolis.net>
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the “Software”), to deal in
+the Software without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of images.weserv.nl nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -1,5 +1,5 @@
# See LICENSE file for copyright and license details.
-# graphcurses - an ncurses 2D graph generator
+# graphcurses - curses(3) 2D graph generator
.POSIX:
include config.mk
@@ -8,47 +8,47 @@ BIN = graphcurses
DIST = ${BIN}-${VERSION}
MAN1 = ${BIN}.1
-EXT = c
SRC = graphcurses.c
-OBJ = ${SRC:.${EXT}=.o}
+OBJ = ${SRC:.c=.o}
all: options ${BIN}
options:
@echo ${BIN} build options:
- @echo "CFLAGS = ${CFLAGS}"
- @echo "LDFLAGS = ${LDFLAGS}"
- @echo "CC = ${CC}"
+ @echo "CFLAGS = ${CFLAGS}"
+ @echo "LDFLAGS = ${LDFLAGS}"
+ @echo "CC = ${CC}"
${BIN}: ${OBJ}
${CC} ${LDFLAGS} ${OBJ} -o $@
-.${EXT}.o:
+.c.o:
${CC} -c ${CFLAGS} $<
dist: clean
- ${MKDIR} ${DIST}
- ${CP} -R config.mk ${MAN1} ${SRC} LICENSE Makefile README.md ${DIST}
- ${TAR} ${DIST}.tar ${DIST}
- ${GZIP} ${DIST}.tar
- ${RM_DIR} ${DIST}
+ mkdir -p ${DIST}
+ cp -R config.mk graphcurses.1 graphcurses.c LICENSE Makefile \
+ README.md ${DIST}
+ tar -cf ${DIST}.tar ${DIST}
+ gzip ${DIST}.tar
+ rm -rf ${DIST}
run:
./${BIN}
install: all
- ${MKDIR} ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN_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 -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${MANPREFIX}/man1
+ cp -f ${BIN} ${DESTDIR}${PREFIX}/bin
+ cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1
+ sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MANPREFIX}/man1/${MAN1}
+ chmod 755 ${DESTDIR}${PREFIX}/bin/${BIN}
+ chmod 644 ${DESTDIR}${MANPREFIX}/man1/${MAN1}
uninstall:
- ${RM} ${DESTDIR}${BIN_DIR}/${BIN}
- ${RM} ${DESTDIR}${MAN_DIR}/${MAN1}
+ rm -f ${DESTDIR}${PREFIX}/bin/${BIN} \
+ ${DESTDIR}${MANPREFIX}/man1/${MAN1}
clean:
- ${RM} ${BIN} ${OBJ} ${DIST}.tar.gz
+ rm -f ${BIN} ${OBJ} ${DIST}.tar.gz *.core
.PHONY: all options clean dist install uninstall run
diff --git a/README.md b/README.md
@@ -1,12 +1,12 @@
# graphcurses
-A simple ncurses graph generator.
+A simple curses graph generator.
![preview](https://user-images.githubusercontent.com/54286563/102025554-66e14380-3da1-11eb-81e0-ea7cfc8c1161.png)
## Dependencies
-* `ncurses`
+* `curses`
* `libmatheval`
## Usage
diff --git a/config.mk b/config.mk
@@ -1,32 +1,20 @@
# See LICENSE file for copyright and license details.
# graphcurses version
-VERSION = 0
+VERSION = 0.1
# paths
PREFIX = /usr/local
-MAN_DIR = ${PREFIX}/man/man1
-BIN_DIR = ${PREFIX}/bin
+MANPREFIX = ${PREFIX}/share/man
# includes and libs
-INCS = -Iinclude
-LIBS = -Llib -lm -lmatheval -lncurses
+INCS = -Iinclude -I${PREFIX}/include
+LIBS = -Llib -L${PREFIX}/lib -lncursesw -lmatheval -lm
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L \
- -D_XOPEN_SOURCE=600 -DVERSION=\"${VERSION}\" -U__STRICT_ANSI__
-CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations \
- -O3 ${INCS} ${CPPFLAGS}
+ -D_XOPEN_SOURCE=700 -DVERSION=\"${VERSION}\"
+CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS}
-# utils
-CP = cp -f
-RM = rm -f
-RM_DIR = rm -rf
-MV = mv
-MKDIR = mkdir -p
-RM_DIR = rm -rf
-TAR = tar -cf
-GZIP = gzip
-
# compiler
-CC = gcc
+CC = cc
diff --git a/graphcurses.1 b/graphcurses.1
@@ -3,13 +3,13 @@
.Os
.Sh NAME
.Nm graphcurses
-.Nd ncurses 2D graph generator
+.Nd curses 2D graph generator
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
takes a function as an input and draws it using
-.Xr ncurses 3
+.Xr curses 3
to draw the TUI. Functions and derivatives are evaluated by
.Xr libmatheval 3
and might use
@@ -40,8 +40,8 @@ zoom in
.It Sy -
zoom out
.Sh SEE ALSO
-.Xr ncurses 3 ,
+.Xr curses 3 ,
.Xr libmatheval 3 ,
.Xr math 3
.Sh AUTHORS
-.An Christos Margiolis Aq Mt christos@christosmarg.xyz
+.An Christos Margiolis Aq Mt christos@margiolis.net
diff --git a/graphcurses.c b/graphcurses.c
@@ -1,338 +1,355 @@
/* See LICENSE file for copyright and license details. */
+#include <err.h>
#include <math.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <curses.h>
#include <matheval.h>
-#include <ncurses.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
-
-#define XMIN_PLANE (-2.0f * M_PI)
-#define XMAX_PLANE ( 2.0f * M_PI)
-#define YMIN_PLANE (-M_PI)
-#define YMAX_PLANE M_PI
-#define XSCALE_PLANE 1.0f
-#define YSCALE_PLANE 1.0f
-#define SHIFT_STEP 1.0f
-#define ZOOM_IN_FACTOR (1.0f / 1.05f)
-#define ZOOM_OUT_FACTOR 1.05f
-#define BUFSIZE 256
-
-#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 OPT_QUIT "q Quit"
-#define OPT_MOVE_UP "Up/k Move up"
-#define OPT_MOVE_DOWN "Down/j Move down"
-#define OPT_MOVE_LEFT "Left/h Move left"
-#define OPT_MOVE_RIGHT "Right/l Move right"
-#define OPT_SHOW_DERIVATIVE "d Show derivative"
-#define OPT_NEW_FUNCTION "f New function"
-#define OPT_RESTORE_ZOOM "r Restore zoom"
-#define OPT_ZOOM_IN "+ Zoom in"
-#define OPT_ZOOM_OUT "- Zoom out"
-#define MSG_QUIT_MENU "Press any key to quit the menu"
-
-typedef struct {
- float (*f)(float);
- void *df;
- float ymin;
- float ymax;
- float xmin;
- float xmax;
- float xscale;
- float yscale;
- int ymaxs;
- int xmaxs;
- int derivshow;
-} Plane;
-
-static void cursesinit(void);
-static void funcget(Plane *, char *);
-static void exprvalidate(Plane *);
-static float expreval(float);
-static Plane *planeinit(void);
-static void planeshift(Plane *, float, float);
-static void zoomrestore(Plane *);
-static void zoomhandle(Plane *, float);
-static void axesdraw(const Plane *);
-static void graphdraw(const Plane *);
-static void graphplot(const Plane *, float, float);
-static void menuopts(void);
-
-static void *f = NULL;
+#ifndef SIGWINCH
+#define SIGWINCH 28
+#endif /* SIGWINCH */
+#define SHIFT_STEP 1.0f
+#define BUFSIZE 256
+
+#define YMAX (getmaxy(stdscr))
+#define XMAX (getmaxx(stdscr))
+#define CENTER(x, y) (((x) >> 1) - ((y) >> 1))
+#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 ARRLEN(x) (sizeof(x) / sizeof(x[0]))
+
+struct plane {
+ float (*f)(float);
+ void *df;
+ float ymin;
+ float ymax;
+ float xmin;
+ float xmax;
+ float xscale;
+ float yscale;
+ int ymaxs;
+ int xmaxs;
+ int derivshow;
+};
+
+enum {
+ C_FG = 1,
+ C_F,
+ C_DF,
+};
+
+static void cursesinit(void);
+static void exprvalidate(void);
+static float expreval(float);
+static void planeinit(void);
+static void planeshift(float, float);
+static void zoomrestore(void);
+static void zoomhandle(float);
+static void axesdraw(void);
+static void graphdraw(void);
+static void graphplot(float, float);
+static void menuopts(void);
+static void sighandler(int);
+static void cleanup(void);
+
+static struct plane *p;
+static void *f = NULL;
+static int colors[] = {
+ [C_FG] = COLOR_BLUE,
+ [C_F] = COLOR_YELLOW,
+ [C_DF] = COLOR_MAGENTA,
+};
static void
cursesinit(void)
{
- if (!initscr()) {
- fputs("graphcurses: initscr: cannot initialiaze ncurses", stderr);
- exit(EXIT_FAILURE);
- }
- 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);
-}
-
-static void
-funcget(Plane *p, char *buf)
-{
- move(0, 0);
- clrtoeol();
- printw("f(x) = ");
- echo();
- refresh();
- getnstr(buf, BUFSIZE);
- zoomrestore(p);
- refresh();
- noecho();
+ struct sigaction sa;
+ int i;
+
+ if (!initscr())
+ errx(1, "initscr");
+ cbreak();
+ noecho();
+ curs_set(0);
+ keypad(stdscr, 1);
+
+ start_color();
+ use_default_colors();
+ for (i = 1; i < ARRLEN(colors); i++)
+ (void)init_pair(i, colors[i], -1);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sighandler;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGWINCH, &sa, NULL);
}
static void
-exprvalidate(Plane *p)
+exprvalidate(void)
{
- char *buf;
-
- if ((buf = malloc(BUFSIZE)) == NULL) {
- fputs("graphcurses: exprvalidate: cannot allocate memory", stderr);
- exit(EXIT_FAILURE);
- }
- funcget(p, buf);
- while (!(f = evaluator_create(buf))) {
- printw("Error in expression! Try again");
- funcget(p, buf);
- refresh();
- }
- p->df = evaluator_derivative_x(f);
- free(buf);
+ char *buf;
+
+ if ((buf = malloc(BUFSIZE)) == NULL)
+ err(1, "malloc");
+ attron(COLOR_PAIR(C_FG));
+ for (;;) {
+ move(0, 0);
+ clrtoeol();
+ printw("f(x) = ");
+ echo();
+ refresh();
+ if (getnstr(buf, BUFSIZE) == ERR)
+ continue;
+ zoomrestore();
+ refresh();
+ noecho();
+ if (!(f = evaluator_create(buf)))
+ printw("Error in expression! Try again");
+ else
+ break;
+ refresh();
+ }
+ attroff(COLOR_PAIR(C_FG));
+ p->df = evaluator_derivative_x(f);
+ free(buf);
}
static float
expreval(float x)
{
- return evaluator_evaluate_x(f, x);
+ return evaluator_evaluate_x(f, x);
}
-static Plane *
+static void
planeinit(void)
{
- Plane *p;
-
- if ((p = malloc(sizeof(Plane))) == NULL) {
- fputs("graphcurses: planeinit: cannot allocate memory", stderr);
- exit(EXIT_FAILURE);
- }
-
- p->xmaxs = XMAX;
- p->ymaxs = YMAX;
- p->derivshow = 0;
- p->f = expreval;
- zoomrestore(p);
-
- return p;
+ if ((p = malloc(sizeof(struct plane))) == NULL)
+ err(1, "malloc");
+ p->xmaxs = XMAX;
+ p->ymaxs = YMAX;
+ p->derivshow = 0;
+ p->f = expreval;
+ zoomrestore();
}
static void
-planeshift(Plane *p, float xshift, float yshift)
+planeshift(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;
}
static void
-zoomrestore(Plane *p)
+zoomrestore(void)
{
- 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 = -2.0f * M_PI;
+ p->xmax = 2.0f * M_PI;
+ p->ymin = -M_PI;
+ p->ymax = M_PI;
+ p->xscale = 1.0f;
+ p->yscale = 1.0f;
}
static void
-zoomhandle(Plane *p, float factor)
+zoomhandle(float factor)
{
- float xctr = (p->xmin + p->ymax) / 2.0f;
- float yctr = (p->ymin + p->ymax) / 2.0f;
+ 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);
+ 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);
}
static void
-axesdraw(const Plane *p)
+axesdraw(void)
{
- 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);
+ 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);
}
static void
-graphdraw(const Plane *p)
+graphdraw(void)
{
- 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));
- graphplot(p, x, y);
- if (p->derivshow) {
- dy = evaluator_evaluate_x(p->df, x);
- attron(COLOR_PAIR(3));
- graphplot(p, x, dy);
- }
- }
- attroff(COLOR_PAIR(2) | COLOR_PAIR(3));
+ 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(C_F));
+ graphplot(x, y);
+ if (p->derivshow) {
+ dy = evaluator_evaluate_x(p->df, x);
+ attron(COLOR_PAIR(C_DF));
+ graphplot(x, dy);
+ }
+ }
+ attroff(COLOR_PAIR(C_F) | COLOR_PAIR(C_DF));
}
static void
-graphplot(const Plane *p, float x, float y)
+graphplot(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);
+ 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, '.');
+ mvaddch(yp, xp, '.');
}
static void
menuopts(void)
{
- WINDOW *opts;
- int w, h, wy, wx;
-
- w = 33;
- h = 14;
- wy = CENTER(YMAX, h);
- wx = CENTER(XMAX, w);
- opts = newwin(h, w, wy, wx);
- werase(opts);
- box(opts, 0, 0);
-
- /* fill 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);
-
- wrefresh(opts);
- wgetch(opts);
- werase(opts);
- wrefresh(opts);
- delwin(opts);
+ WINDOW *opts;
+ int w, h, wy, wx;
+
+ w = 33;
+ h = 14;
+ wy = CENTER(YMAX, h);
+ wx = CENTER(XMAX, w);
+ if ((opts = newwin(h, w, wy, wx)) == NULL)
+ errx(1, "newwin");
+ werase(opts);
+ wattron(opts, COLOR_PAIR(C_FG));
+ box(opts, 0, 0);
+
+ /* fill menu */
+ mvwprintw(opts, 1, 1, "q Quit");
+ mvwprintw(opts, 2, 1, "Up/k Move up");
+ mvwprintw(opts, 3, 1, "Down/j Move down");
+ mvwprintw(opts, 4, 1, "Left/h Move left");
+ mvwprintw(opts, 5, 1, "Right/l Move right");
+ mvwprintw(opts, 6, 1, "d Show derivative");
+ mvwprintw(opts, 7, 1, "f New function");
+ mvwprintw(opts, 8, 1, "r Restore zoom");
+ mvwprintw(opts, 9, 1, "+ Zoom in");
+ mvwprintw(opts, 10, 1, "- Zoom out");
+ mvwprintw(opts, 12, 1, "Press any key to quit the menu");
+
+ wrefresh(opts);
+ wattroff(opts, COLOR_PAIR(C_FG));
+ (void)wgetch(opts);
+ werase(opts);
+ wrefresh(opts);
+ delwin(opts);
+}
+
+static void
+sighandler(int sig)
+{
+ switch (sig) {
+ case SIGINT: /* FALLTHROUGH */
+ case SIGTERM:
+ cleanup();
+ exit(0);
+ case SIGWINCH:
+ /* TODO: lol... */
+ break;
+ }
+}
+
+static void
+cleanup(void)
+{
+ endwin();
+ evaluator_destroy(f);
+ free(p);
}
int
main(int argc, char *argv[])
{
- /* TODO: implement `die` */
- Plane *p;
- int key = 0;
-
- cursesinit();
- p = planeinit();
- exprvalidate(p);
-
- for (; key != 'q'; key = getch()) {
- switch (key) {
- case 'k': /* FALLTHROUGH */
- case KEY_UP:
- planeshift(p, 0.0f, SHIFT_STEP);
- break;
- case 'j': /* FALLTHROUGH */
- case KEY_DOWN:
- planeshift(p, 0.0f, -SHIFT_STEP);
- break;
- case 'h': /* FALLTHROUGH */
- case KEY_LEFT:
- planeshift(p, -SHIFT_STEP, 0.0f);
- break;
- case 'l': /* FALLTHROUGH */
- case KEY_RIGHT:
- planeshift(p, SHIFT_STEP, 0.0f);
- break;
- case '+':
- zoomhandle(p, ZOOM_IN_FACTOR);
- break;
- case '-':
- zoomhandle(p, ZOOM_OUT_FACTOR);
- break;
- case 'd':
- p->derivshow ^= 1;
- break;
- case 'r':
- zoomrestore(p);
- break;
- case 'f':
- exprvalidate(p);
- break;
- case 'm':
- menuopts();
- break;
- }
-
- erase();
- attron(COLOR_PAIR(1) | A_REVERSE | A_BOLD);
- mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f));
- if (p->derivshow)
- mvprintw(1, 0, "f'(x) = %s", evaluator_get_string(p->df));
- attroff(COLOR_PAIR(1) | A_REVERSE | A_BOLD);
-
- axesdraw(p);
- graphdraw(p);
- refresh();
- }
-
- endwin();
- free(p);
- evaluator_destroy(f);
-
- return EXIT_SUCCESS;
+ int key = 0;
+
+ cursesinit();
+ planeinit();
+ exprvalidate();
+
+ for (; key != 'q'; key = getch()) {
+ switch (key) {
+ case KEY_UP: /* FALLTHROUGH */
+ case 'k':
+ planeshift(0.0f, SHIFT_STEP);
+ break;
+ case KEY_DOWN: /* FALLTHROUGH */
+ case 'j':
+ planeshift(0.0f, -SHIFT_STEP);
+ break;
+ case KEY_LEFT: /* FALLTHROUGH */
+ case 'h':
+ planeshift(-SHIFT_STEP, 0.0f);
+ break;
+ case KEY_RIGHT: /* FALLTHROUGH */
+ case 'l':
+ planeshift(SHIFT_STEP, 0.0f);
+ break;
+ case '+':
+ zoomhandle(1.0f / 1.05f);
+ break;
+ case '-':
+ zoomhandle(1.05f);
+ break;
+ case 'd':
+ p->derivshow ^= 1;
+ break;
+ case 'r':
+ zoomrestore();
+ break;
+ case 'f':
+ exprvalidate();
+ break;
+ case 'c':
+ menuopts();
+ break;
+ }
+ erase();
+ attron(COLOR_PAIR(C_FG) | A_REVERSE | A_BOLD);
+ mvprintw(0, 0, "f(x) = %s", evaluator_get_string(f));
+ /* TODO: print controls opt */
+ if (p->derivshow)
+ mvprintw(1, 0, "f'(x) = %s", evaluator_get_string(p->df));
+ attroff(A_REVERSE | A_BOLD);
+ axesdraw();
+ attroff(COLOR_PAIR(C_FG));
+ graphdraw();
+ refresh();
+ }
+ cleanup();
+
+ return 0;
}