diff options
Diffstat (limited to 'sheets.c')
-rw-r--r-- | sheets.c | 268 |
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); +} + + + + + + + + + + + + + + + + + |