sheets.c (5283B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdbool.h> 4 #include <ctype.h> 5 #include <string.h> 6 #include <math.h> 7 8 #include "expr.h" 9 #include "sheets.h" 10 11 #define ACCURACY 2 12 13 #define arg1(s, n) if (strcmp(argv[i], s) == 0) {\ 14 i++; \ 15 if (i >= argc) {\ 16 fprintf(stderr, "expected value after %s option\n", s);\ 17 exit(1);\ 18 } 19 20 #define arg2(s, n) else if (strcmp(argv[i], s) == 0) {\ 21 i++; \ 22 if (i >= argc) {\ 23 fprintf(stderr, "expected value after %s option\n", s);\ 24 exit(1);\ 25 } 26 27 28 void clearstdin() { 29 while (getc(stdin) != '\n') continue; 30 } 31 32 void freeSheet(sheet *s) { 33 for (int y = 0; y < s->height; y++) { 34 for (int x = 0; x < s->width; x++) 35 freeExpr(s->cells[y][x]); 36 free(s->cells[y]); 37 } 38 free(s->cells); 39 free(s); 40 } 41 42 sheet *makeSheet(int x, int y) { 43 sheet *s = calloc(1, sizeof(sheet)); 44 s->width = x; 45 s->height = y; 46 47 s->cells = calloc(1, sizeof(expr **) * y); 48 for (int i = 0; i < y; i++) { 49 s->cells[i] = calloc(1, sizeof(expr *) * x); 50 for (int j = 0; j < x; j++) 51 s->cells[i][j] = makeNumber(0); 52 } 53 return s; 54 } 55 56 void export(sheet *s, FILE *f) { 57 fprintf(f, "%d %d\n", s->width, s->height); 58 for (int y = 0; y < s->height; y++) { 59 fprintf(f, "\n|"); 60 for (int x = 0; x < s->width; x++) 61 fprintf(f, "%s|", s->cells[y][x]->expr); 62 } 63 fprintf(f, "\n"); 64 } 65 66 sheet *import(FILE *f) { 67 int width, height; 68 sheet *s; 69 70 fscanf(f, "%d %d\n\n|", &width, &height); 71 s = makeSheet(width, height); 72 73 for (int y = 0; y < s->height; y++) { 74 for (int x = 0; x < s->width; x++) { 75 in = Pin; 76 char expr[256] = {0}; 77 fscanf(f, "%[^|]s", expr); 78 fscanf(f, "|"); 79 80 memcpy(in, expr, 256); 81 s->cells[y][x] = parseExpr(); 82 s->cells[y][x]->expr = strdup(expr); 83 } 84 fscanf(f, "\n|"); 85 } 86 return s; 87 } 88 89 void inputln(char *s, int size, FILE *f) { 90 fflush(stdout); 91 fgets(s, size, f); 92 *strchr(s, '\n') = 0; 93 } 94 95 void printSheetContents(sheet *s, int X, int Y) { 96 int longest[s->width]; 97 memset(longest, 0, sizeof(int) * s->width); 98 99 for (int y = 0; y < s->height; y++) 100 for (int x = 0; x < s->width; x++) 101 if (strlen(s->cells[y][x]->expr) > longest[x]) 102 longest[x] = strlen(s->cells[y][x]->expr); 103 104 for (int y = 0; y < s->height; y++) { 105 printf("\n|"); 106 for (int x = 0; x < s->width; x++) 107 if (strcmp(s->cells[y][x]->expr, "0") == 0) 108 printf(" %*s |", longest[x], " "); 109 else if (X == x && Y == y) 110 printf("\e[1;34m %*s \e[0m|", longest[x], s->cells[y][x]->expr); 111 else 112 printf(" %*s |", longest[x], s->cells[y][x]->expr); 113 } 114 printf("\n"); 115 } 116 117 void shell(char *prompt, FILE *fin) { 118 sheet *s; 119 if (!fin) { 120 invalid: 121 int x = -1; 122 int y = -1; 123 printf("What size sheet do you want 'x,y': "); 124 scanf("%d,%d", &x, &y); 125 clearstdin(); 126 if (x == -1 || y == -1) { 127 printf("Please input a valid expression!\n"); 128 goto invalid; 129 } 130 s = makeSheet(x, y); 131 } else s = import(fin); 132 133 134 struct expr *e; 135 int x = 0; 136 int y = 0; 137 FILE *f; 138 char fname[256]; 139 140 141 for (;;) { 142 in = Pin; 143 printf("(%d, %d) %s", x, y, prompt); 144 memset(in, 0, 256); 145 inputln(in, 256, stdin); 146 147 switch (in[0]) { 148 case 'u': y--; break; 149 case 'd': y++; break; 150 case 'l': x--; break; 151 case 'r': x++; break; 152 case 'q': 153 freeSheet(s); 154 printf("Exiting\n"); 155 exit(0); 156 case 'p': printf("(%d,%d) %s\n", x, y,s->cells[y][x]->expr); break; 157 case 'P': 158 printSheetContents(s, x, y); 159 break; 160 case 'e': 161 for (int i = 0; i < s->height; i++) { 162 printf("\n|"); 163 for (int j = 0; j < s->width; j++) 164 if (j == x && i == y) 165 printf("\e[1;34m %.*f \e[0m|", ACCURACY, evalExpr(s->cells[i][j], s)); 166 else 167 printf(" %.*f |", ACCURACY, evalExpr(s->cells[i][j], s)); 168 } 169 printf("\n"); 170 break; 171 case 'i': 172 in = Pin; 173 memset(in, 0, 256); 174 inputln(in, 256, stdin); 175 176 freeExpr(s->cells[y][x]); 177 178 s->cells[y][x] = parseExpr(); 179 s->cells[y][x]->expr = strdup(Pin); 180 181 break; 182 case 's': 183 printf("file to save to: "); 184 inputln(fname, 256, stdin); 185 f = fopen(fname, "w"); 186 export(s, f); 187 fclose(f); 188 break; 189 case 'o': 190 printf("file to open: "); 191 inputln(fname, 256, stdin); 192 f = fopen(fname, "r"); 193 if (!f) 194 fprintf(stderr, "couldn't open file!\n"); 195 else { 196 freeSheet(s); 197 s = import(f); 198 fclose(f); 199 } 200 break; 201 default: 202 fprintf(stderr, "unknown cmd '%s'!\n", in); 203 break; 204 205 } 206 207 if (x > s->width) { 208 fprintf(stderr, "error: x:%d is out of range (0 - %d)\n", x, s->width); 209 x = s->width; 210 } 211 if (x < 0) { 212 fprintf(stderr, "error: x:%d is out of range (0 - %d)\n", x, s->width); 213 x = 0; 214 } 215 if (y > s->height) { 216 fprintf(stderr, "error: y:%d is out of range (0 - %d)\n", y, s->height); 217 y = s->height; 218 } 219 if (y < 0) { 220 fprintf(stderr, "error: y:%d is out of range (0 - %d)\n", y, s->height); 221 y = 0; 222 } 223 } 224 } 225 226 227 int main(int argc, char **argv) { 228 setbuf(stdout, NULL); 229 230 in = malloc(256); 231 Pin = in; 232 233 char *prompt = "> "; 234 FILE *input = NULL; 235 236 for (int i = 1; i < argc; i++) { 237 arg1("-p", true) 238 prompt = argv[i]; 239 } 240 else { 241 input = fopen(argv[i], "r"); 242 if (!input) { 243 fprintf(stderr, "couldn't open file\n"); 244 exit(0); 245 } 246 } 247 } 248 249 shell(prompt, input); 250 free(in); 251 } 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268