summaryrefslogtreecommitdiff
path: root/sheets.c
diff options
context:
space:
mode:
Diffstat (limited to 'sheets.c')
-rw-r--r--sheets.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/sheets.c b/sheets.c
new file mode 100644
index 0000000..c9cba5d
--- /dev/null
+++ b/sheets.c
@@ -0,0 +1,268 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+
+#include "expr.h"
+#include "sheets.h"
+
+#define ACCURACY 2
+
+#define arg1(s, n) if (strcmp(argv[i], s) == 0) {\
+ i++; \
+ if (i >= argc) {\
+ fprintf(stderr, "expected value after %s option\n", s);\
+ exit(1);\
+ }
+
+#define arg2(s, n) else if (strcmp(argv[i], s) == 0) {\
+ i++; \
+ if (i >= argc) {\
+ fprintf(stderr, "expected value after %s option\n", s);\
+ exit(1);\
+ }
+
+
+void clearstdin() {
+ while (getc(stdin) != '\n') continue;
+}
+
+void freeSheet(sheet *s) {
+ for (int y = 0; y < s->height; y++) {
+ for (int x = 0; x < s->width; x++)
+ freeExpr(s->cells[y][x]);
+ free(s->cells[y]);
+ }
+ free(s->cells);
+ free(s);
+}
+
+sheet *makeSheet(int x, int y) {
+ sheet *s = calloc(1, sizeof(sheet));
+ s->width = x;
+ s->height = y;
+
+ s->cells = calloc(1, sizeof(expr **) * y);
+ for (int i = 0; i < y; i++) {
+ s->cells[i] = calloc(1, sizeof(expr *) * x);
+ for (int j = 0; j < x; j++)
+ s->cells[i][j] = makeNumber(0);
+ }
+ return s;
+}
+
+void export(sheet *s, FILE *f) {
+ fprintf(f, "%d %d\n", s->width, s->height);
+ for (int y = 0; y < s->height; y++) {
+ fprintf(f, "\n|");
+ for (int x = 0; x < s->width; x++)
+ fprintf(f, "%s|", s->cells[y][x]->expr);
+ }
+ fprintf(f, "\n");
+}
+
+sheet *import(FILE *f) {
+ int width, height;
+ sheet *s;
+
+ fscanf(f, "%d %d\n\n|", &width, &height);
+ s = makeSheet(width, height);
+
+ for (int y = 0; y < s->height; y++) {
+ for (int x = 0; x < s->width; x++) {
+ in = Pin;
+ char expr[256] = {0};
+ fscanf(f, "%[^|]s", expr);
+ fscanf(f, "|");
+
+ memcpy(in, expr, 256);
+ s->cells[y][x] = parseExpr();
+ s->cells[y][x]->expr = strdup(expr);
+ }
+ fscanf(f, "\n|");
+ }
+ return s;
+}
+
+void inputln(char *s, int size, FILE *f) {
+ fflush(stdout);
+ fgets(s, size, f);
+ *strchr(s, '\n') = 0;
+}
+
+void printSheetContents(sheet *s, int X, int Y) {
+ int longest[s->width];
+ memset(longest, 0, sizeof(int) * s->width);
+
+ for (int y = 0; y < s->height; y++)
+ for (int x = 0; x < s->width; x++)
+ if (strlen(s->cells[y][x]->expr) > longest[x])
+ longest[x] = strlen(s->cells[y][x]->expr);
+
+ for (int y = 0; y < s->height; y++) {
+ printf("\n|");
+ for (int x = 0; x < s->width; x++)
+ if (strcmp(s->cells[y][x]->expr, "0") == 0)
+ printf(" %*s |", longest[x], " ");
+ else if (X == x && Y == y)
+ printf("\e[1;34m %*s \e[0m|", longest[x], s->cells[y][x]->expr);
+ else
+ printf(" %*s |", longest[x], s->cells[y][x]->expr);
+ }
+ printf("\n");
+}
+
+void shell(char *prompt, FILE *fin) {
+ sheet *s;
+ if (!fin) {
+invalid:
+ int x = -1;
+ int y = -1;
+ printf("What size sheet do you want 'x,y': ");
+ scanf("%d,%d", &x, &y);
+ clearstdin();
+ if (x == -1 || y == -1) {
+ printf("Please input a valid expression!\n");
+ goto invalid;
+ }
+ s = makeSheet(x, y);
+ } else s = import(fin);
+
+
+ struct expr *e;
+ int x = 0;
+ int y = 0;
+ FILE *f;
+ char fname[256];
+
+
+ for (;;) {
+ in = Pin;
+ printf("(%d, %d) %s", x, y, prompt);
+ memset(in, 0, 256);
+ inputln(in, 256, stdin);
+
+ switch (in[0]) {
+ case 'u': y--; break;
+ case 'd': y++; break;
+ case 'l': x--; break;
+ case 'r': x++; break;
+ case 'q':
+ freeSheet(s);
+ printf("Exiting\n");
+ exit(0);
+ case 'p': printf("(%d,%d) %s\n", x, y,s->cells[y][x]->expr); break;
+ case 'P':
+ printSheetContents(s, x, y);
+ break;
+ case 'e':
+ for (int i = 0; i < s->height; i++) {
+ printf("\n|");
+ for (int j = 0; j < s->width; j++)
+ if (j == x && i == y)
+ printf("\e[1;34m %.*f \e[0m|", ACCURACY, evalExpr(s->cells[i][j], s));
+ else
+ printf(" %.*f |", ACCURACY, evalExpr(s->cells[i][j], s));
+ }
+ printf("\n");
+ break;
+ case 'i':
+ in = Pin;
+ memset(in, 0, 256);
+ inputln(in, 256, stdin);
+
+ freeExpr(s->cells[y][x]);
+
+ s->cells[y][x] = parseExpr();
+ s->cells[y][x]->expr = strdup(Pin);
+
+ break;
+ case 's':
+ printf("file to save to: ");
+ inputln(fname, 256, stdin);
+ f = fopen(fname, "w");
+ export(s, f);
+ fclose(f);
+ break;
+ case 'o':
+ printf("file to open: ");
+ inputln(fname, 256, stdin);
+ f = fopen(fname, "r");
+ if (!f)
+ fprintf(stderr, "couldn't open file!\n");
+ else {
+ freeSheet(s);
+ s = import(f);
+ fclose(f);
+ }
+ break;
+ default:
+ fprintf(stderr, "unknown cmd '%s'!\n", in);
+ break;
+
+ }
+
+ if (x > s->width) {
+ fprintf(stderr, "error: x:%d is out of range (0 - %d)\n", x, s->width);
+ x = s->width;
+ }
+ if (x < 0) {
+ fprintf(stderr, "error: x:%d is out of range (0 - %d)\n", x, s->width);
+ x = 0;
+ }
+ if (y > s->height) {
+ fprintf(stderr, "error: y:%d is out of range (0 - %d)\n", y, s->height);
+ y = s->height;
+ }
+ if (y < 0) {
+ fprintf(stderr, "error: y:%d is out of range (0 - %d)\n", y, s->height);
+ y = 0;
+ }
+ }
+}
+
+
+int main(int argc, char **argv) {
+ setbuf(stdout, NULL);
+
+ in = malloc(256);
+ Pin = in;
+
+ char *prompt = "> ";
+ FILE *input = NULL;
+
+ for (int i = 1; i < argc; i++) {
+ arg1("-p", true)
+ prompt = argv[i];
+ }
+ else {
+ input = fopen(argv[i], "r");
+ if (!input) {
+ fprintf(stderr, "couldn't open file\n");
+ exit(0);
+ }
+ }
+ }
+
+ shell(prompt, input);
+ free(in);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+