teapot-spreadsheet/src/common/main.c

1877 lines
50 KiB
C
Raw Normal View History

/* #includes */ /*{{{C}}}*//*{{{*/
#ifndef NO_POSIX_SOURCE
#undef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 2
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <locale.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
extern char *optarg;
extern int optind,opterr,optopt;
int getopt(int argc, char * const *argv, const char *optstring);
extern char *strdup(const char* s);
#include <string.h>
#include <unistd.h>
#include "default.h"
#include "display.h"
#include "eval.h"
#include "htmlio.h"
#include "latex.h"
#include "context.h"
#include "main.h"
#include "misc.h"
#include "sc.h"
#include "scanner.h"
#include "utf8.h"
#include "parser.h"
#include "sheet.h"
#include "wk1.h"
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
#include "xdr.h"
/*}}}*/
/* variables */ /*{{{*/
char helpfile[PATH_MAX];
bool batch = false;
unsigned int batchln=0;
int def_precision = DEF_PRECISION;
StringFormat quote = DIRECT_STRING;
bool header = true;
bool always_redraw = false;
int debug_level = 0;
static bool usexdr = false;
/*}}}*/
void moveto(Sheet *sheet, int x, int y, int z)
{
int need_redraw = 0;
int xdir = x > sheet->cur[X]?1:-1;
if (x >= 0) sheet->cur[X] = x;
if (y >= 0) sheet->cur[Y] = y;
if (z >= 0) need_redraw++, sheet->cur[Z] = z;
while (sheet->cur[X] > 0 && SHADOWED(sheet, sheet->cur)) sheet->cur[X] += xdir;
if (getmarkstate(sheet) == MARKING) LOCATION_GETS(sheet->mark2, sheet->cur);
if (sheet->cur[X] <= sheet->offx && sheet->offx) need_redraw++, sheet->offx = (sheet->cur[X]?sheet->cur[X]-1:0);
if (sheet->cur[Y] <= sheet->offy && sheet->offy) need_redraw++, sheet->offy = (sheet->cur[Y]?sheet->cur[Y]-1:0);
if (sheet->cur[X] >= sheet->offx+sheet->maxx) need_redraw++, sheet->offx = sheet->cur[X]-sheet->maxx+2;
if (sheet->cur[Y] >= sheet->offy+sheet->maxy) need_redraw++, sheet->offy = sheet->cur[Y]-sheet->maxy+2;
if (need_redraw) redraw_sheet(sheet);
else if (x != sheet->cur[X] || y != sheet->cur[Y] || z != sheet->cur[Z]) redraw_cell(sheet, sheet->cur);
}
void movetoloc(Sheet *sheet, const Location dest) {
moveto(sheet, dest[X], dest[Y], dest[Z]);
}
void relmoveto(Sheet *sheet, int x, int y, int z)
{
moveto(sheet, sheet->cur[X]+x, sheet->cur[Y]+y, (z?sheet->cur[Z]+z:-1));
}
/* line_numedit -- number line editor function */ /*{{{*/
static int line_numedit(int *n, const char *prompt)
{
assert(prompt != NULL);
char buf[20];
Token *t = NULLTOKEN;
sprintf(buf, "%d", *n);
char *s = buf+strlen(buf);
do
{
free(t);
size_t x = s - buf;
size_t offx = 0;
int c = line_edit((Sheet*)0, buf, sizeof(buf), prompt, &x, &offx);
if (c < 0) return c;
s = buf;
t = scan_integer(&s);
} while (*s != '\0');
if (t == NULLTOKEN) *n = -1;
else { *n = t->u.integer; free(t); }
return 0;
}
/*}}}*/
/* line_lidedit -- label identifier line editor function */ /*{{{*/
static int line_idedit(char *ident, size_t size, const char *prompt, size_t *x, size_t *offx)
{
Token *t = NULLTOKEN;
char *s = ident+strlen(ident);
do
{
free(t);
*x = s - ident;
int c = line_edit((Sheet*)0, ident, size, prompt, x, offx);
if (c < 0) return c;
s = ident;
t = scan_ident(&s);
} while (*s != '\0' || t == NULLTOKEN || t->type != LIDENT);
free(t);
return 0;
}
/*}}}*/
/* doanyway -- ask if action should be done despite unsaved changes */ /*{{{*/
int doanyway(Sheet *sheet, const char *msg)
{
int result;
if (sheet->changed) {
result = line_ok(msg,0);
if (result < 0) return 0;
return result;
}
return 1;
}
/*}}}*/
/* do_edit -- set or modify cell contents */ /*{{{*/
static int do_edit(Sheet *cursheet, Key c, char *expr, TokVariety tv)
{
/* variables */ /*{{{*/
char buf[1024];
const char *prompt;
char *s;
size_t x,offx;
Location scur;
Token **t;
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
Token newcont;
Cell *cell;
/*}}}*/
cell = curcell(cursheet);
if (locked(cell)) line_msg(_("Edit cell:"),_("Cell is locked"));
else
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
newcont.type = EMPTY;
LOCATION_GETS(scur, cursheet->cur);
if (expr)
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
s = expr;
t = scan(&s);
prompt = _("Cell contents:");
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
if (tv == ITER_CONT) prompt = _("Clocked cell contents");
if (*s != '\0')
if (t == EMPTY_TVEC)
line_msg(prompt, "XXX invalid expression");
else
{
newcont = eval_safe(t, LITERAL);
if (newcont.type = EEK)
line_msg(prompt, "XXX unparseable expression");
}
tvecfree(t);
}
else
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
Token cntt;
offx=0;
if (c == K_NONE)
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
cntt = gettok(cell, tv);
printtok(buf, sizeof(buf), 0, QUOTE_STRING, FLT_COMPACT, 0,
TRUNCATED_ERROR, &cntt);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
s = buf+strlen(buf);
}
else if (c == K_BACKSPACE)
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
cntt = gettok(cell, tv);
printtok(buf, sizeof(buf), 0, QUOTE_STRING, FLT_COMPACT, 0,
TRUNCATED_ERROR, &cntt);
if (strlen(buf)) *mbspos(buf+strlen(buf),-1)='\0';
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
s = buf+strlen(buf);
}
else if (c == K_DC)
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
cntt = gettok(cell, tv);
printtok(buf, sizeof(buf), 0, QUOTE_STRING, FLT_COMPACT, 0,
TRUNCATED_ERROR, &cntt);
memmove(buf,mbspos(buf,1),strlen(mbspos(buf,1))+1);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
s = buf;
}
else if (isalpha(c))
{
buf[0] = '"';
buf[1] = c;
buf[2] = 0;
s=buf+2;
}
else
{
if (c < 256) buf[0]=c;
else buf[0] = 0;
buf[1]='\0';
s=buf+1;
}
do
{
int r;
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
tfree(&newcont);
newcont.type = EEK;
newcont.u.err = (char *)0;
x = mbslen(buf)-mbslen(s);
prompt = _("Cell contents:");
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
if (tv == ITER_CONT) prompt = _("Clocked cell contents:");
if ((r = line_edit(cursheet, buf, sizeof(buf), prompt, &x, &offx)) < 0)
return r;
s = buf;
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
if (buf[0] == '"' && buf[strlen(buf)-1] != '"'
&& strlen(buf)+1 < sizeof(buf))
{
buf[strlen(buf)+1] = 0;
buf[strlen(buf)] = '"';
}
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
t = scan(&s);
if (t != EMPTY_TVEC) {
newcont = eval_safe(t, LITERAL);
}
tvecfree(t);
} while (*s != '\0' && newcont.type == EEK);
}
movetoloc(cursheet, scur);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
puttok(cursheet, cursheet->cur, newcont, tv);
forceupdate(cursheet);
}
return 0;
}
/*}}}*/
/* do_label -- modify cell label */ /*{{{*/
static int do_label(Sheet *sheet)
{
/* variables */ /*{{{*/
char buf[1024],oldlabel[1024];
size_t edx,offx,ok;
Token t;
Location w;
int tried;
int c;
/*}}}*/
assert(sheet != (Sheet*)0);
do_mark(sheet, GET_MARK_ALL);
if (SAME_LOC(sheet->mark1,sheet->mark2) &&
locked(CELL_AT(sheet, sheet->mark1)))
{
line_msg(_("Cell label:"),_("Cell is locked"));
}
else
{
ok=edx=offx=0;
(void)strcpy(buf, getlabel(curcell(sheet)));
(void)strcpy(oldlabel, buf);
tried = 0;
do
{
if (tried) {
line_msg(_("Cell label:"), _("Label already in use"));
}
if ((c=line_idedit(buf,sizeof(buf),_("Cell label:"),&edx,&offx))<0) return c;
tried = 1;
if (buf[0]=='\0') ok=1;
else
{
ok=((t=findlabel(sheet,buf)).type==EEK ||
(t.type == LOCATION && SAME_LOC(t.u.location, sheet->cur)));
tfree(&t);
}
} while (!ok);
setlabel(sheet, sheet->cur, buf,1);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
if (buf[0] != '\0' && oldlabel[0] != '\0')
for (ALL_LOCS_IN_REGION(sheet,w))
relabel(sheet, w, oldlabel, buf);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
cachelabels(sheet);
forceupdate(sheet);
}
return -1;
}
/*}}}*/
/* do_columnwidth -- set the column width */ /*{{{*/
static int do_columnwidth(Sheet *cursheet)
{
do_mark(cursheet, GET_MARK_CUR);
int n = columnwidth(cursheet, cursheet->mark1[X], cursheet->mark1[Z]);
do {
int c = line_numedit(&n, _("Column width:"));
if (c < 0) return c;
} while (n <= 0);
/*}}}*/
for (int x = cursheet->mark1[X]; x <= cursheet->mark2[X]; ++x)
for (int z = cursheet->mark1[Z]; z <= cursheet->mark2[Z]; ++z)
setwidth(cursheet,x,z,n);
return -1;
}
/*}}}*/
/* do_attribute -- set cell attributes */ /*{{{*/
static void do_attribute(Sheet *cursheet, Key action)
{
Location w;
Adjust adj = LEFT;
FloatFormat ff = FLT_DECIMAL;
do_mark(cursheet, GET_MARK_CUR);
bool onecell = SAME_LOC(cursheet->mark1, cursheet->mark2);
Cell *fcell = safe_cell_at(cursheet, cursheet->mark1);
bool changed = false;
if (action != ADJUST_LOCK && onecell && locked(fcell))
{
line_msg(_("Cell attribute:"),_("Cell is locked"));
return;
}
switch ((int)action)
{
case ADJUST_CENTER: ++adj; /* drop through */
case ADJUST_RIGHT: ++adj; /* drop through */
case ADJUST_LEFT:
{
const char *templ = _("Change adjustment of block to %s?");
char *prompt = malloc(strlen(templ) + MAX_ADJUST_NAME_LENGTH + 1);
sprintf(prompt, templ, Adjust_Name[adj]);
if (!onecell && line_ok(prompt, 0) <= 0) break;
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = setadjust(cursheet, w, adj) || changed;
break;
}
/* set float format */ /*{{{*/
case ADJUST_HEXACT: ++ff; /* drop through */
case ADJUST_COMPACT: ++ff; /* drop through */
case ADJUST_SCIENTIFIC: ++ff; /* drop through */
case ADJUST_DECIMAL:
{
const char* templ = _("Change float format of block to %s?");
char *prompt = malloc(strlen(templ) + MAX_FLOATFORM_NAME_LENGTH +1);
sprintf(prompt, templ, FloatFormat_Name[ff]);
if (!onecell && line_ok(prompt, 0) <= 0) break;
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = setfltformat(cursheet, w, ff) || changed;
break;
}
/*}}}*/
/* 5 -- set precision */ /*{{{*/
case ADJUST_PRECISION:
{
size_t ex,offx;
int n;
offx=0;
ex=0;
n = getprecision(fcell);
const char* prompt = _("Precision for block:");
if (onecell) prompt = _("Precision for cell:");
int c = line_numedit(&n, prompt);
if (c < 0) return;
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = setprecision(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* 6 -- shadow */ /*{{{*/
case ADJUST_SHADOW:
{
int n;
Location r;
LOCATION_GETS(r, cursheet->mark1); ++r[X];
if (onecell) n = !SHADOWED(cursheet, r);
else n = line_binary(_("Set block to:"),
_("uU)nshadowed"), _("sS)hadowed"),
!SHADOWED(cursheet, r));
if (cursheet->mark1[X] == 0 && n == 1) {
line_msg(_("Shadow cell:"),_("You can not shadow cells in column 0"));
break;
}
if (n >= 0) {
for (ALL_LOCS_IN_REGION(cursheet,w))
{
Location r;
if (n == 0)
{
LOCATION_GETS(r, w);
if (!SHADOWED(cursheet, r)) ++(r[X]);
for (; SHADOWED(cursheet, r); ++(r[X]))
changed = shadow(cursheet, r, false) || changed;
}
else if (w[X]>0) changed = shadow(cursheet, w, true) || changed;
}
}
if (n>0) do_mark(cursheet, UNMARKED);
break;
}
/*}}}*/
/* 7 -- transparent */ /*{{{*/
case ADJUST_TRANSPARENT:
{
int n;
if (onecell) n = !transparent(fcell);
else n = line_binary(_("Set block to:"),
_("pP)rotected"), _("tT)ransparent:"),
!transparent(fcell));
if (n >= 0)
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = maketrans(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* 8 -- bold */ /*{{{*/
case ADJUST_BOLD:
{
int n;
if (onecell) n = !isbold(fcell);
else n = line_binary(_("Set block weight to:"),
_("rR)egular"), _("bB)old"), !isbold(fcell));
if (n >= 0)
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = bold(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* 9 -- underline */ /*{{{*/
case ADJUST_UNDERLINE:
{
int n;
if (onecell) n = !underlined(fcell);
else n = line_binary(_("Set block to:"), _("nN)ot underline"),
_("uU)nderline"), !underlined(fcell));
if (n >= 0)
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = underline(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* 1 -- edit label and goto end */ /*{{{*/
case ADJUST_LABEL:
{
do_label(cursheet);
return;
}
/*}}}*/
/* 2 -- lock */ /*{{{*/
case ADJUST_LOCK:
{
int n;
if (onecell) n = !locked(fcell);
else n = line_binary(_("Set block to:"), _("uU)nlocked"), _("lL)ocked"),
!locked(fcell));
if (n >= 0)
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = lockcell(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* 3 -- ignore */ /*{{{*/
case ADJUST_IGNORE:
{
int n;
if (onecell) n = !ignored(fcell);
else n = line_binary(_("Set block to:"), _("cC)omputed"), _("iI)gnored"),
!ignored(fcell));
if (n >= 0)
for (ALL_LOCS_IN_REGION(cursheet,w))
changed = igncell(cursheet, w, n) || changed;
break;
}
/*}}}*/
/* default -- should not happen */ /*{{{*/
default: assert(0);
/*}}}*/
}
if (changed) {
if (onecell) redraw_cell(cursheet, cursheet->mark1);
else redraw_sheet(cursheet);
forceupdate(cursheet);
}
}
/*}}}*/
/* do_saveport -- save sheet as portable ASCII file */ /*{{{*/
static int do_saveport(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
unsigned int count;
if (!name) name = cursheet->name;
if ((msg = saveport(cursheet, name, &count))) {
line_msg(_("Save sheet to ASCII file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save sheet to ASCII file:"),buf);
return -1;
}
/*}}}*/
/* do_savetbl -- save sheet as tbl file */ /*{{{*/
static int do_savetbl(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
int standalone=0;
unsigned int count;
do_mark(cursheet, GET_MARK_ALL);
if (!name) {
name = cursheet->name;
if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
}
if ((msg = savetbl(cursheet, name, !standalone,
cursheet->mark1, cursheet->mark2, &count))) {
line_msg(_("Save in tbl format to file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in tbl format to file:"), buf);
return -1;
}
/*}}}*/
/* do_savelatex -- save sheet as LaTeX file */ /*{{{*/
static int do_savelatex(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
int standalone=0;
unsigned int count;
do_mark(cursheet, GET_MARK_ALL);
if (!name) {
name = cursheet->name;
if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
}
if ((msg = savelatex(cursheet, name, !standalone,
cursheet->mark1, cursheet->mark2, &count))) {
line_msg(_("Save in LaTeX format to file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in LaTeX format to file:"), buf);
return -1;
}
/*}}}*/
/* do_savecontext -- save sheet as ConTeXt file */ /*{{{*/
static int do_savecontext(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
int standalone=0;
int x1,y1,z1,x2,y2,z2;
unsigned int count;
do_mark(cursheet, GET_MARK_ALL);
if (!name)
{
name = cursheet->name;
if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
}
if ((msg = savecontext(cursheet, name, !standalone,
cursheet->mark1, cursheet->mark2, &count)))
{
line_msg(_("Save in ConTeXt format to file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in ConTeXt format to file:"), buf);
return -1;
}
/*}}}*/
/* do_savehtml -- save sheet as HTML file */ /*{{{*/
static int do_savehtml(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
int standalone=0;
int x1,y1,z1,x2,y2,z2;
unsigned int count;
do_mark(cursheet, GET_MARK_ALL);
if (!name) {
name = cursheet->name;
if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
}
if ((msg = savehtml(cursheet, name, !standalone,
cursheet->mark1, cursheet->mark2, &count))) {
line_msg(_("Save in HTML format to file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in HTML format to file:"), buf);
return -1;
}
/*}}}*/
/* do_savetext -- save sheet as formatted text file */ /*{{{*/
static int do_savetext(Sheet *cursheet, const char *name)
{
char buf[PATH_MAX];
const char *msg;
int x1,y1,z1,x2,y2,z2;
unsigned int count;
do_mark(cursheet, GET_MARK_ALL);
if (!name) name = cursheet->name;
if ((msg = savetext(cursheet, name,
cursheet->mark1, cursheet->mark2, &count))) {
line_msg(_("Save in plain text format to file:"),msg);
return -2;
}
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in plain text format to file:"), buf);
return -1;
}
/*}}}*/
/* do_savecsv -- save sheet as CSV file */ /*{{{*/
static int do_savecsv(Sheet *cursheet, const char *name)
{
do_mark(cursheet, GET_MARK_ALL);
if (!name) name = cursheet->name;
const char *menu[] =
{ _("cC)omma (,)"), _("sS)emicolon (;)"), _("tT)ab (\\t)"), NULL };
const char seps[4] = ",;\t";
int sep = line_menu(_("Choose separator:"), menu, 0);
if (sep < 0) return sep;
unsigned int count;
const char *msg;
if ((msg = savecsv(cursheet, name, seps[sep],
cursheet->mark1, cursheet->mark2, &count)))
{
line_msg(_("Save in CSV format to file:"), msg);
return -2;
}
char buf[1024];
snprintf(buf, sizeof(buf), _("%u cells written"), count);
if (!batch) line_msg(_("Save in CSV format to file:"), buf);
return -1;
}
/*}}}*/
/* do_loadxdr -- load sheet from XDR file */ /*{{{*/
static int do_loadxdr(Sheet *cursheet)
{
const char *msg;
if ((msg=loadxdr(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from XDR file:"),msg);
return -1;
}
/*}}}*/
/* do_loadport -- load sheet from portable ASCII file */ /*{{{*/
static int do_loadport(Sheet *cursheet)
{
const char *msg;
/*}}}*/
if ((msg=loadport(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from ASCII file:"),msg);
return -1;
}
/*}}}*/
/* do_loadsc -- load sheet from SC file */ /*{{{*/
static int do_loadsc(Sheet *cursheet)
{
const char *msg;
if ((msg=loadsc(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from SC file:"),msg);
return -1;
}
/*}}}*/
/* do_loadwk1 -- load sheet from WK1 file */ /*{{{*/
static int do_loadwk1(Sheet *cursheet)
{
const char *msg;
if ((msg=loadwk1(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from WK1 file:"),msg);
return -1;
}
/*}}}*/
/* do_loadcsv -- load/merge sheet from CSV file */ /*{{{*/
static int do_loadcsv(Sheet *cursheet)
{
const char *msg;
if ((msg=loadcsv(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from CSV file:"),msg);
return -1;
}
/*}}}*/
/* do_mark -- set mark */ /*{{{*/
void do_mark(Sheet *cursheet, MarkState ms)
{
MarkState ps;
Dimensions dim;
ps = getmarkstate(cursheet);
if (ms == MARK_CYCLE)
{
if (ps == UNMARKED) ms = MARKING;
else ms = ps + 1;
}
if (ps == ms) return;
switch (ms)
{
case MARKING:
{
LOCATION_GETS(cursheet->mark1, cursheet->cur);
LOCATION_GETS(cursheet->mark2, cursheet->cur);
break;
}
case UNMARKED:
break;
case MARKED:
case GET_MARK_CUR:
case GET_MARK_ALL:
{
switch (ps)
{
case MARKED: {
ms = MARKED;
break;
}
case MARKING:
{
for (dim = X; dim < HYPER; ++dim)
posorder(&(cursheet->mark1[dim]), &(cursheet->mark2[dim]));
ms = MARKED;
break;
}
case UNMARKED:
{
if (ms == GET_MARK_CUR)
{
LOCATION_GETS(cursheet->mark1, cursheet->cur);
LOCATION_GETS(cursheet->mark2, cursheet->cur);
ms = UNMARKED;
}
else if (ms == GET_MARK_ALL)
{
OLOCATION(cursheet->mark1);
cursheet->mark2[X] = cursheet->dimx - 1;
cursheet->mark2[Y] = cursheet->dimy - 1;
cursheet->mark2[Z] = cursheet->dimz - 1;
ms = UNMARKED;
}
else assert(ms == MARKED);
break;
}
default: assert(0);
}
break;
}
default: assert(0);
}
cursheet->marking = ms;
}
/*}}}*/
static int do_name(Sheet *cursheet);
/* do_save -- save sheet */ /*{{{*/
static int do_save(Sheet *cursheet)
{
const char *ext = cursheet->name;
if (ext==(char*)0) return do_name(cursheet);
ext += strlen(ext)-1;
if (!strcmp(ext-3, ".tbl")) return do_savetbl(cursheet, NULL);
if (!strcmp(ext-5, ".latex")) return do_savelatex(cursheet, NULL);
if (!strcmp(ext-4, ".html")) return do_savehtml(cursheet, NULL);
if (!strcmp(ext-3, ".csv")) return do_savecsv(cursheet, NULL);
if (!strcmp(ext-3, ".txt")) return do_savetext(cursheet, NULL);
if (!strcmp(ext-3, ".tex")) return do_savecontext(cursheet, NULL);
return do_saveport(cursheet, NULL);
}
/*}}}*/
/* do_name -- (re)name sheet */ /*{{{*/
static int do_name(Sheet *cursheet)
{
const char *name;
name = line_file(cursheet->name, _("Teapot ASCII \t*.tpa\ntbl \t*.tbl\nLaTeX \t*.latex\nHTML \t*.html\nCSV \t*.csv\nFormatted ASCII \t*.txt\nConTeXt \t*.tex"), _("New file name:"), 1);
if (!name) return -1;
if (cursheet->name!=(char*)0) free(cursheet->name);
cursheet->name=strdup(name);
return do_save(cursheet);
}
/*}}}*/
/* do_load -- load sheet */ /*{{{*/
static int do_load(Sheet *cursheet)
{
const char *name, *ext;
if (doanyway(cursheet, _("Sheet modified, load new file anyway?")) != 1) return -1;
name = line_file(cursheet->name,
_("Teapot ASCII \t*.tpa\n"
"CSV \t*.csv\n"
"Legacy binary Teapot \t*.tp\n"
"SC Spreadsheet Calculator \t*.sc\n"
"Lotus 1-2-3 \t*.wk1\n"
), _("Load sheet:"), 0);
if (!name) return -1;
if (cursheet->name!=(char*)0) free(cursheet->name);
cursheet->name=strdup(name);
ext = name+strlen(name)-1;
if (!strcmp(ext-2, ".tp")) return do_loadxdr(cursheet);
if (!strcmp(ext-2, ".sc")) return do_loadsc(cursheet);
if (!strcmp(ext-3, ".wk1")) return do_loadwk1(cursheet);
if (!strcmp(ext-3, ".csv")) return do_loadcsv(cursheet);
return do_loadport(cursheet);
}
/*}}}*/
/* do_clear -- clear block */ /*{{{*/
static int do_clear(Sheet *sheet)
{
/* variables */ /*{{{*/
Location w;
bool onecell;
int c;
/*}}}*/
do_mark(sheet, GET_MARK_CUR);
onecell = SAME_LOC(sheet->mark1, sheet->mark2);
if (onecell && locked(CELL_AT(sheet, sheet->mark1)))
line_msg(_("Clear cell:"),_("Cell is locked"));
else
{
if (!onecell)
{
if ((c=line_ok(_("Clear block:"),0))<0) return c;
else if (c!=1) return -1;
}
for (ALL_LOCS_IN_REGION(sheet, w)) freecellofsheet(sheet, w);
cachelabels(sheet);
forceupdate(sheet);
}
return -1;
}
/*}}}*/
/* do_insert -- insert block */ /*{{{*/
static int do_insert(Sheet *sheet)
{
int reply;
/* ask for direction of insertion */ /*{{{*/
{
const char* menu[] =
{ _("cC)olumn"), _("rR)ow"), _("dD)epth"), NULL };
reply = line_menu(_("Insert:"), menu, 0);
if (reply<0) return reply;
}
/*}}}*/
do_mark(sheet, GET_MARK_CUR);
Location beg, end;
LOCATION_GETS(beg, sheet->mark1);
LOCATION_GETS(end, sheet->mark2);
bool onecell = SAME_LOC(beg, end);
if (onecell)
/* ask if current cell or whole dimension should be used */ /*{{{*/
{
const char *menu[3];
/* show menu */ /*{{{*/
switch (reply)
{
case 0: menu[0] = _("wW)hole column"); break;
case 1: menu[0] = _("wW)hole line"); break;
case 2: menu[0] = _("wW)hole sheet"); break;
default: assert(0);
}
menu[1] = _("sS)ingle cell");
menu[2] = NULL;
int r = line_menu(_("Insert:"), menu, 0);
/*}}}*/
switch (r)
{
/* 0 -- use whole dimension */ /*{{{*/
case 0:
{
switch (reply)
{
/* 0 -- use whole column */ /*{{{*/
case 0:
{
beg[Y] = 0; end[Y] = sheet->dimy;
break;
}
/*}}}*/
/* 1 -- use whole line */ /*{{{*/
case 1:
{
beg[X] = 0; end[X] = sheet->dimx;
break;
}
/*}}}*/
/* 2 -- use whole layer */ /*{{{*/
case 2:
{
beg[X] = 0; end[X] = sheet->dimx;
beg[Y] = 0; end[Y] = sheet->dimy;
break;
}
/*}}}*/
/* default -- should not happen */ /*{{{*/
default: assert(0);
/*}}}*/
}
break;
}
/*}}}*/
/* 1 -- use current cell */ /*{{{*/
case 1: break;
/*}}}*/
/* -2,-1 -- go up or abort */ /*{{{*/
case -2:
case -1: return r;
/*}}}*/
/* default -- should not happen */ /*{{{*/
default: assert(0);
/*}}}*/
}
}
/*}}}*/
/*}}}*/
switch (reply)
{
/* 0 -- columns */ /*{{{*/
case 0: insertcube(sheet, beg, end, IN_X); break;
/*}}}*/
/* 1 -- rows */ /*{{{*/
case 1: insertcube(sheet, beg, end, IN_Y); break;
/*}}}*/
/* 2 -- depth */ /*{{{*/
case 2: insertcube(sheet, beg, end, IN_Z); break;
/*}}}*/
}
return 0;
}
/*}}}*/
/* do_delete -- delete block */ /*{{{*/
static int do_delete(Sheet *sheet)
{
int reply;
firstmenu:
/* ask for direction of deletion */ /*{{{*/
{
const char* menu[] =
{ _("cC)olumn"), _("rR)ow"), _("dD)epth"), NULL };
reply = line_menu(_("Delete:"), menu, 0);
if (reply < 0) return reply;
}
/*}}}*/
do_mark(sheet, GET_MARK_CUR);
Location beg, end;
LOCATION_GETS(beg, sheet->mark1);
LOCATION_GETS(end, sheet->mark2);
bool onecell = SAME_LOC(beg, end);
if (onecell)
/* ask if range is the current cell or whole dimension should be used */ /*{{{*/
{
const char *menu[3];
/* show menu */ /*{{{*/
switch (reply)
{
case 0: menu[0] = _("wW)hole column"); break;
case 1: menu[0] = _("wW)hole line"); break;
case 2: menu[0] = _("wW)hole sheet"); break;
default: assert(0);
}
menu[1] = _("sS)ingle cell");
menu[2] = NULL;
int r = line_menu(_("Delete:"), menu, 0);
/*}}}*/
switch (r)
{
/* 0 -- use whole dimension */ /*{{{*/
case 0:
{
switch (reply)
{
/* 0 -- use whole column */ /*{{{*/
case 0:
{
beg[Y] = 0; end[Y] = sheet->dimy;
break;
}
/*}}}*/
/* 1 -- use whole line */ /*{{{*/
case 1:
{
beg[X] = 0; end[X] = sheet->dimx;
break;
}
/*}}}*/
/* 2 -- use whole layer */ /*{{{*/
case 2:
{
beg[X] = 0; end[X] = sheet->dimx;
beg[Y] = 0; end[Y] = sheet->dimy;
break;
}
/*}}}*/
/* default -- should not happen */ /*{{{*/
default: assert(0);
/*}}}*/
}
break;
}
/*}}}*/
/* 1 -- use current cell */ /*{{{*/
case 1: break;
/*}}}*/
/* -1 -- abort */ /*{{{*/
case -1: return -1;
/*}}}*/
/* -2 -- go back to previous menu */ /*{{{*/
case -2: goto firstmenu;
/*}}}*/
/* default -- should not happen */ /*{{{*/
default: assert(0);
/*}}}*/
}
}
/*}}}*/
/*}}}*/
switch(reply)
{
/* 0 -- columns */ /*{{{*/
case 0: deletecube(sheet, beg, end, IN_X); break;
/*}}}*/
/* 1 -- rows */ /*{{{*/
case 1: deletecube(sheet, beg, end, IN_Y); break;
/*}}}*/
/* 2 -- depth */ /*{{{*/
case 2: deletecube(sheet, beg, end, IN_Z); break;
/*}}}*/
}
return -1;
}
/*}}}*/
/* do_move -- copy or move a block */ /*{{{*/
static int do_move(Sheet *sheet, int copy, int force)
{
int c;
c=-1;
if (getmarkstate(sheet) == UNMARKED) line_msg(copy ? _("Copy block:") : _("Move block:"),_("No block marked"));
else if (force || (c=line_ok(copy ? _("Copy block:") : _("Move block:"),0))==1)
{
do_mark(sheet, MARKED);
moveblock(sheet, sheet->mark1, sheet->mark2, sheet->cur, copy);
if (!copy) sheet->marking = UNMARKED;
}
if (c<0) return c; else return -1;
}
/*}}}*/
/* do_fill -- fill a block */ /*{{{*/
static int do_fill(Sheet *sheet)
{
/* variables */ /*{{{*/
int cols,rows,layers;
int x,y,z;
Location wid, go;
int c;
/*}}}*/
if (getmarkstate(sheet) == UNMARKED) line_msg(_("Fill block:"),_("No block marked"));
else
{
do_mark(sheet, MARKED);
cols=rows=layers=1;
firstmenu:
do {
int c = line_numedit(&cols, _("Number of column-wise repetitions:"));
if (c < 0) return c;
} while (cols <= 0);
secondmenu:
do
{
int c = line_numedit(&rows, _("Number of row-wise repetitions:"));
if (c == -1) return -1;
else if (c == -2) goto firstmenu;
} while (rows <= 0);
do
{
int c = line_numedit(&layers, _("Number of depth-wise repetitions:"));
if (c == -1) return -1;
else if (c == -2) goto secondmenu;
} while (layers <= 0);
LOCATION_GETS(wid, sheet->mark2);
LOCATION_SUB(wid, sheet->mark1);
wid[X]++; wid[Y]++; wid[Z]++;
LOCATION_GETS(go, sheet->cur);
for (z=0; z<layers; ++z, go[Z] += wid[Z])
for (y=0, go[Y] = sheet->cur[Y]; y<rows; ++y, go[Y] += wid[Y])
for (x=0, go[X] = sheet->cur[X]; x<cols; ++x, go[X] += wid[X])
moveblock(sheet, sheet->mark1, sheet->mark2, go, 1);
}
return -1;
}
/*}}}*/
/* fill the entire marked region using the current cell */
void fillwith(Sheet *she)
{
do_mark(she, GET_MARK_ALL);
Cell *src = curcell(she);
Location dest;
bool scan_labels = (src != NULLCELL && getlabel(src) != (const char*)0);
/* the following is safe since we have handled copying a cell to itself */
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
for (ALL_LOCS_IN_REGION(she, dest))
copycelltosheet(src, she, dest, ALTER_LABEL);
if (scan_labels) cachelabels(she);
forceupdate(she);
}
/* do_sort -- sort block */ /*{{{*/
static int do_sort(Sheet *sheet)
{
do_mark(sheet, GET_MARK_ALL);
/* build menus */ /*{{{*/
const char* menu1[] =
{ _("cC)olumn"), _("rR)ow"), _("dD)epth"), NULL };
const char* menu2[] =
{ _("sS)ort region"), _("aA)dd key"), NULL };
const char* menu3[] =
{ _("aA)scending"), _("dD)escending"), NULL };
/*}}}*/
int last = -1;
Direction in_dir = (Direction)-2; /* cause run time error */
int dir;
/* ask for sort direction */ /*{{{*/
zero:
dir = line_menu(_("Sort block:"), menu1, 0);
switch (dir)
{
case 0: in_dir = IN_X; break;
case 1: in_dir = IN_Y; break;
case 2: in_dir = IN_Z; break;
case -2: case -1: return dir;
default: assert(0);
}
last=0;
/*}}}*/
Sortkey sk[MAX_SORTKEYS];
unsigned int key = 0;
bool doit = false;
do
{
/* ask for positions */ /*{{{*/
one: if (in_dir==IN_X) sk[key].x=0; else /* ask for x position */ /*{{{*/
{
sk[key].x = 0;
do
{
int c = line_numedit(&(sk[key].x), _("X position of key vector:"));
if (c == -1) return -1;
else if (c == -2) switch (last)
{
case -1: return -2;
case 0: goto zero;
case 2: goto two;
case 3: goto three;
case 5: goto five;
}
} while (sk[key].x < 0);
last = 1;
}
/*}}}*/
two: if (in_dir==IN_Y) sk[key].y=0; else /* ask for y position */ /*{{{*/
{
sk[key].y = 0;
do
{
int c = line_numedit(&(sk[key].y), _("Y position of key vector:"));
if (c == -1) return -1;
else if (c == -2) switch (last)
{
case -1: return -2;
case 0: goto zero;
case 1: goto one;
case 3: goto three;
case 5: goto five;
default: assert(0);
}
} while (sk[key].y < 0);
last = 2;
}
/*}}}*/
three: if (in_dir==IN_Z) sk[key].z=0; else /* ask for z position */ /*{{{*/
{
sk[key].z = 0;
do
{
int c = line_numedit(&(sk[key].z), _("Z position of key vector:"));
if (c == -1) return -1;
else if (c == -2) switch (last)
{
case -1: return -2;
case 0: goto zero;
case 1: goto one;
case 2: goto two;
case 5: goto five;
default: assert(0);
}
} while (sk[key].z < 0);
last = 3;
}
/*}}}*/
/*}}}*/
/* ask for sort key */ /*{{{*/
four: sk[key].sortkey=0;
int ckey = line_menu(_("Sort block:"), menu3, 0);
switch (ckey)
{
case 0: sk[key].sortkey |= ASCENDING; break;
case 1: sk[key].sortkey &= ~ASCENDING; break;
case -1: return -1;
case -2: switch (last)
{
case -1: return -2;
case 1: goto one;
case 2: goto two;
case 3: goto three;
default: assert(0);
}
default: assert(0);
}
last = 4;
/*}}}*/
++key;
five:
if (key == MAX_SORTKEYS) /* ask for sort comfirmation */ /*{{{*/
{
int c = line_ok(_("Sort block:"),0);
if (c == -1) return -1;
else if (c == -2) goto four;
else if (c == 0) doit = true;
}
/*}}}*/
else /* ask for sort or adding another key */ /*{{{*/
switch (line_menu(_("Sort block:"), menu2, 0))
{
case 0: doit = true; break;
case 1: doit = false; break;
case -1: return -1;
case -2: goto four;
default: assert(0);
}
/*}}}*/
last = 5;
} while (!doit);
const char *msg =
sortblock(sheet, sheet->mark1, sheet->mark2, in_dir, sk, key);
if (msg != NULL) line_msg(_("Sort block:"), msg);
return 0;
}
/*}}}*/
/* do_batchsort -- sort block in a batch*/ /*{{{*/
static void do_batchsort(Sheet *sheet, Direction dir, char* arg)
{
Sortkey sk[MAX_SORTKEYS];
int x1,y1,z1,x2,y2,z2;
unsigned int key = 0;
char* next;
while( *arg != '\0' )
{
while (isspace((int)*arg)) arg++;
sk[key].x=sk[key].y=sk[key].z=sk[key].sortkey=0;
switch (*arg)
{
case 'a': sk[key].sortkey|=ASCENDING; arg++; break;
case 'd': sk[key].sortkey&=~ASCENDING; arg++; break;
}
if ( *arg != '\0' && dir != IN_X ) { sk[key].x=strtol(arg, &next, 10); arg = next; }
if ( *arg != '\0' && dir != IN_Y ) { sk[key].y=strtol(arg, &next, 10); arg = next; }
if ( *arg != '\0' && dir != IN_Z ) { sk[key].z=strtol(arg, &next, 10); arg = next; }
key++;
}
do_mark(sheet, GET_MARK_ALL);
sortblock(sheet, sheet->mark1, sheet->mark2, dir, sk, key);
}
/*}}}*/
/* do_mirror -- mirror block */ /*{{{*/
static int do_mirror(Sheet *sheet)
{
/* variables */ /*{{{*/
int x1,y1,z1,x2,y2,z2,reply;
/*}}}*/
do_mark(sheet, GET_MARK_ALL);
/* ask for direction of mirroring */ /*{{{*/
{
const char *menu[] =
{ _("lL)eft-right"), _("uU)pside-down"), _("fF)ront-back"), NULL};
reply = line_menu(_("Mirror block:"), menu, 0);
if (reply < 0) return reply;
}
/*}}}*/
switch (reply)
{
/* 0 -- left-right */ /*{{{*/
case 0: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_X); break;
/*}}}*/
/* 1 -- upside-down */ /*{{{*/
case 1: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_Y); break;
/*}}}*/
/* 2 -- front-back */ /*{{{*/
case 2: mirrorblock(sheet, sheet->mark1, sheet->mark2, IN_Z); break;
/*}}}*/
default: assert(0);
}
return 0;
}
/*}}}*/
/* do_goto -- go to a specific cell */ /*{{{*/
static int do_goto(Sheet *sheet, const char *expr)
{
assert(sheet != (Sheet*)0);
size_t x = 0;
size_t offx = 0;
char buf[1024];
buf[0]='\0';
if (expr) strcpy(buf,expr);
else {
int c = line_edit(sheet, buf, sizeof(buf), _("Go to location:"), &x, &offx);
if (c < 0) return c;
}
char *s = buf;
Token **t = scan(&s);
if (t != EMPTY_TVEC)
{
Token value;
LOCATION_GETS(upd_l, sheet->cur);
upd_sheet = sheet;
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
value = eval_safe(t, FULL);
tvecfree(t);
if (value.type == LOCATION && IN_OCTANT(value.u.location))
movetoloc(sheet, value.u.location);
else
line_msg(_("Go to location:"), _("Not a valid location"));
tfree(&value);
}
return -1;
}
/*}}}*/
/* do_sheetcmd -- process one key press */ /*{{{*/
int do_sheetcmd(Sheet *cursheet, Key c, int moveonly)
{
switch ((int)c)
{
case K_GOTO: do_goto(cursheet, (const char *)0); break;
case K_COLWIDTH: do_columnwidth(cursheet); break;
case BLOCK_CLEAR: do_clear(cursheet); redraw_sheet(cursheet); break;
case BLOCK_INSERT: do_insert(cursheet); redraw_sheet(cursheet); break;
case BLOCK_DELETE: do_delete(cursheet); redraw_sheet(cursheet); break;
case BLOCK_MOVE: do_move(cursheet,0,0); redraw_sheet(cursheet); break;
case BLOCK_COPY: do_move(cursheet,1,0); redraw_sheet(cursheet); break;
case BLOCK_FILL: do_fill(cursheet); redraw_sheet(cursheet); break;
case FILL_BLOCK: fillwith(cursheet); redraw_sheet(cursheet); break;
case BLOCK_SORT: do_sort(cursheet); redraw_sheet(cursheet); break;
case BLOCK_MIRROR: do_mirror(cursheet); redraw_sheet(cursheet); break;
case ADJUST_LEFT:
case ADJUST_RIGHT:
case ADJUST_CENTER:
case ADJUST_DECIMAL:
case ADJUST_SCIENTIFIC:
case ADJUST_COMPACT:
case ADJUST_HEXACT:
case ADJUST_PRECISION:
case ADJUST_SHADOW:
case ADJUST_BOLD:
case ADJUST_UNDERLINE:
case ADJUST_TRANSPARENT:
case ADJUST_LABEL:
case ADJUST_LOCK:
case ADJUST_IGNORE: do_attribute(cursheet, c); break;
/* UP -- move up */ /*{{{*/
case K_UP:
{
relmoveto(cursheet, 0, -1, 0);
break;
}
/*}}}*/
/* DOWN -- move down */ /*{{{*/
case K_DOWN:
{
relmoveto(cursheet, 0, 1, 0);
break;
}
/*}}}*/
/* LEFT -- move left */ /*{{{*/
case K_LEFT:
{
relmoveto(cursheet, -1, 0, 0);
break;
}
/*}}}*/
/* RIGHT -- move right */ /*{{{*/
case K_RIGHT:
{
relmoveto(cursheet, 1, 0, 0);
break;
}
/*}}}*/
/* FIRSTL -- move to first line */ /*{{{*/
case K_FIRSTL:
case '<':
{
moveto(cursheet, -1, 0, -1);
break;
}
/*}}}*/
/* LASTL -- move to last line */ /*{{{*/
case K_LASTL:
case '>':
{
moveto(cursheet, -1, (cursheet->dimy ? cursheet->dimy-1 : 0), -1);
break;
}
/*}}}*/
/* HOME -- move to beginning of line */ /*{{{*/
case K_HOME:
{
moveto(cursheet, 0, -1, -1);
break;
}
/*}}}*/
/* END -- move to end of line */ /*{{{*/
case K_END:
{
moveto(cursheet, (cursheet->dimx ? cursheet->dimx-1 : 0), -1, -1);
break;
}
/*}}}*/
/* + -- move one sheet down */ /*{{{*/
case K_NSHEET:
case '+':
{
relmoveto(cursheet, 0, 0, 1);
break;
}
/*}}}*/
/* - -- move one sheet up */ /*{{{*/
case K_PSHEET:
case '-':
{
relmoveto(cursheet, 0, 0, -1);
break;
}
/*}}}*/
/* * -- move to bottom sheet */ /*{{{*/
case K_LSHEET:
case '*':
{
moveto(cursheet, -1, -1, (cursheet->dimz ? cursheet->dimz-1 : 0));
break;
}
/*}}}*/
/* _ -- move to top sheet */ /*{{{*/
case K_FSHEET:
case '_':
{
moveto(cursheet, -1, -1, 0);
break;
}
/*}}}*/
/* ENTER -- edit current cell */ /*{{{*/
case K_ENTER:
if (moveonly) break;
do_edit(cursheet, '\0', NULL, 0);
break;
/*}}}*/
/* MENTER -- edit current clocked cell */ /*{{{*/
case K_MENTER:
if (moveonly) break;
do_edit(cursheet, '\0', NULL, 1);
break;
/*}}}*/
/* ", @, digit -- edit current cell with character already in buffer */ /*{{{*/
case K_BACKSPACE:
case K_DC:
case '"':
case '@':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (moveonly) break;
do_edit(cursheet, c, NULL, 0);
break;
/*}}}*/
/* MARK -- toggle block marking */ /*{{{*/
case '.':
case K_MARK: if (moveonly) break; do_mark(cursheet, 0); break;
/*}}}*/
/* _("Save sheet file format:") -- save menu */ /*{{{*/
case K_SAVEMENU: if (moveonly) break; do_save(cursheet); break;
/*}}}*/
/* _("Load sheet file format:") -- load menu */ /*{{{*/
case K_LOAD:
case K_LOADMENU: if (moveonly) break; do_load(cursheet); break;
/*}}}*/
/* _("nN)ame") -- set name */ /*{{{*/
case K_NAME: if (moveonly) break; do_name(cursheet); break;
/*}}}*/
#ifdef ENABLE_HELP
case K_HELP: show_text(helpfile); break;
#else
case K_HELP: show_text(_("Sorry, manual is not installed.")); break;
#endif
case K_DUMPCELL: dump_current_cell(cursheet); break;
case K_ABOUT: show_text(_("<html><head><title>About teapot</title></head><body><center><pre>\n\n"
" ` ',` ' ' \n"
" ` ' ` ' ' \n"
" `' ' '`' \n"
" ' ` ' '` \n"
" ' '` ' ` '`` ` \n"
" `. Table Editor And Planner, or: \n"
" , . , , . . \n"
" ` ' ` ' ' \n"
" `::\\ /:::::::::::::::::\\ ___ \n"
" `::\\ /:::::::::::::::::::\\,'::::\\ \n"
" :::\\/:::::::::::::::::::::\\/ \\:\\ \n"
" :::::::::::::::::::::::::::\\ ::: \n"
" ::::::::::::::::::::::::::::; /:;' \n"
" `::::::::::::::::::::::::::::_/:;' \n"
" `::::::::::::::::::::::::::::' \n"
" `////////////////////////' \n"
" `:::::::::::::::::::::' \n"
"</pre>\n"
"<p>Teapot " VERSION "</p>\n"
"\n"
"<p>Original Version: Michael Haardt<br>\n"
"Current Maintainer: Joerg Walter<br>\n"
"Contibutions by: Glen Whitney<br>\b"
"Home Page: <a href='http://www.syntax-k.de/projekte/teapot/'>http://www.syntax-k.de/projekte/teapot/</a></p>\n"
"This distribution: <a href='https://code.studioinfinity.org/glen/teapot-spreadsheet/'>https://code.studioinfinity.org/glen/teapot-spreadsheet/</a></p>\n"
"\n"
"<p>Copyright 1995-2006 Michael Haardt,<br>\n"
"Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)<br>"
"Copyright 2019 Glen Whitney</p></center>\n"
"\f"
"<p>This program is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, either version 3 of the License, or\n"
"(at your option) any later version.</p>\n"
"\n"
"<p>This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.</p>\n"
"\n"
"<p>You should have received a copy of the GNU General Public License\n"
"along with this program. If not, see <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.</p>"
"</body></html>"));
break;
/* MENU, / -- main menu */ /*{{{*/
case '/': if (!moveonly && do_sheetcmd(cursheet, show_menu(cursheet), 0)) return 1; break;
/*}}}*/
/* _("sS)ave") -- save in current native format */ /*{{{*/
case K_SAVE: do_save(cursheet); break;
/*}}}*/
/* _("cC)opy") -- copy block */ /*{{{*/
case K_COPY: if (moveonly) break; do_move(cursheet,1,1); break;
/*}}}*/
/* RECALC -- recalculate */ /*{{{*/
case K_RECALC: if (moveonly) break; forceupdate(cursheet); break;
/*}}}*/
/* _("Usage: clock(condition,location[,location])") -- clock */ /*{{{*/
case K_CLOCK:
{
Location w;
for (ALL_LOCS_IN_SHEET(cursheet, w))
clk(cursheet, w);
update(cursheet);
break;
}
/*}}}*/
/* NPAGE -- page down */ /*{{{*/
case K_NPAGE:
{
cursheet->offy+=(cursheet->maxy-3);
relmoveto(cursheet, 0, cursheet->maxy-3, 0);
break;
}
/*}}}*/
/* PPAGE -- page up */ /*{{{*/
case K_PPAGE:
{
cursheet->offy = (cursheet->offy>=(cursheet->maxy-3) ? cursheet->offy-(cursheet->maxy-3) : 0);
relmoveto(cursheet, 0, (cursheet->cur[Y] >= (cursheet->maxy-3) ? -(cursheet->maxy-3) : -cursheet->cur[Y]), 0);
break;
}
/*}}}*/
/* FPAGE -- page right */ /*{{{*/
case K_FPAGE:
{
cursheet->offx+=cursheet->width;
relmoveto(cursheet, cursheet->width, 0, 0);
break;
}
/*}}}*/
/* BPAGE -- page left */ /*{{{*/
case K_BPAGE:
{
cursheet->offx=(cursheet->offx>=cursheet->width ? cursheet->offx-cursheet->width : 0);
relmoveto(cursheet, (cursheet->cur[X]>=cursheet->width ? -cursheet->width : -cursheet->cur[X]), 0, 0);
break;
}
/*}}}*/
/* SAVEQUIT -- save and quit */ /*{{{*/
case K_SAVEQUIT:
{
if (moveonly) break;
if (do_save(cursheet)!=-2) return 1;
break;
}
/*}}}*/
/* _("qQ)uit") -- quit */ /*{{{*/
case K_QUIT: if (moveonly) break; return 1;
/*}}}*/
default:
if (isalpha(c) && !moveonly) do_edit(cursheet, c, NULL, 0);
break;
}
return 0;
}
/*}}}*/
/* main */ /*{{{*/
int main(int argc, char *argv[])
{
/* variables */ /*{{{*/
Sheet sheet,*cursheet;
int o;
const char *loadfile;
char ln[1024];
/*}}}*/
setlocale(LC_ALL, "");
find_helpfile(helpfile, sizeof(helpfile), argv[0]);
/* parse options */ /*{{{*/
while ((o=getopt(argc,argv,"bdhnrqHp:?"))!=EOF) switch (o)
{
/* b -- run batch */ /*{{{*/
case 'b': batch = true; break;
/*}}}*/
/* d -- increase debug level */ /*{{{*/
case 'd': ++debug_level; break;
/*}}}*/
/* n -- no quoted strings */ /*{{{*/
case 'n': quote = DIRECT_STRING; break;
/*}}}*/
/* q -- force quoted strings */ /*{{{*/
case 'q': quote = QUOTE_STRING; break;
/*}}}*/
/* H -- no row/column headers */ /*{{{*/
case 'H': header = false; break;
/*}}}*/
/* r -- always redraw */ /*{{{*/
case 'r':
{
always_redraw = true;
break;
}
/*}}}*/
/* p -- precision */ /*{{{*/
case 'p':
{
long n;
char *end;
n=strtol(optarg,&end,0);
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
if (*end || n < 0 || n > LDBL_DIG)
{
Streamline internals of teapot The primary change is to add a “funcall” token, so that an entire expression can be encapsulated as a single token. This change is used to allow a cell to include simply a selection of appropriate semantic tokens. I.e., the content and iterative content are now each a single token like the value and the result value. Token vectors are used only as intermediate results in scanning and parsing. Not this means the cells are now in effect storing parse trees, so computation should be slightly faster and future extensions (like #56) should be facilitated. This commit also takes the opportunity while internals are being altered to add another token to a cell for future use for computed attributes, cf #22, and to change the internal numerical values from double and ints to long doubles and long longs. However, the change attempts to encapsulate that choice so it would be easy to change back or change to another representation. Note that these changes break savexdr(), as the internal binary format of a cell is now different. Rather than reimplement it, it is deprecated as the world does not need another binary spreadsheet format. Hence, the ascii format for teapot spreadsheets becomes the primary file format. Loading of old xdr files is still supported for backward compatibility. Closes #59. Also along the way, various other slight fixes and enhancements crept in, a partial but probably not exhaustive list of which follows: Fixes #31. Further revisions and improvements to documentation. Make the approximate comparison of floating point values scale more accurately with the size of the doubles being compared. Further extensions of absolute and relative cell addressing. Addition of (circle constant) tau function/constant. Modified string conversion to simply use internal printing routines, and to take "scientific" and "decimal" keywords. Allowed n() function to take a list of values, or just a single location defaulting to the current location. Added floor, ceil, trunc, and round functions, and allowed them to be keywords controlling the int() integer conversion function as well. Allowed substr() to drop its last argument to go to the end of the string. Provided an enum of built-in functions to preserve legacy function identifiers, allowing the large table inside func.c to be reorganized in a clearer fashion. Added additional annotation of properties of the built-in functions, including precedence. All operators are now also accessible as built-in functions. Made precedence of unary - lower than ^ to match python. Avoided inadvertently using FLTK @symbol abbreviations for formulas with "@" in them.
2019-08-23 19:12:06 +00:00
fprintf(stderr,
_("teapot: precision must be between 0 and %d.\n"), LDBL_DIG);
exit(1);
}
def_precision=n;
break;
}
/*}}}*/
/* default -- includes ? and h */ /*{{{*/
default:
{
fprintf(stderr,_(
"Usage: %s [-a] [-b] [-d]* [-h] [-n|-q] [-H] [-r] [-p digits] [file]\n"
" -a: use ASCII file format as default\n"
" -b: batch mode\n"
" -d: increase debug level, once for each occurrence\n"
" -h: print this message and exit\n"
" -n|-q: DO NOT or DO display strings in quotes, respectively\n"
" -H: hide row/column headers\n"
" -r: redraw more often\n"
" -p: set decimal precision\n"
), argv[0]);
exit(1);
}
/*}}}*/
}
loadfile = (optind<argc ? argv[optind] : (const char*)0);
/*}}}*/
cursheet = &sheet;
initialize_sheet(cursheet);
if (loadfile) /* load given sheet */ /*{{{*/
{
const char *msg;
cursheet->name=strdup(loadfile);
if (usexdr)
{
if ((msg=loadxdr(cursheet, cursheet->name)) != NULL)
line_msg(_("Load sheet from XDR file:"), msg);
}
else
if ((msg=loadport(cursheet, cursheet->name)) != NULL)
line_msg(_("Load sheet from ASCII file:"),msg);
}
/*}}}*/
if (batch) /* process batch */ /*{{{*/
while (fgets(ln,sizeof(ln),stdin)!=(char*)0)
{
/* variables */ /*{{{*/
size_t len;
char *cmd,*arg;
/*}}}*/
/* set cmd and arg */ /*{{{*/
++batchln;
len=strlen(ln);
if (len && ln[len-1]=='\n') ln[len-1]='\0';
cmd=ln; while (isspace((int)*cmd)) ++cmd;
arg=cmd;
while (*arg && !isspace((int)*arg)) ++arg;
while (isspace((int)*arg)) *arg++='\0';
/*}}}*/
/* goto location */ /*{{{*/
if (strcmp(cmd,"goto")==0) do_goto(cursheet,arg);
/*}}}*/
/* from location */ /*{{{*/
else if (strcmp(cmd,"from")==0)
{
do_goto(cursheet,arg);
do_mark(cursheet,1);
}
/*}}}*/
/* to location */ /*{{{*/
else if (strcmp(cmd,"to")==0)
{
do_goto(cursheet,arg);
do_mark(cursheet,2);
}
/*}}}*/
/* save-tbl file */ /*{{{*/
else if (strcmp(cmd,"save-tbl")==0) do_savetbl(cursheet,arg);
/*}}}*/
/* save-latex file */ /*{{{*/
else if (strcmp(cmd,"save-latex")==0) do_savelatex(cursheet,arg);
/*}}}*/
/* save-context file */ /*{{{*/
else if (strcmp(cmd,"save-context")==0) do_savecontext(cursheet,arg);
/*}}}*/
/* save-csv file */ /*{{{*/
else if (strcmp(cmd,"save-csv")==0) do_savecsv(cursheet,arg);
/*}}}*/
/* save-html file */ /*{{{*/
else if (strcmp(cmd,"save-html")==0) do_savehtml(cursheet,arg);
/*}}}*/
/* load-csv file */ /*{{{*/
else if (strcmp(cmd,"load-csv")==0) { loadcsv(cursheet,arg); forceupdate(cursheet); }
/*}}}*/
/* sort in x direction */ /*{{{*/
else if (strcmp(cmd,"sort-x")==0) do_batchsort(cursheet, IN_X, arg);
/*}}}*/
/* sort in y direction */ /*{{{*/
else if (strcmp(cmd,"sort-y")==0) do_batchsort(cursheet, IN_Y, arg);
/*}}}*/
/* sort in z direction */ /*{{{*/
else if (strcmp(cmd,"sort-z")==0) do_batchsort(cursheet, IN_Z, arg);
/*}}}*/
/* this is an unknown command */ /*{{{*/
else line_msg(_("Unknown batch command:"),cmd);
/*}}}*/
}
/*}}}*/
else /* process interactive input */ /*{{{*/
display_main(cursheet);
/*}}}*/
freesheet(cursheet,1);
fclose(stdin);
return 0;
}
/*}}}*/