Logo Search packages:      
Sourcecode: sc version File versions  Download package

frame.c

/*    SC    A Spreadsheet Calculator
 *          Framed range manipulation
 *
 *          Chuck Martin <nrocinu@myrealbox.com>
 *          Originally created:  December, 2000
 *
 *          $Revision: 7.16 $
 */

#include <sys/types.h>
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <curses.h>
#include <unistd.h>
#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);
      }
}

Generated by  Doxygen 1.6.0   Back to index