/* SC A Spreadsheet Calculator * Framed range manipulation * * Chuck Martin * Originally created: December, 2000 * * $Revision: 7.16 $ */ #include #ifdef BSD42 #include #else #ifndef SYSIII #include #endif #endif #include #include #include "sc.h" static struct frange *frame_base; extern struct frange *lastfr; void add_frange(struct ent *or_left, struct ent *or_right, struct ent *ir_left, struct ent *ir_right, int toprows, int bottomrows, int leftcols, int rightcols) { struct frange *r; int minr, minc, maxr, maxc; minr = or_left->row < or_right->row ? or_left->row : or_right->row; minc = or_left->col < or_right->col ? or_left->col : or_right->col; maxr = or_left->row > or_right->row ? or_left->row : or_right->row; maxc = or_left->col > or_right->col ? or_left->col : or_right->col; or_left = lookat(minr, minc); or_right = lookat(maxr, maxc); if (ir_left) { minr = ir_left->row < ir_right->row ? ir_left->row : ir_right->row; minc = ir_left->col < ir_right->col ? ir_left->col : ir_right->col; maxr = ir_left->row > ir_right->row ? ir_left->row : ir_right->row; maxc = ir_left->col > ir_right->col ? ir_left->col : ir_right->col; ir_left = lookat(minr, minc); ir_right = lookat(maxr, maxc); if (ir_left->row < or_left->row || ir_left->col < or_left->col || ir_right->row > or_right->row || ir_right->col > or_right->col) { error("Invalid parameters"); return; } } if (frame_base) { /* * Has this frange already been created? If so, any negative * parameters mean "don't change this value." */ for (r = frame_base; r; r = r->r_next) { if ((r->or_left == or_left) && (r->or_right == or_right)) { if (ir_left) { r->ir_left = ir_left; r->ir_right = ir_right; } else { if (toprows < 0) toprows = r->ir_left->row - r->or_left->row; if (bottomrows < 0) bottomrows = r->or_right->row - r->ir_right->row; if (leftcols < 0) leftcols = r->ir_left->col - r->or_left->col; if (rightcols < 0) rightcols = r->or_right->col - r->ir_right->col; r->ir_left = lookat(r->or_left->row + toprows, r->or_left->col + leftcols); r->ir_right = lookat(r->or_right->row - bottomrows, r->or_right->col - rightcols); } /* If all frame sides are 0, delete the frange */ if (r->ir_left == r->or_left && r->ir_right == r->or_right) { if (r->r_next) r->r_next->r_prev = r->r_prev; if (r->r_prev) r->r_prev->r_next = r->r_next; else frame_base = r->r_next; scxfree((char *)r); if (lastfr == r) lastfr = NULL; } modflg++; FullUpdate++; return; } } /* * See if the specified range overlaps any previously created frange. */ for (r = frame_base; r; r = r->r_next) { if ( !(r->or_left->row > or_right->row || r->or_right->row < or_left->row || r->or_left->col > or_right->col || r->or_right->col < or_left->col)) { error("Framed ranges may not be nested or overlapping"); return; } } } if (ir_left != or_left || ir_right != or_right) { r = (struct frange *)scxmalloc((unsigned)sizeof(struct frange)); r->or_left = or_left; r->or_right = or_right; if (ir_left) { r->ir_left = ir_left; r->ir_right = ir_right; } else { if (toprows < 0) toprows = 0; if (bottomrows < 0) bottomrows = 0; if (leftcols < 0) leftcols = 0; if (rightcols < 0) rightcols = 0; r->ir_left = lookat(r->or_left->row + toprows, r->or_left->col + leftcols); r->ir_right = lookat(r->or_right->row - bottomrows, r->or_right->col - rightcols); } r->r_next = frame_base; r->r_prev = NULL; if (frame_base) frame_base->r_prev = r; frame_base = r; modflg++; FullUpdate++; } } void clean_frange() { register struct frange *fr; register struct frange *nextfr; fr = frame_base; frame_base = NULL; while (fr) { nextfr = fr->r_next; scxfree((char *)fr); fr = nextfr; } lastfr = NULL; } struct frange * find_frange(int row, int col) { struct frange *r; if (frame_base) for (r = frame_base; r; r = r->r_next) { if ((r->or_left->row <= row) && (r->or_left->col <= col) && (r->or_right->row >= row) && (r->or_right->col >= col)) return r; } return 0; } void sync_franges() { struct frange *fr; fr = frame_base; while (fr) { fr->or_left = lookat(fr->or_left->row, fr->or_left->col); fr->or_right = lookat(fr->or_right->row, fr->or_right->col); fr->ir_left = lookat(fr->ir_left->row, fr->ir_left->col); fr->ir_right = lookat(fr->ir_right->row, fr->ir_right->col); fr = fr->r_next; } } void write_franges(FILE *f) { register struct frange *r; register struct frange *nextr; for (r = nextr = frame_base; nextr; r = nextr, nextr = r->r_next) /**/ ; while (r) { fprintf(f, "frame %s", v_name(r->or_left->row, r->or_left->col)); fprintf(f, ":%s", v_name(r->or_right->row, r->or_right->col)); fprintf(f, " %s", v_name(r->ir_left->row, r->ir_left->col)); fprintf(f, ":%s\n", v_name(r->ir_right->row, r->ir_right->col)); r = r->r_prev; } } void list_frames(FILE *f) { register struct frange *r; register struct frange *nextr; if (!are_frames()) { fprintf(f, " No frames"); return; } (void) fprintf(f, " %-30s %s\n","Outer Range","Inner Range"); if (!brokenpipe) (void) fprintf(f, " %-30s %s\n","-----------","-----------"); for (r = nextr = frame_base; nextr; r = nextr, nextr = r->r_next) /* */ ; while (r) { fprintf(f, " %-30s", r_name(r->or_left->row, r->or_left->col, r->or_right->row, r->or_right->col)); fprintf(f, " %s\n", r_name(r->ir_left->row, r->ir_left->col, r->ir_right->row, r->ir_right->col)); if (brokenpipe) return; r = r->r_prev; } } int are_frames() { return (frame_base != 0); } void fix_frames(int row1, int col1, int row2, int col2, int delta1, int delta2) { int r1, r2, c1, c2; struct frange *fr, *cfr; cfr = find_frange(currow, curcol); if (frame_base) for (fr = frame_base; fr; fr = fr->r_next) { r1 = fr->or_left->row; c1 = fr->or_left->col; r2 = fr->or_right->row; c2 = fr->or_right->col; if (!(cfr && (c1 < cfr->or_left->col || c1 > cfr->or_right->col))) { if (r1 >= row1 && r1 <= row2) r1 = row2 - delta1; if (c1 >= col1 && c1 <= col2) c1 = col2 - delta1; } if (!(cfr && (c2 < cfr->or_left->col || c2 > cfr->or_right->col))) { if (r2 >= row1 && r2 <= row2) r2 = row1 + delta2; if (c2 >= col1 && c2 <= col2) c2 = col1 + delta2; } fr->or_left = lookat(r1, c1); fr->or_right = lookat(r2, c2); r1 = fr->ir_left->row; c1 = fr->ir_left->col; r2 = fr->ir_right->row; c2 = fr->ir_right->col; if (!(cfr && (c1 < cfr->or_left->col || c1 > cfr->or_right->col))) { if (r1 >= row1 && r1 <= row2) r1 = row2 - delta1; if (c1 >= col1 && c1 <= col2) c1 = col2 - delta1; } if (!(cfr && (c2 < cfr->or_left->col || c2 > cfr->or_right->col))) { if (r2 >= row1 && r2 <= row2) r2 = row1 + delta2; if (c2 >= col1 && c2 <= col2) c2 = col1 + delta2; } fr->ir_left = lookat(r1, c1); fr->ir_right = lookat(r2, c2); } }