diff options
Diffstat (limited to 'src.scim2/cmds.c')
-rwxr-xr-x | src.scim2/cmds.c | 1781 |
1 files changed, 1781 insertions, 0 deletions
diff --git a/src.scim2/cmds.c b/src.scim2/cmds.c new file mode 100755 index 0000000..c1c364f --- /dev/null +++ b/src.scim2/cmds.c @@ -0,0 +1,1781 @@ +#include <curses.h> +#include <stdlib.h> +#include <ctype.h> // for isdigit +#include <wchar.h> +#include <wctype.h> +#include "maps.h" +#include "yank.h" +#include "marks.h" +#include "cmds.h" +#include "buffer.h" +#include "screen.h" +#include "conf.h" // for conf parameters +#include "color.h" // for set_ucolor +#include "xmalloc.h" // for scxfree +#include "vmtbl.h" // for growtbl +#include "utils/string.h" // for add_char +#include "y.tab.h" // for yyparse +#ifdef UNDO +#include "undo.h" +#endif + +void syncref(register struct enode *e); +extern unsigned int shall_quit; +char insert_edit_submode; +struct ent * freeents = NULL; // keep deleted ents around before sync_refs +wchar_t interp_line[BUFFERSIZE]; + +// mark_ent_as_deleted (free_ents en sc original): +// This structure is used to keep ent structs around before they +// are actualy deleted (memory freed) to allow the sync_refs routine a chance to fix the +// variable references. +// it sets is_deleted flag of an ent. +void mark_ent_as_deleted(register struct ent *p) { + if (p == NULL) return; + //p->flags |= iscleared; + p->flags |= is_deleted; + + p->next = freeents; /* put this ent on the front of freeents */ + freeents = p; + + return; +} + +// flush_saved: iterates throw freeents (ents marked as deleted) +// calls clearent for freeing ents contents memory +// and free ent pointer. this function should always be called +// at exit. this is mandatory, just in case we want to UNDO any changes. +void flush_saved() { + register struct ent *p; + register struct ent *q; + + p = freeents; + while (p != NULL) { + (void) clearent(p); + q = p->next; + free(p); + p = q; + } + freeents = NULL; + return; +} + +// sync_refs and syncref are used to REMOVE references to +// deleted struct ents. +// Note that the deleted structure must still +// be hanging around before the call, but not referenced +// by an entry in tbl. +// IMPROVE: Shouldn't traverse the whole table. +void sync_refs() { + int i, j; + register struct ent *p; + // sync_ranges(); + for (i=0; i <= maxrow; i++) + for (j=0; j <= maxcol; j++) + if ( (p = *ATBL(tbl, i, j)) && p->expr ) { + syncref(p->expr); + //scinfo("%d %d %d", i, j, ++k); + } + return; +} + +void syncref(register struct enode *e) { + if ( e == (struct enode *) 0 ) { + //if ( e == NULL || e->op == ERR_ ) { + return; + } else if (e->op & REDUCE) { + e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col); + e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col); + } else { + switch (e->op) { + case 'v': + //if (e->e.v.vp->flags & iscleared) { + if (e->e.v.vp->flags & is_deleted) { + e->op = ERR_; + //scinfo("%d %d", e->e.v.vp->row, e->e.v.vp->col); + e->e.o.left = NULL; + e->e.o.right = NULL; + } else if (e->e.v.vp->flags & may_sync) + e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col); + break; + case 'k': + break; + case '$': + break; + default: + syncref(e->e.o.right); + syncref(e->e.o.left); + break; + } + } + return; +} + +// Delete a column +void deletecol() { + int r, c, i; + struct ent **pp; + + if (any_locked_cells(0, curcol, maxrow, curcol)) { + scinfo("Locked cells encountered. Nothing changed"); + return; + } + + // mark ent of column to erase with isdeleted flag + for (r = 0; r <= maxrow; r++) { + pp = ATBL(tbl, r, curcol); + if ( *pp != NULL ) { + mark_ent_as_deleted(*pp); + //clearent(*pp); + //free(*pp); + *pp = NULL; + } + } + + // Copy references from right column cells to left column (which gets removed) + for (r = 0; r <= maxrow; r++) { + for (c = curcol; c < maxcol; c++) { + pp = ATBL(tbl, r, c); + + // nota: pp[1] = ATBL(tbl, r, c+1); + if ( pp[1] != NULL ) pp[1]->col--; + pp[0] = pp[1]; + } + + // Free last column memory (Could also initialize 'ent' to zero with `cleanent`). + pp = ATBL(tbl, r, maxcol); + *pp = (struct ent *) 0; + // agregado el 06/12/2014 + } + + // Fix columns precision and width + for (i = curcol; i < maxcols - 2; i++) { + fwidth[i] = fwidth[i+1]; + precision[i] = precision[i+1]; + realfmt[i] = realfmt[i+1]; + col_hidden[i] = col_hidden[i+1]; + } + + for (; i < maxcols - 1; i++) { + fwidth[i] = DEFWIDTH; + precision[i] = DEFPREC; + realfmt[i] = DEFREFMT; + col_hidden[i] = FALSE; + } + + maxcol--; + sync_refs(); + //flush_saved(); // we have to flush_saved only at exit. + //this is because we have to keep ents in case we want to UNDO + modflg++; + return; +} + +// Copy a cell (struct ent). "special" indicates special treatment when +// merging two cells for the "pm" command, merging formats only for the +// "pf" command, or for adjusting cell references when transposing with +// the "pt" command. r1, c1, r2, and c2 define the range in which the dr +// and dc values should be used. +void copyent(register struct ent *n, register struct ent *p, int dr, int dc, + int r1, int c1, int r2, int c2, int special) { + if (!n || !p) { + scerror("internal error"); + return; + } + + //n->flags = may_sync; + + if (special != 'f') { + //if (special != 'm' || p->flags & is_valid) { + if (p->flags & is_valid) { + n->v = p->v; + n->flags |= p->flags & is_valid; + } + //if (special != 'm' || p->expr) { + if (special != 'v' && p->expr) { + n->expr = copye(p->expr, dr, dc, r1, c1, r2, c2, special == 't'); + if (p->flags & is_strexpr) + n->flags |= is_strexpr; + else + n->flags &= ~is_strexpr; + } + if (p->label) { + if (n->label) scxfree(n->label); + n->label = scxmalloc((unsigned) (strlen(p->label) + 1)); + (void) strcpy(n->label, p->label); + n->flags &= ~is_leftflush; + n->flags |= ((p->flags & is_label) | (p->flags & is_leftflush)); + //} else if (special != 'm') { + // n->label = NULL; + // n->flags &= ~(is_label | is_leftflush); + } + n->flags |= p->flags & is_locked; + } + //if (p->format) { + if (p->format && special != 'v') { + if (n->format) scxfree(n->format); + n->format = scxmalloc((unsigned) (strlen(p->format) + 1)); + (void) strcpy(n->format, p->format); + //} else if (special != 'm' && special != 'f') + } else if (special != 'v' && special != 'f') + n->format = NULL; + + if (special != 'v') + n->pad = p->pad; + + if (p->ucolor && special != 'v') { + n->ucolor = (struct ucolor *) malloc (sizeof(struct ucolor)); + n->ucolor->fg = p->ucolor->fg; + n->ucolor->bg = p->ucolor->bg; + n->ucolor->bold = p->ucolor->bold; + n->ucolor->dim = p->ucolor->dim; + n->ucolor->reverse = p->ucolor->reverse; + n->ucolor->standout = p->ucolor->standout; + n->ucolor->underline = p->ucolor->underline; + n->ucolor->blink = p->ucolor->blink; + } + + n->flags |= is_changed; + n->row = p->row; + n->col = p->col; + return; +} + +int etype(register struct enode *e) { + if (e == (struct enode *)0) + return NUM; + switch (e->op) { + case UPPER: case LOWER: case CAPITAL: + case O_SCONST: case '#': case DATE: case FMT: case STINDEX: + case EXT: case SVAL: case SUBSTR: + return (STR); + + case '?': + case IF: + return (etype(e->e.o.right->e.o.left)); + + case 'f': + return (etype(e->e.o.right)); + + case O_VAR: { + register struct ent *p; + p = e->e.v.vp; + if (p->expr) + return (p->flags & is_strexpr ? STR : NUM); + else if (p->label) + return (STR); + else + return (NUM); + } + + default: + return (NUM); + } + return -1; +} + +// ignorelock is used when sorting so that locked cells can still be sorted +void erase_area(int sr, int sc, int er, int ec, int ignorelock) { + int r, c; + struct ent **pp; + + if (sr > er) { + r = sr; sr = er; er = r; + } + + if (sc > ec) { + c = sc; sc = ec; ec = c; + } + + if (sr < 0) + sr = 0; + if (sc < 0) + sc = 0; + checkbounds(&er, &ec); + + // Do a lookat() for the upper left and lower right cells of the range + // being erased to make sure they are included in the delete buffer so + // that pulling cells always works correctly even if the cells at one + // or more edges of the range are all empty. + + (void) lookat(sr, sc); + (void) lookat(er, ec); + + for (r = sr; r <= er; r++) { + for (c = sc; c <= ec; c++) { + pp = ATBL(tbl, r, c); + if (*pp && (!((*pp)->flags & is_locked) || ignorelock)) { + mark_ent_as_deleted(*pp); + *pp = NULL; + } + } + } + return; +} + +struct enode * copye(register struct enode *e, int Rdelta, int Cdelta, int r1, int c1, int r2, int c2, int transpose) { + register struct enode *ret; + static struct enode *range = NULL; + + if (e == (struct enode *)0) { + ret = (struct enode *)0; + + } else if (e->op & REDUCE) { + int newrow, newcol; + //if (freeenodes) { + // ret = freeenodes; + // freeenodes = ret->e.o.left; + //} else + ret = (struct enode *) scxmalloc((unsigned) sizeof (struct enode)); + ret->op = e->op; + newrow = e->e.r.left.vf & FIX_ROW || + e->e.r.left.vp->row < r1 || e->e.r.left.vp->row > r2 || + e->e.r.left.vp->col < c1 || e->e.r.left.vp->col > c2 ? + e->e.r.left.vp->row : + transpose ? r1 + Rdelta + e->e.r.left.vp->col - c1 : + e->e.r.left.vp->row + Rdelta; + newcol = e->e.r.left.vf & FIX_COL || + e->e.r.left.vp->row < r1 || e->e.r.left.vp->row > r2 || + e->e.r.left.vp->col < c1 || e->e.r.left.vp->col > c2 ? + e->e.r.left.vp->col : + transpose ? c1 + Cdelta + e->e.r.left.vp->row - r1 : + e->e.r.left.vp->col + Cdelta; + ret->e.r.left.vp = lookat(newrow, newcol); + ret->e.r.left.vf = e->e.r.left.vf; + newrow = e->e.r.right.vf & FIX_ROW || + e->e.r.right.vp->row < r1 || e->e.r.right.vp->row > r2 || + e->e.r.right.vp->col < c1 || e->e.r.right.vp->col > c2 ? + e->e.r.right.vp->row : + transpose ? r1 + Rdelta + e->e.r.right.vp->col - c1 : + e->e.r.right.vp->row + Rdelta; + newcol = e->e.r.right.vf & FIX_COL || + e->e.r.right.vp->row < r1 || e->e.r.right.vp->row > r2 || + e->e.r.right.vp->col < c1 || e->e.r.right.vp->col > c2 ? + e->e.r.right.vp->col : + transpose ? c1 + Cdelta + e->e.r.right.vp->row - r1 : + e->e.r.right.vp->col + Cdelta; + ret->e.r.right.vp = lookat(newrow, newcol); + ret->e.r.right.vf = e->e.r.right.vf; + } else { + struct enode *temprange=0; + //if (freeenodes) { + // ret = freeenodes; + // freeenodes = ret->e.o.left; + //} else + ret = (struct enode *) scxmalloc((unsigned) sizeof (struct enode)); + ret->op = e->op; + switch (ret->op) { + case SUM: + case PROD: + case AVG: + case COUNT: + case STDDEV: + case MAX: + case MIN: + temprange = range; + range = e->e.o.left; + r1 = 0; + c1 = 0; + r2 = maxrow; + c2 = maxcol; + } + switch (ret->op) { + case 'v': + { + int newrow, newcol; + if (range && e->e.v.vp->row >= range->e.r.left.vp->row && + e->e.v.vp->row <= range->e.r.right.vp->row && + e->e.v.vp->col >= range->e.r.left.vp->col && + e->e.v.vp->col <= range->e.r.right.vp->col) { + newrow = range->e.r.left.vf & FIX_ROW ? e->e.v.vp->row : e->e.v.vp->row + Rdelta; + newcol = range->e.r.left.vf & FIX_COL ? e->e.v.vp->col : e->e.v.vp->col + Cdelta; + } else { + newrow = e->e.v.vf & FIX_ROW || + e->e.v.vp->row < r1 || e->e.v.vp->row > r2 || + e->e.v.vp->col < c1 || e->e.v.vp->col > c2 ? + e->e.v.vp->row : transpose ? r1 + Rdelta + e->e.v.vp->col - c1 : + e->e.v.vp->row + Rdelta; + newcol = e->e.v.vf & FIX_COL || + e->e.v.vp->row < r1 || e->e.v.vp->row > r2 || + e->e.v.vp->col < c1 || e->e.v.vp->col > c2 ? + e->e.v.vp->col : transpose ? c1 + Cdelta + e->e.v.vp->row - r1 : + e->e.v.vp->col + Cdelta; + } + ret->e.v.vp = lookat(newrow, newcol); + ret->e.v.vf = e->e.v.vf; + break; + } + case 'k': + ret->e.k = e->e.k; + break; + case 'f': + case 'F': + if ((range && ret->op == 'F') || (!range && ret->op == 'f')) + Rdelta = Cdelta = 0; + ret->e.o.left = copye(e->e.o.left, Rdelta, Cdelta, r1, c1, r2, c2, transpose); + ret->e.o.right = (struct enode *)0; + break; + case '$': + case EXT: + ret->e.s = scxmalloc((unsigned) strlen(e->e.s)+1); + (void) strcpy(ret->e.s, e->e.s); + if (e->op == '$') /* Drop through if ret->op is EXT */ + break; + default: + ret->e.o.left = copye(e->e.o.left, Rdelta, Cdelta, r1, c1, r2, c2, transpose); + ret->e.o.right = copye(e->e.o.right, Rdelta, Cdelta, r1, c1, r2, c2, transpose); + break; + } + switch (ret->op) { + case SUM: + case PROD: + case AVG: + case COUNT: + case STDDEV: + case MAX: + case MIN: + range = temprange; + } + } + return ret; +} + +/* Modified 9/17/90 THA to handle more formats */ +void doformat(int c1, int c2, int w, int p, int r) { + register int i; + int crows = 0; + int ccols = c2; + + if (c1 >= maxcols && !growtbl(GROWCOL, 0, c1)) c1 = maxcols-1 ; + if (c2 >= maxcols && !growtbl(GROWCOL, 0, c2)) c2 = maxcols-1 ; + + if (w == 0) { + scinfo("Width too small - setting to 1"); + w = 1; + } + + if (! atoi(get_conf_value("nocurses")) && w > COLS - rescol - 2) { + scinfo("Width too large - Maximum = %d", COLS - rescol - 2); + w = COLS - rescol - 2; + } + + if (p > w) { + scinfo("Precision too large"); + p = w; + } + + checkbounds(&crows, &ccols); + if (ccols < c2) { + scerror("Format statement failed to create implied column %d", c2); + return; + } + + for (i = c1; i <= c2; i++) + fwidth[i] = w, precision[i] = p, realfmt[i] = r; + + //rowsinrange = 1; + //colsinrange = fwidth[curcol]; + + modflg++; + return; + +} + +void formatcol(int c) { + int arg = 1; + int i; + + switch (c) { + case '<': + case 'h': + case OKEY_LEFT: + for (i = curcol; i < curcol + arg; i++) { + fwidth[i]--; + if (fwidth[i] < 1) + fwidth[i] = 1; + } + //rowsinrange = 1; + //colsinrange = fwidth[curcol]; + modflg++; + break; + case '>': + case 'l': + case OKEY_RIGHT: + for (i = curcol; i < curcol + arg; i++) { + fwidth[i]++; + if (fwidth[i] > COLS - rescol - 2) + fwidth[i] = COLS - rescol - 2; + } + //rowsinrange = 1; + //colsinrange = fwidth[curcol]; + modflg++; + break; + case '-': + case 'j': + case OKEY_DOWN: + for (i = curcol; i < curcol + arg; i++) { + precision[i]--; + if (precision[i] < 0) + precision[i] = 0; + } + modflg++; + break; + case '+': + case 'k': + case OKEY_UP: + for (i = curcol; i < curcol + arg; i++) + precision[i]++; + modflg++; + break; + } + scinfo("Current format is %d %d %d", fwidth[curcol], precision[curcol], realfmt[curcol]); + update(TRUE); + return; +} + +// Insert a single row. It will be inserted before currow +// if after is 0; after if it is 1. +void insert_row(int after) { + int r, c; + struct ent **tmprow, **pp; + int lim = maxrow - currow + 1; + + if (currow > maxrow) maxrow = currow; + maxrow++; + lim = maxrow - lim + after; + if (maxrow >= maxrows && !growtbl(GROWROW, maxrow, 0)) return; + + tmprow = tbl[maxrow]; + for (r = maxrow; r > lim; r--) { + row_hidden[r] = row_hidden[r-1]; + tbl[r] = tbl[r-1]; + for (c = 0, pp = ATBL(tbl, r, 0); c < maxcols; c++, pp++) + if (*pp) (*pp)->row = r; + } + tbl[r] = tmprow; // the last row is never used + + modflg++; + return; +} + +// Insert a single col. The col will be inserted +// BEFORE CURCOL if after is 0; +// AFTER CURCOL if it is 1. +void insert_col(int after) { + int r, c; + register struct ent **pp; + int lim = maxcol - curcol - after + 1; + + if (curcol + after > maxcol) + maxcol = curcol + after; + maxcol++; + + if ((maxcol >= maxcols) && !growtbl(GROWCOL, 0, maxcol)) + return; + + for (c = maxcol; c >= curcol + after + 1; c--) { + fwidth[c] = fwidth[c-1]; + precision[c] = precision[c-1]; + realfmt[c] = realfmt[c-1]; + col_hidden[c] = col_hidden[c-1]; + } + for (c = curcol + after; c - curcol - after < 1; c++) { + fwidth[c] = DEFWIDTH; + precision[c] = DEFPREC; + realfmt[c] = DEFREFMT; + col_hidden[c] = FALSE; + } + + for (r=0; r <= maxrow; r++) { + pp = ATBL(tbl, r, maxcol); + for (c = lim; --c >= 0; pp--) + if ((pp[0] = pp[-1])) pp[0]->col++; + + pp = ATBL(tbl, r, curcol + after); + for (c = curcol + after; c - curcol - after < 1; c++, pp++) + *pp = (struct ent *) 0; + } + + curcol += after; + modflg++; + return; +} + +// delete a row +void deleterow() { + register struct ent **pp; + int r, c; + struct ent **tmprow; + + + if (any_locked_cells(currow, 0, currow, maxcol)) { + scinfo("Locked cells encountered. Nothing changed"); + + } else { + //flush_saved(); + erase_area(currow, 0, currow, maxcol, 0); + if (currow > maxrow) return; + r = currow; + + // Rows are dealt with in numrow groups, each group of rows spaced numrow rows apart. + // save the first row of the group and empty it out + tmprow = tbl[r]; + pp = ATBL(tbl, r, 0); + for (c = maxcol + 1; --c >= 0; pp++) { + if (*pp != NULL) { + mark_ent_as_deleted(*pp); + *pp = NULL; + //clearent(*pp); + //free(*pp); + } + } + + // move the rows, put the deleted, but now empty, row at the end + for (; r + 1 < maxrows - 1; r++) { + row_hidden[r] = row_hidden[r+1]; + tbl[r] = tbl[r + 1]; + pp = ATBL(tbl, r, 0); + for (c = 0; c < maxcols; c++, pp++) + if (*pp) (*pp)->row = r; + } + tbl[r] = tmprow; + + maxrow--; + + sync_refs(); + //flush_saved(); // we have to flush only at exit. this is in case we want to UNDO + modflg++; + } + return; +} + +void ljustify(int sr, int sc, int er, int ec) { + struct ent *p; + int i, j; + + if (sr > er) { + i = sr; + sr = er; + er = i; + } + if (sc > ec) { + i = sc; + sc = ec; + ec = i; + } + for (i = sr; i <= er; i++) { + for (j = sc; j <= ec; j++) { + p = *ATBL(tbl, i, j); + if (p && p->label) { + p->flags &= ~is_label; + p->flags |= is_leftflush | is_changed; + changed++; + modflg++; + } + } + } + return; +} + +void rjustify(int sr, int sc, int er, int ec) { + struct ent *p; + int i, j; + + if (sr > er) { + i = sr; + sr = er; + er = i; + } + if (sc > ec) { + i = sc; + sc = ec; + ec = i; + } + for (i = sr; i <= er; i++) { + for (j = sc; j <= ec; j++) { + p = *ATBL(tbl, i, j); + if (p && p->label) { + p->flags &= ~(is_label | is_leftflush); + p->flags |= is_changed; + changed++; + modflg++; + } + } + } + return; +} + +void center(int sr, int sc, int er, int ec) { + struct ent *p; + int i, j; + + if (sr > er) { + i = sr; + sr = er; + er = i; + } + if (sc > ec) { + i = sc; + sc = ec; + ec = i; + } + for (i = sr; i <= er; i++) { + for (j = sc; j <= ec; j++) { + p = *ATBL(tbl, i, j); + if (p && p->label) { + p->flags &= ~is_leftflush; + p->flags |= is_label | is_changed; + changed++; + modflg++; + } + } + } + return; +} + +/* +void move_area(int dr, int dc, int sr, int sc, int er, int ec) { + struct ent *p; + struct ent **pp; + int deltar, deltac; + int r, c; + + if (sr > er) r = sr; + sr = er; + er = r; + if (sc > ec) + c = sc; + sc = ec; + ec = c; + if (sr < 0) sr = 0; + if (sc < 0) sc = 0; + checkbounds(&er, &ec); + + r = currow; + currow = sr; + c = curcol; + curcol = sc; + + // First we erase the source range, which puts the cells on the delete + // buffer stack. + erase_area(sr, sc, er, ec, 0); + + currow = r; + curcol = c; + deltar = dr - sr; + deltac = dc - sc; + + // Now we erase the destination range, which adds it to the delete buffer + // stack, but then we flush it off. We then move the original source + // range from the stack to the destination range, adjusting the addresses + // as we go, leaving the stack in its original state. + erase_area(dr, dc, er + deltar, ec + deltac, 0); + //flush_saved(); + for (p = delbuf[dbidx]; p; p = p->next) { + pp = ATBL(tbl, p->row + deltar, p->col + deltac); + *pp = p; + p->row += deltar; + p->col += deltac; + p->flags &= ~is_deleted; + } +} +*/ + +void chg_mode(char strcmd){ + switch (strcmd) { + case '=': + curmode = INSERT_MODE; + break; + case '<': + curmode = INSERT_MODE; + break; + case '>': + curmode = INSERT_MODE; + break; + case '\\': + curmode = INSERT_MODE; + break; + case 'E': + curmode = EDIT_MODE; + break; + case 'e': + curmode = EDIT_MODE; + break; + case ':': + curmode = COMMAND_MODE; + break; + case '.': + curmode = NORMAL_MODE; + break; + case 'v': + curmode = VISUAL_MODE; + break; + } + return; +} + +// del selected cells +// can be a single cell or a range +void del_selected_cells() { + + // delete range + if (is_range_selected() != -1) { + srange * r = get_selected_range(); + if (any_locked_cells(r->tlrow, r->tlcol, r->brrow, r->brcol)) { + scerror("Locked cells encountered. Nothing changed"); + return; + } + yank_area(r->tlrow, r->tlcol, r->brrow, r->brcol, 'a', 1); + + #ifdef UNDO + create_undo_action(); + copy_to_undostruct(r->tlrow, r->tlcol, r->brrow, r->brcol, 'd'); + #endif + + erase_area(r->tlrow, r->tlcol, r->brrow, r->brcol, 0); + modflg++; + sync_refs(); + //flush_saved(); NO DESCOMENTAR. VER ABAJO. + + #ifdef UNDO + copy_to_undostruct(r->tlrow, r->tlcol, r->brrow, r->brcol, 'a'); + end_undo_action(); + #endif + + // delete cell + } else { + if (any_locked_cells(currow, curcol, currow, curcol)) { + scerror("Locked cells encountered. Nothing changed"); + return; + } + yank_area(currow, curcol, currow, curcol, 'e', 1); + + #ifdef UNDO + create_undo_action(); + copy_to_undostruct(currow, curcol, currow, curcol, 'd'); + #endif + + erase_area(currow, curcol, currow, curcol, 0); + modflg++; + sync_refs(); + + #ifdef UNDO + copy_to_undostruct(currow, curcol, currow, curcol, 'a'); + end_undo_action(); + #endif + +/* + // UNDO feature + // Save deleted ent + struct ent * e_prev = (struct ent *) malloc( (unsigned) sizeof(struct ent) ); + cleanent(e_prev); + copyent(e_prev, lookat(currow, curcol), 0, 0, 0, 0, currow, curcol, 0); + // Save ents that depends on the deleted one: TODO + //struct ent * e_prev2 = (struct ent *) malloc( (unsigned) sizeof(struct ent) ); + //cleanent(e_prev2); + //copyent(e_prev2, lookat(currow+9, curcol+2), 0, 0, 0, 0, currow+9, curcol+2, 0); + //e_prev->next = e_prev2; + + // create undo struct: + struct undo u; + u.removed = e_prev; + u.added = NULL; // Eliminar esta linea, luego de implementar los TODO descriptos + + // delete the ent: + erase_area(currow, curcol, currow, curcol, 0); + modflg++; + // sync refs after the delete + sync_refs(); + + // Save current status of each ent that depends on the deleted one TODO + struct ent * e_now = (struct ent *) malloc( (unsigned) sizeof(struct ent) ); + cleanent(e_now); + (void) copyent(e_now, lookat(currow+9, curcol+2), 0, 0, 0, 0, currow+9, curcol+2, 0); + u.added = e_now; + + // Add undo struct to undolist: + add_to_undolist(&u); // <---------| +*/ + //flush_saved(); // No descomentar. Se debe hacer flush SOLO al salir + } + + return; +} + +// Change cell content sending inputline to interpreter +// REVISED +void insert_or_edit_cell() { + char ope[BUFFERSIZE] = ""; + switch (insert_edit_submode) { + case '=': + strcpy(ope, "let"); + break; + case '<': + strcpy(ope, "leftstring"); + break; + case '>': + strcpy(ope, "rightstring"); + break; + case '\\': + strcpy(ope, "label"); + break; + } + if (inputline[0] == '"') { + del_wchar(inputline, 0); //FIXME!!! + } else if (insert_edit_submode != '=' && inputline[0] != L'"') { + add_wchar(inputline, L'\"', 0); //FIXME!!! + add_wchar(inputline, L'\"', wcslen(inputline)); //FIXME!!! + } + + #ifdef UNDO + create_undo_action(); + copy_to_undostruct(currow, curcol, currow, curcol, 'd'); + #endif + + (void) swprintf(interp_line, BUFFERSIZE, L"%s %s = %ls", ope, v_name(currow, curcol), inputline); + + send_to_interp(interp_line); + + #ifdef UNDO + copy_to_undostruct(currow, curcol, currow, curcol, 'a'); + end_undo_action(); + #endif + + inputline[0] = L'\0'; + inputline_pos = 0; + chg_mode('.'); + clr_header(input_win, 0); + + char * opt = get_conf_value("newline_action"); + switch (opt[0]) { + case 'j': + currow = forw_row(1)->row; + break; + case 'l': + curcol = forw_col(1)->col; + break; + } + update(TRUE); + return; +} + +// REVISED - Send command to interpreter +void send_to_interp(wchar_t * oper) { + //debug(oper); + wcstombs(line, oper, BUFFERSIZE); + //scdebug("enviado a intérprete. line >>%s<<", line); + linelim = 0; + (void) yyparse(); + if (atoi(get_conf_value("autocalc")) && ! loading) EvalAll(); + return; +} + +/* return a pointer to a cell's [struct ent *], creating if needed */ +struct ent * lookat(int row, int col) { + register struct ent **pp; + + checkbounds(&row, &col); + pp = ATBL(tbl, row, col); + if ( *pp == NULL ) { + //*pp = (struct ent *) scxmalloc( (unsigned) sizeof(struct ent) ); + *pp = (struct ent *) malloc( (unsigned) sizeof(struct ent) ); + (*pp)->label = (char *) 0; + (*pp)->flags = may_sync; + (*pp)->expr = (struct enode *) 0; + (*pp)->v = (double) 0.0; + (*pp)->format = (char *) 0; + (*pp)->cellerror = CELLOK; + (*pp)->next = NULL; + (*pp)->ucolor = NULL; + (*pp)->pad = 0; + } + (*pp)->row = row; + (*pp)->col = col; + if (row > maxrow) maxrow = row; + if (col > maxcol) maxcol = col; + return (*pp); +} + +// cleanent: blank an ent +void cleanent(struct ent * p) { + p->label = (char *) 0; + p->row = 0; + p->col = 0; + p->flags = may_sync; + p->expr = (struct enode *) 0; + p->v = (double) 0.0; + p->format = (char *) 0; + p->cellerror = CELLOK; + p->next = NULL; + p->ucolor = NULL; + p->pad = 0; + return; +} + +// clearent: free memory of an ent and its contents +void clearent(struct ent *v) { + if (!v) return; + + label(v, "", -1); + v->v = (double)0; + + if (v->expr) efree(v->expr); + v->expr = NULL; + + if (v->format) scxfree(v->format); + v->format = NULL; + + if (v->ucolor) free(v->ucolor); + v->ucolor = NULL; + + v->flags = ( is_changed | iscleared ); + changed++; + modflg++; + + return; +} + +void scroll_left(int n) { + while (n--) { + if (! offscr_sc_cols ) { + break; + } + int a = 1; + int b = 0; + offscr_sc_cols--; + while (a != b && curcol) { + a = offscr_sc_cols; + calc_offscr_sc_cols(); + b = offscr_sc_cols; + if (a != b) { + curcol --; + offscr_sc_cols = a; + } + } + } + return; +} + +void scroll_right(int n) { + while (n--) { + // This while statement allow the cursor to shift to the right when the + // las visible column is reached in the screen + while (curcol < offscr_sc_cols + 1) { + curcol++; + } + offscr_sc_cols++; + } + return; +} + +void scroll_down(int n) { + while (n--) { + if (currow == offscr_sc_rows) { + forw_row(1); + unselect_ranges(); + } + offscr_sc_rows++; + } + return; +} + +void scroll_up(int n) { + while (n--) { + if (offscr_sc_rows) + offscr_sc_rows--; + else + break; + if (currow == offscr_sc_rows + LINES - RESROW - 1) { + back_row(1); + unselect_ranges(); + } + } + return; +} + +struct ent * left_limit() { + int c = 0; + while ( col_hidden[c] && c < curcol ) c++; + return lookat(currow, c); +} + +struct ent * right_limit() { + register struct ent *p; + int c = maxcols - 1; + while ( (! VALID_CELL(p, currow, c) && c > 0) || col_hidden[c]) c--; + return lookat(currow, c); +} + +struct ent * goto_top() { + int r = 0; + while ( row_hidden[r] && r < currow ) r++; + return lookat(r, curcol); +} + +struct ent * goto_bottom() { + register struct ent *p; + int r = maxrows - 1; + while ( (! VALID_CELL(p, r, curcol) && r > 0) || row_hidden[r]) r--; + return lookat(r, curcol); +} + +// moves curcol back one displayed column +struct ent * back_col(int arg) { + int c = curcol; + while (--arg >= 0) { + if (c) + c--; + else { + scinfo ("At column A"); + break; + } + while( col_hidden[c] && c ) + c--; + } + //rowsinrange = 1; + //colsinrange = fwidth[curcol]; + return lookat(currow, c); +} + +/* moves curcol forward one displayed column */ +struct ent * forw_col(int arg) { + int c = curcol; + while (--arg >= 0) { + if (c < maxcols - 1) + c++; |