Move source code into subdirectory
Also removed a stray copy of the automatically generated config.h which had somehow gotten into the distribution. Closes #36.
This commit is contained in:
parent
255bd86bf5
commit
ea230efc23
41 changed files with 68 additions and 70 deletions
60
src/CMakeLists.txt
Normal file
60
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,60 @@
|
|||
add_subdirectory(common)
|
||||
|
||||
include_directories("${Teapot_SOURCE_DIR}/src")
|
||||
include_directories("${Teapot_SOURCE_DIR}/src/common")
|
||||
|
||||
find_library(LIB_PORTABLEXDR portablexdr)
|
||||
if (NOT LIB_PORTABLEXDR)
|
||||
find_library(LIB_TIRPC tirpc)
|
||||
if (LIB_TIRPC)
|
||||
set(LIB_PORTABLEXDR ${LIB_TIRPC})
|
||||
else ()
|
||||
set(LIB_PORTABLEXDR "")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
find_package(Curses)
|
||||
if (CURSES_FOUND AND ENABLE_UTF8)
|
||||
find_library(LIB_CURSESW ncursesw)
|
||||
if (NOT LIB_CURSESW)
|
||||
find_library(LIB_CURSESW ncursesw5)
|
||||
endif ()
|
||||
if (LIB_CURSESW)
|
||||
set(teapot_DEB_DEPENDS ", libncursesw5 (>= 5.6+20071006-3)")
|
||||
set(CURSES_CURSES_LIBRARY ${LIB_CURSESW})
|
||||
else ()
|
||||
set(ENABLE_UTF8 OFF)
|
||||
set(teapot_DEB_DEPENDS ", libncurses5 (>= 5.6+20071006-3)")
|
||||
endif ()
|
||||
elseif (CURSES_FOUND)
|
||||
set(teapot_DEB_DEPENDS ", libncurses5 (>= 5.6+20071006-3)")
|
||||
endif ()
|
||||
|
||||
if (CURSES_FOUND)
|
||||
include_directories("${CURSES_INCLUDE_DIR}")
|
||||
add_executable(teapot display.c complete.c)
|
||||
target_link_libraries(teapot teapotlib m ${CURSES_CURSES_LIBRARY} ${LIB_PORTABLEXDR})
|
||||
install(TARGETS teapot DESTINATION bin)
|
||||
endif ()
|
||||
|
||||
find_package(FLTK)
|
||||
if (FLTK_FOUND)
|
||||
fltk_wrap_ui(fteapot fteapot.fl)
|
||||
add_executable(fteapot WIN32 ${fteapot_FLTK_UI_SRCS})
|
||||
set(fteapot_DEB_DEPENDS ", libstdc++6 (>= 4.1.1), libfltk1.3")
|
||||
if (ENABLE_HELP)
|
||||
set(fteapot_DEB_DEPENDS "${fteapot_DEB_DEPENDS}, libfltk-images1.3")
|
||||
if (ENABLE_STATIC)
|
||||
target_link_libraries(fteapot teapotlib fltk fltk_images ${LIB_PORTABLEXDR})
|
||||
else ()
|
||||
target_link_libraries(fteapot teapotlib fltk fltk_images ${LIB_PORTABLEXDR})
|
||||
endif ()
|
||||
else ()
|
||||
if (ENABLE_STATIC)
|
||||
target_link_libraries(fteapot teapotlib fltk fltk_images ${LIB_PORTABLEXDR})
|
||||
else ()
|
||||
target_link_libraries(fteapot teapotlib fltk ${LIB_PORTABLEXDR})
|
||||
endif ()
|
||||
endif ()
|
||||
install(TARGETS fteapot DESTINATION bin)
|
||||
endif ()
|
6
src/common/CMakeLists.txt
Normal file
6
src/common/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
include_directories("${Teapot_SOURCE_DIR}/src")
|
||||
include_directories("${Teapot_SOURCE_DIR}/src/common")
|
||||
|
||||
link_directories("${Teapot_SOURCE_DIR}/src/common")
|
||||
|
||||
add_library(teapotlib context.c csv.c eval.c func.c htmlio.c latex.c main.c misc.c parser.c sc.c scanner.c sheet.c utf8.c wk1.c xdr.c)
|
147
src/common/context.c
Normal file
147
src/common/context.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "context.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
/*}}}*/
|
||||
|
||||
/* savecontext -- save as ConTeXt table */ /*{{{*/
|
||||
const char *savecontext(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||
Location w;
|
||||
char buf[1024];
|
||||
char num[20];
|
||||
char fullname[PATH_MAX];
|
||||
Cell *cell;
|
||||
/*}}}*/
|
||||
|
||||
/* asserts */ /*{{{*/
|
||||
assert(sheet != (Sheet*)0);
|
||||
assert(name != (const char*)0);
|
||||
/*}}}*/
|
||||
*count=0;
|
||||
w[X] = beg[X];
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
|
||||
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
|
||||
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
{
|
||||
if (body)
|
||||
/* open new file */ /*{{{*/
|
||||
{
|
||||
sprintf(num, ".%d", w[Z]);
|
||||
|
||||
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* print header */ /*{{{*/
|
||||
if (w[Z] == beg[Z])
|
||||
{
|
||||
if (fputs_close("\\starttext\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fputs_close("\\page\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* print bogus format */ /*{{{*/
|
||||
fprintf(fp,"\\starttable[");
|
||||
for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X]))
|
||||
if (fputs_close("|l",fp)==EOF) return strerror(errno);
|
||||
fprintf(fp,"|]\n");
|
||||
/*}}}*/
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
|
||||
/* print contents */ /*{{{*/
|
||||
{
|
||||
for (w[X]=beg[X]; w[X]<=end[X]; )
|
||||
{
|
||||
int multicols;
|
||||
char *bufp;
|
||||
|
||||
if (w[X] > beg[X] && fputs_close("\\NC",fp)==EOF) return strerror(errno);
|
||||
for (multicols=w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
|
||||
multicols=multicols-w[X];
|
||||
if (multicols>1) fprintf(fp,"\\use{%d}",multicols);
|
||||
cell = CELL_AT(sheet, w);
|
||||
switch (getadjust(cell))
|
||||
{
|
||||
case LEFT: if (fputs_close("\\JustLeft ",fp)==EOF) return strerror(errno); break;
|
||||
case RIGHT: if (fputs_close("\\JustRight ",fp)==EOF) return strerror(errno); break;
|
||||
case CENTER: if (fputs_close("\\JustCenter ",fp)==EOF) return strerror(errno); break;
|
||||
default: assert(0);
|
||||
}
|
||||
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
|
||||
getprecision(cell), sheet, w);
|
||||
/* if (fputs_close("}{",fp)==EOF) return strerror(errno);*/
|
||||
if (transparent(cell))
|
||||
{
|
||||
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||
{
|
||||
case '%':
|
||||
case '$':
|
||||
case '&':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
case '~':
|
||||
case '^': if (fputc_close('\\',fp)==EOF || fputc_close(*bufp,fp)==EOF) return strerror(errno); break;
|
||||
case '\\': if (fputs_close("\\backslash ",fp)==EOF) return strerror(errno); break;
|
||||
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/* if (fputc_close('}',fp)==EOF) return strerror(errno);*/
|
||||
w[X] += multicols;
|
||||
++*count;
|
||||
}
|
||||
if (fputs_close(w[Y]<end[Y] ? "\\MR\n" : "\n\\stoptable\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
if (body)
|
||||
{
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fputs_close("\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
}
|
||||
if (!body)
|
||||
{
|
||||
if (fputs_close("\\stoptext\n",fp)==EOF) return strerror(errno);
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
return (const char*)0;
|
||||
}
|
||||
/*}}}*/
|
10
src/common/context.h
Normal file
10
src/common/context.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef CONTEXT_H
|
||||
#define CONTEXT_H
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
const char *savecontext(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count);
|
||||
|
||||
#endif
|
160
src/common/csv.c
Normal file
160
src/common/csv.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef OLD_REALLOC
|
||||
#define realloc(s,l) myrealloc(s,l)
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include "csv.h"
|
||||
|
||||
static int semicol=0;
|
||||
|
||||
/* csv_setopt -- set language */ /*{{{C}}}*//*{{{*/
|
||||
void csv_setopt(int sem)
|
||||
{
|
||||
semicol=sem;
|
||||
}
|
||||
/*}}}*/
|
||||
#if 0
|
||||
/* csv_date -- convert string "year<sep>month<sep>day<sep>" to date */ /*{{{*/
|
||||
static struct CSV_Date csv_date(const char *s, const char **end)
|
||||
{
|
||||
struct CSV_Date date;
|
||||
|
||||
assert(s!=(const char*)0);
|
||||
assert(end!=(const char**)0);
|
||||
*end=s;
|
||||
if (*s=='"')
|
||||
{
|
||||
++s;
|
||||
if (isdigit(*s))
|
||||
{
|
||||
for (date.year=0; isdigit(*s); date.year=10*date.year+(*s-'0'),++s);
|
||||
if (*s)
|
||||
{
|
||||
++s;
|
||||
if (isdigit(*s))
|
||||
{
|
||||
for (date.month=0; isdigit(*s); date.month=10*date.month+(*s-'0'),++s);
|
||||
if (*s)
|
||||
{
|
||||
++s;
|
||||
if (isdigit(*s))
|
||||
{
|
||||
for (date.day=0; isdigit(*s); date.day=10*date.day+(*s-'0'),++s);
|
||||
if (*s=='"')
|
||||
{
|
||||
++s;
|
||||
*end=s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return date;
|
||||
}
|
||||
/*}}}*/
|
||||
#endif
|
||||
/* csv_separator -- convert string \t to nothing */ /*{{{*/
|
||||
void csv_separator(const char *s, const char **end)
|
||||
{
|
||||
assert(s!=(const char*)0);
|
||||
assert(end!=(const char**)0);
|
||||
*end=s+(*s=='\t' || (semicol && *s==';') || (!semicol && *s==','));
|
||||
}
|
||||
/*}}}*/
|
||||
/* csv_long -- convert string [0[x]]12345 to long */ /*{{{*/
|
||||
long csv_long(const char *s, const char **end)
|
||||
{
|
||||
long value;
|
||||
const char *t;
|
||||
|
||||
assert(s!=(const char*)0);
|
||||
assert(end!=(const char**)0);
|
||||
if (*s=='\t') { *end=s; return 0L; };
|
||||
value=strtol(s,(char**)end,0);
|
||||
if (s!=*end)
|
||||
{
|
||||
t=*end; csv_separator(t,end);
|
||||
if (t!=*end || *t=='\0' || *t=='\n') return value;
|
||||
}
|
||||
*end=s; return 0L;
|
||||
}
|
||||
/*}}}*/
|
||||
/* csv_double -- convert string 123.4e5 to double */ /*{{{*/
|
||||
double csv_double(const char *s, const char **end)
|
||||
{
|
||||
double value;
|
||||
const char *t;
|
||||
|
||||
assert(s!=(const char*)0);
|
||||
assert(end!=(const char**)0);
|
||||
if (*s=='\t') { *end=s; return 0.0; };
|
||||
value=strtod(s,(char**)end);
|
||||
if (s!=*end)
|
||||
{
|
||||
t=*end; csv_separator(t,end);
|
||||
if (t!=*end || *t=='\0' || *t=='\n') return value;
|
||||
}
|
||||
*end=s; return 0.0;
|
||||
}
|
||||
/*}}}*/
|
||||
/* csv_string -- convert almost any string to string */ /*{{{*/
|
||||
char *csv_string(const char *s, const char **end)
|
||||
{
|
||||
static char *string;
|
||||
static int strings,stringsz;
|
||||
|
||||
assert(s!=(const char*)0);
|
||||
assert(end!=(const char**)0);
|
||||
strings=0;
|
||||
stringsz=0;
|
||||
string=(char*)0;
|
||||
if (!isprint((int)*s) || (!semicol && *s==',') || (semicol && *s==';')) return (char*)0;
|
||||
if (*s=='"')
|
||||
{
|
||||
++s;
|
||||
while (*s!='\0' && *s!='\n' && *s!='"')
|
||||
{
|
||||
if ((strings+2)>=stringsz)
|
||||
{
|
||||
string=realloc(string,stringsz+=32);
|
||||
}
|
||||
string[strings]=*s;
|
||||
++strings;
|
||||
++s;
|
||||
}
|
||||
if (*s=='"') ++s;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*s!='\0' && *s!='\n' && *s!='\t' && ((!semicol && *s!=',') || (semicol && *s!=';')))
|
||||
{
|
||||
if ((strings+2)>=stringsz)
|
||||
{
|
||||
string=realloc(string,stringsz+=32);
|
||||
}
|
||||
string[strings]=*s;
|
||||
++strings;
|
||||
++s;
|
||||
}
|
||||
}
|
||||
string[strings]='\0';
|
||||
*end=s;
|
||||
csv_separator(s,end);
|
||||
return string;
|
||||
}
|
||||
/*}}}*/
|
17
src/common/csv.h
Normal file
17
src/common/csv.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef CSV_H
|
||||
#define CSV_H
|
||||
|
||||
struct CSV_Date
|
||||
{
|
||||
int day;
|
||||
int month;
|
||||
int year;
|
||||
};
|
||||
|
||||
void csv_setopt(int sem);
|
||||
void csv_separator(const char *s, const char **end);
|
||||
char *csv_string(const char *s, const char **end);
|
||||
double csv_double(const char *s, const char **end);
|
||||
long csv_long(const char *s, const char **end);
|
||||
|
||||
#endif
|
38
src/common/default.h
Normal file
38
src/common/default.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef DEFAULT_H
|
||||
#define DEFAULT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* default width of a column */
|
||||
#define DEF_COLUMNWIDTH 12
|
||||
|
||||
/* default precision of a printed value */
|
||||
#define DEF_PRECISION 2
|
||||
|
||||
/* default is no scientific notation for numbers */
|
||||
#define DEF_SCIENTIFIC 0
|
||||
|
||||
/* character attribute for cell and row numbers */
|
||||
#define DEF_NUMBER A_BOLD
|
||||
|
||||
/* character attribute for cell cursor */
|
||||
#define DEF_CELLCURSOR A_REVERSE
|
||||
|
||||
/* character attribute for selected menu choice */
|
||||
#define DEF_MENU A_REVERSE
|
||||
|
||||
/* maximum number of sort keys */
|
||||
#define MAX_SORTKEYS 8
|
||||
|
||||
/* maximum number of eval() nesting */
|
||||
#define MAX_EVALNEST 32
|
||||
|
||||
/* define if testing with EletricFence */
|
||||
#ifdef THE_ELECTRIC_FENCE
|
||||
#undef malloc
|
||||
#undef free
|
||||
#undef realloc
|
||||
#undef calloc
|
||||
#endif
|
||||
|
||||
#endif
|
1290
src/common/eval.c
Normal file
1290
src/common/eval.c
Normal file
File diff suppressed because it is too large
Load diff
27
src/common/eval.h
Normal file
27
src/common/eval.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef THE_EVAL_H
|
||||
#define THE_EVAL_H
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
Token tcopy(Token n);
|
||||
void tfree(Token *n);
|
||||
void tvecfreetoks(Token **tvec);
|
||||
void tvecfree(Token **tvec);
|
||||
size_t tveclen(Token **tvec);
|
||||
Token tpow(Token l, Token r);
|
||||
Token tdiv(Token l, Token r);
|
||||
Token tmod(Token l, Token r);
|
||||
Token tmul(Token l, Token r);
|
||||
Token tadd(Token l, Token r);
|
||||
Token tsub(Token l, Token r);
|
||||
Token tneg(Token x);
|
||||
Token tfuncall(Token *ident, int argc, Token argv[]);
|
||||
Token tlt(Token l, Token r);
|
||||
Token tle(Token l, Token r);
|
||||
Token tge(Token l, Token r);
|
||||
Token tgt(Token l, Token r);
|
||||
Token teq(Token l, Token r);
|
||||
Token tabouteq(Token l, Token r);
|
||||
Token tne(Token l, Token r);
|
||||
|
||||
#endif
|
1441
src/common/func.c
Normal file
1441
src/common/func.c
Normal file
File diff suppressed because it is too large
Load diff
14
src/common/func.h
Normal file
14
src/common/func.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef FUNC_H
|
||||
#define FUNC_H
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char name[20];
|
||||
Token (*func)(int, const Token[]);
|
||||
} Tfunc;
|
||||
|
||||
extern Tfunc tfunc[];
|
||||
|
||||
#endif
|
123
src/common/htmlio.c
Normal file
123
src/common/htmlio.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "htmlio.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
/*}}}*/
|
||||
|
||||
/* savehtml -- save as HTML table */ /*{{{*/
|
||||
const char *savehtml(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||
Location w;
|
||||
char buf[1024];
|
||||
char num[20];
|
||||
char fullname[PATH_MAX];
|
||||
Cell *cell;
|
||||
/*}}}*/
|
||||
|
||||
/* asserts */ /*{{{*/
|
||||
assert(sheet != (Sheet*)0);
|
||||
assert(name != (const char*)0);
|
||||
/*}}}*/
|
||||
*count=0;
|
||||
w[X] = beg[X];
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
|
||||
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
|
||||
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
{
|
||||
if (body) /* open new file */ /*{{{*/
|
||||
{
|
||||
sprintf(num, ".%d", w[Z]);
|
||||
|
||||
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
else /* print header */ /*{{{*/
|
||||
if (fputs_close("<html>\n<head>\n<title>\n</title>\n</head>\n<body>\n",fp)==EOF) return strerror(errno);
|
||||
/*}}}*/
|
||||
|
||||
if (fputs_close("<table>\n",fp)==EOF) return strerror(errno);
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y])) /* print contents */ /*{{{*/
|
||||
{
|
||||
if (fputs_close("<tr>",fp)==EOF) return strerror(errno);
|
||||
for (w[X]=beg[X]; w[X]<=end[X]; )
|
||||
{
|
||||
int multicols;
|
||||
char *bufp;
|
||||
|
||||
for (multicols=w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
|
||||
multicols = multicols - w[X];
|
||||
if (multicols>1) fprintf(fp,"<td colspan=%d",multicols);
|
||||
else fprintf(fp,"<td");
|
||||
cell = CELL_AT(sheet, w);
|
||||
switch (getadjust(cell))
|
||||
{
|
||||
case LEFT: if (fputs_close(" align=left>",fp)==EOF) return strerror(errno); break;
|
||||
case RIGHT: if (fputs_close(" align=right>",fp)==EOF) return strerror(errno); break;
|
||||
case CENTER: if (fputs_close(" align=center>",fp)==EOF) return strerror(errno); break;
|
||||
default: assert(0);
|
||||
}
|
||||
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
|
||||
getprecision(cell), sheet, w);
|
||||
if (transparent(cell))
|
||||
{
|
||||
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||
{
|
||||
case '<': if (fputs_close("<",fp)==EOF) return strerror(errno); break;
|
||||
case '>': if (fputs_close(">",fp)==EOF) return strerror(errno); break;
|
||||
case '&': if (fputs_close("&",fp)==EOF) return strerror(errno); break;
|
||||
case '"': if (fputs_close(""",fp)==EOF) return strerror(errno); break;
|
||||
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
if (fputs_close("</td>",fp)==EOF) return strerror(errno);
|
||||
w[X] += multicols;
|
||||
++*count;
|
||||
}
|
||||
if (fputs_close("</tr>\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
if (fputs_close("</table>\n",fp)==EOF) return strerror(errno);
|
||||
if (body)
|
||||
{
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
}
|
||||
if (!body)
|
||||
{
|
||||
if (fputs_close("</body>\n</html>\n",fp)==EOF) return strerror(errno);
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
return (const char*)0;
|
||||
}
|
||||
/*}}}*/
|
10
src/common/htmlio.h
Normal file
10
src/common/htmlio.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef HTML_H
|
||||
#define HTML_H
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
const char *savehtml(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count);
|
||||
|
||||
#endif
|
147
src/common/latex.c
Normal file
147
src/common/latex.c
Normal file
|
@ -0,0 +1,147 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "latex.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
/*}}}*/
|
||||
|
||||
/* savelatex -- save as LaTeX table */ /*{{{*/
|
||||
const char *savelatex(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||
Location w;
|
||||
char buf[1024];
|
||||
char num[20];
|
||||
char fullname[PATH_MAX];
|
||||
Cell *cell;
|
||||
/*}}}*/
|
||||
|
||||
/* asserts */ /*{{{*/
|
||||
assert(sheet != (Sheet*)0);
|
||||
assert(name != (const char*)0);
|
||||
/*}}}*/
|
||||
|
||||
*count=0;
|
||||
w[X] = beg[X];
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
|
||||
if (shadowed(CELL_AT(sheet,w))) return _("Shadowed cells in first column");
|
||||
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||
for (w[Z]=beg[Z]; w[Z]<=end[Z]; ++(w[Z]))
|
||||
{
|
||||
if (body)
|
||||
/* open new file */ /*{{{*/
|
||||
{
|
||||
sprintf(num, ".%d", w[Z]);
|
||||
|
||||
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||
fullname[sizeof(fullname)-1]='\0';
|
||||
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* print header */ /*{{{*/
|
||||
if (w[Z] == beg[Z])
|
||||
{
|
||||
if (fputs_close("\\documentclass{article}\n\\usepackage{longtable}\n\\begin{document}\n\\setlongtables\n\\vfill\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fputs_close("\\clearpage\n\\vfill\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* print bogus format */ /*{{{*/
|
||||
fprintf(fp,"\\begin{longtable}{");
|
||||
for (w[X]=beg[X]; w[X]<=end[X]; ++(w[X])) if (fputc_close('l',fp)==EOF) return strerror(errno);
|
||||
fprintf(fp,"}\n");
|
||||
/*}}}*/
|
||||
for (w[Y]=beg[Y]; w[Y]<=end[Y]; ++(w[Y]))
|
||||
/* print contents */ /*{{{*/
|
||||
{
|
||||
for (w[X]=beg[X]; w[X]<=end[X]; )
|
||||
{
|
||||
int multicols;
|
||||
char *bufp;
|
||||
|
||||
if (w[X]>beg[X] && fputc_close('&',fp)==EOF) return strerror(errno);
|
||||
for (multicols = w[X]+1; multicols<sheet->dimx && SHADOWEDC(sheet,multicols,w[Y],w[Z]); ++multicols);
|
||||
multicols = multicols - w[X];
|
||||
fprintf(fp,"\\multicolumn{%d}{",multicols);
|
||||
cell = CELL_AT(sheet, w);
|
||||
switch (getadjust(cell))
|
||||
{
|
||||
case LEFT: if (fputc_close('l',fp)==EOF) return strerror(errno); break;
|
||||
case RIGHT: if (fputc_close('r',fp)==EOF) return strerror(errno); break;
|
||||
case CENTER: if (fputc_close('c',fp)==EOF) return strerror(errno); break;
|
||||
default: assert(0);
|
||||
}
|
||||
printvalue(buf, sizeof(buf), 0, 0, getscientific(cell),
|
||||
getprecision(cell), sheet, w);
|
||||
if (fputs_close("}{",fp)==EOF) return strerror(errno);
|
||||
if (transparent(cell))
|
||||
{
|
||||
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||
{
|
||||
case '%':
|
||||
case '$':
|
||||
case '&':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
case '~':
|
||||
case '^': if (fputc_close('\\',fp)==EOF || fputc_close(*bufp,fp)==EOF) return strerror(errno); break;
|
||||
case '\\': if (fputs_close("\\backslash ",fp)==EOF) return strerror(errno); break;
|
||||
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||
}
|
||||
if (fputc_close('}',fp)==EOF) return strerror(errno);
|
||||
w[X] += multicols;
|
||||
++*count;
|
||||
}
|
||||
if (fputs_close(w[Y]<end[Y] ? "\\\\\n" : "\n\\end{longtable}\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
/*}}}*/
|
||||
if (body)
|
||||
{
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fputs_close("\\vfill\n",fp)==EOF) return strerror(errno);
|
||||
}
|
||||
}
|
||||
if (!body)
|
||||
{
|
||||
if (fputs_close("\\end{document}\n",fp)==EOF) return strerror(errno);
|
||||
if (fclose(fp)==EOF) return strerror(errno);
|
||||
}
|
||||
return (const char*)0;
|
||||
}
|
||||
/*}}}*/
|
10
src/common/latex.h
Normal file
10
src/common/latex.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef LATEX_H
|
||||
#define LATEX_H
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
const char *savelatex(Sheet *sheet, const char *name, int body,
|
||||
const Location beg, const Location end,
|
||||
unsigned int *count);
|
||||
|
||||
#endif
|
1965
src/common/main.c
Normal file
1965
src/common/main.c
Normal file
File diff suppressed because it is too large
Load diff
97
src/common/main.h
Normal file
97
src/common/main.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _(x) (x)
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int batch;
|
||||
extern int def_precision;
|
||||
extern int quote;
|
||||
extern int header;
|
||||
extern int debug_level;
|
||||
extern unsigned int batchln;
|
||||
|
||||
/* A variable of type Key is either a special symbol from this enum, representing
|
||||
actions the user has triggered (by whatever means available), or a Unicode
|
||||
character that was entered
|
||||
*/
|
||||
typedef enum {
|
||||
K_NONE = 0,
|
||||
K_INVALID = -1,
|
||||
K_BACKSPACE = -2,
|
||||
K_BPAGE = -3,
|
||||
K_CLOCK = -4,
|
||||
K_COPY = -5,
|
||||
K_DC = -6,
|
||||
K_DOWN = -7,
|
||||
K_END = -8,
|
||||
K_ENTER = -9,
|
||||
K_FIRSTL = -10,
|
||||
K_FPAGE = -11,
|
||||
K_FSHEET = -12,
|
||||
K_HOME = -13,
|
||||
K_LASTL = -14,
|
||||
K_LEFT = -15,
|
||||
K_LOAD = -16,
|
||||
K_LOADMENU = -17,
|
||||
K_LSHEET = -18,
|
||||
K_MARK = -19,
|
||||
K_MENTER = -20,
|
||||
K_NPAGE = -21,
|
||||
K_NSHEET = -22,
|
||||
K_PPAGE = -23,
|
||||
K_PSHEET = -24,
|
||||
K_QUIT = -25,
|
||||
K_RECALC = -26,
|
||||
K_RIGHT = -27,
|
||||
K_SAVE = -28,
|
||||
K_SAVEMENU = -29,
|
||||
K_SAVEQUIT = -30,
|
||||
K_UP = -31,
|
||||
K_GOTO = -32,
|
||||
K_NAME = -33,
|
||||
ADJUST_LEFT = -34,
|
||||
ADJUST_RIGHT = -35,
|
||||
ADJUST_CENTER = -36,
|
||||
ADJUST_SCIENTIFIC = -37,
|
||||
ADJUST_BOLD = -38,
|
||||
ADJUST_PRECISION = -39,
|
||||
ADJUST_SHADOW = -40,
|
||||
ADJUST_TRANSPARENT = -41,
|
||||
ADJUST_LABEL = -42,
|
||||
ADJUST_LOCK = -43,
|
||||
ADJUST_IGNORE = -44,
|
||||
K_COLWIDTH = -45,
|
||||
BLOCK_CLEAR = -46,
|
||||
BLOCK_INSERT = -47,
|
||||
BLOCK_DELETE = -48,
|
||||
BLOCK_MOVE = -49,
|
||||
BLOCK_COPY = -50,
|
||||
BLOCK_FILL = -51,
|
||||
BLOCK_SORT = -52,
|
||||
BLOCK_MIRROR = -53,
|
||||
K_ABOUT = -54,
|
||||
K_HELP = -55,
|
||||
K_DUMPCELL = -56,
|
||||
ADJUST_UNDERLINE = -57
|
||||
} Key;
|
||||
|
||||
extern int do_sheetcmd(Sheet *cursheet, Key c, int moveonly);
|
||||
extern int doanyway(Sheet *sheet, const char *msg);
|
||||
extern void moveto(Sheet *sheet, int x, int y, int z);
|
||||
extern void movetoloc(Sheet *sheet, const Location dest);
|
||||
extern void relmoveto(Sheet *sheet, int x, int y, int z);
|
||||
extern void do_mark(Sheet *cursheet, MarkState ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
249
src/common/misc.c
Normal file
249
src/common/misc.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef NEED_BCOPY
|
||||
#define memmove(dst,src,len) bcopy(src,dst,len)
|
||||
#endif
|
||||
|
||||
|
||||
#include "default.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
/*}}}*/
|
||||
|
||||
/* posnumber -- match positive integer */ /*{{{*/
|
||||
long int posnumber(const char *s, const char **endptr)
|
||||
{
|
||||
unsigned int base=10;
|
||||
unsigned char c;
|
||||
register const char *nptr = s;
|
||||
long int result = 0L;
|
||||
int saw_a_digit = 0;
|
||||
|
||||
if (*nptr == '0')
|
||||
{
|
||||
if ((c = *++nptr) == 'x' || c == 'X')
|
||||
{
|
||||
++nptr;
|
||||
base = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
saw_a_digit = 1;
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
|
||||
--nptr;
|
||||
while ((c=*++nptr)!='\0')
|
||||
{
|
||||
if (isdigit(c)) c -= '0';
|
||||
else if (isupper(c)) c -= ('A'-10);
|
||||
else if (islower(c)) c -= ('a'-10);
|
||||
else break;
|
||||
if (c>=base) break;
|
||||
saw_a_digit = 1;
|
||||
result = result*base+c;
|
||||
}
|
||||
|
||||
*endptr=(saw_a_digit ? nptr : s);
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
/* posorder -- sort two integers */ /*{{{*/
|
||||
void posorder(int *x, int *y)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
int t;
|
||||
/*}}}*/
|
||||
|
||||
assert(x!=(int*)0);
|
||||
assert(*x>=0);
|
||||
assert(y!=(int*)0);
|
||||
assert(*y>=0);
|
||||
if (*x>*y)
|
||||
{
|
||||
t=*x;
|
||||
*x=*y;
|
||||
*y=t;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* mystrmalloc -- return malloced copy of string */ /*{{{*/
|
||||
char *mystrmalloc(const char *str)
|
||||
{
|
||||
return (strcpy(malloc(strlen(str)+1),str));
|
||||
}
|
||||
/*}}}*/
|
||||
/* finite -- return error message about number or null */ /*{{{*/
|
||||
static volatile int caughtfpe;
|
||||
|
||||
static void catchfpe(int n)
|
||||
{
|
||||
caughtfpe=1;
|
||||
}
|
||||
|
||||
const char *dblfinite(double x)
|
||||
{
|
||||
/*struct sigaction act;
|
||||
|
||||
caughtfpe=0;
|
||||
act.sa_handler=catchfpe;
|
||||
act.sa_flags=0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaction(SIGFPE,&act,(struct sigaction*)0);*/
|
||||
signal(SIGFPE, catchfpe);
|
||||
if (x==0.0)
|
||||
{
|
||||
if (caughtfpe) return _("Not a (finite) floating point number"); /* who knows */
|
||||
else return (const char*)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (caughtfpe) return _("Not a (finite) floating point number");
|
||||
/* If one comparison was allowed, more won't hurt either. */
|
||||
if (x<0.0)
|
||||
{
|
||||
if (x<-DBL_MAX) return _("Not a (finite) floating point number"); /* -infinite */
|
||||
else return (const char*)0;
|
||||
}
|
||||
else if (x>0.0)
|
||||
{
|
||||
if (x>DBL_MAX) return _("Not a (finite) floating point number"); /* +infinite */
|
||||
else return (const char*)0;
|
||||
}
|
||||
else return _("Not a (finite) floating point number"); /* NaN */
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* fputc_close -- error checking fputc which closes stream on error */ /*{{{*/
|
||||
int fputc_close(char c, FILE *fp)
|
||||
{
|
||||
int e;
|
||||
|
||||
if ((e=fputc(c,fp))==EOF)
|
||||
{
|
||||
int oerrno;
|
||||
|
||||
oerrno=errno;
|
||||
(void)fclose(fp);
|
||||
errno=oerrno;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/* fputs_close -- error checking fputs which closes stream on error */ /*{{{*/
|
||||
int fputs_close(const char *s, FILE *fp)
|
||||
{
|
||||
int e;
|
||||
|
||||
if ((e=fputs(s,fp))==EOF)
|
||||
{
|
||||
int oerrno;
|
||||
|
||||
oerrno=errno;
|
||||
(void)fclose(fp);
|
||||
errno=oerrno;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/* adjust -- readjust a left adjusted string in a buffer */ /*{{{*/
|
||||
void adjust(Adjust a, char *s, size_t n)
|
||||
{
|
||||
assert(s!=(char*)0);
|
||||
assert(mbslen(s)<=n);
|
||||
switch (a)
|
||||
{
|
||||
/* LEFT */ /*{{{*/
|
||||
case LEFT: break;
|
||||
/*}}}*/
|
||||
/* RIGHT */ /*{{{*/
|
||||
case RIGHT:
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len=mbslen(s);
|
||||
if (len < n)
|
||||
{
|
||||
memmove(s+n-len, s, strlen(s)+1);
|
||||
memset(s, ' ', n-len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* CENTER */ /*{{{*/
|
||||
case CENTER:
|
||||
{
|
||||
size_t len,pad;
|
||||
|
||||
len=mbslen(s);
|
||||
pad=(n-len)/2;
|
||||
assert((pad+len)<=n);
|
||||
memmove(s+pad, s, strlen(s)+1);
|
||||
memset(s, ' ', pad);
|
||||
//*(s+strlen(s)+n-pad-len)='\0';
|
||||
//(void)memset(s+strlen(s),' ',n-pad-len-1);
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* default */ /*{{{*/
|
||||
default: assert(0);
|
||||
/*}}}*/
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* strerror -- strerror(3) */ /*{{{*/
|
||||
#ifdef NEED_STRERROR
|
||||
extern int sys_nerr;
|
||||
extern const char *sys_errlist[];
|
||||
|
||||
const char *strerror(int errno)
|
||||
{
|
||||
return (errno>=0 && errno<sys_nerr ? sys_errlist[errno] : "unknown error");
|
||||
}
|
||||
#endif
|
||||
/*}}}*/
|
||||
/* myrealloc -- ANSI conforming realloc() */ /*{{{*/
|
||||
#ifdef OLD_REALLOC
|
||||
#undef realloc
|
||||
void *myrealloc(void *p, size_t n)
|
||||
{
|
||||
return (p==(void*)0 ? malloc(n) : realloc(p,n));
|
||||
}
|
||||
#endif
|
||||
/*}}}*/
|
||||
|
||||
char *striphtml(const char *in)
|
||||
{
|
||||
char *end, *stripped = malloc(strlen(in)), *out = stripped;
|
||||
in--;
|
||||
|
||||
while (in && (end = strchr(++in, '<'))) {
|
||||
memcpy(out, in, end-in);
|
||||
out += end-in;
|
||||
in = strchr(end+1, '>');
|
||||
}
|
||||
if (in) strcpy(out, in);
|
||||
else *out = 0;
|
||||
return stripped;
|
||||
}
|
25
src/common/misc.h
Normal file
25
src/common/misc.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void posorder(int *x, int *y);
|
||||
long int posnumber(const char *s, const char **endptr);
|
||||
char *mystrmalloc(const char *str);
|
||||
const char *dblfinite(double x);
|
||||
int fputc_close(char c, FILE *fp);
|
||||
int fputs_close(const char *s, FILE *fp);
|
||||
void adjust(Adjust a, char *s, size_t n);
|
||||
char *striphtml(const char *in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
328
src/common/parser.c
Normal file
328
src/common/parser.c
Normal file
|
@ -0,0 +1,328 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "eval.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
#include "parser.h"
|
||||
#include "scanner.h"
|
||||
#include "sheet.h"
|
||||
/*}}}*/
|
||||
/* #defines */ /*{{{*/
|
||||
#define MAXARGC 16
|
||||
/*}}}*/
|
||||
|
||||
/* prototypes */ /*{{{*/
|
||||
static Token term(Token *n[], int *i);
|
||||
/*}}}*/
|
||||
|
||||
/* primary -- parse and evaluate a primary term */ /*{{{*/
|
||||
static Token primary(Token *n[], int *i)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
int argc,j;
|
||||
Token *ident,argv[MAXARGC],result;
|
||||
/*}}}*/
|
||||
|
||||
if (n[*i]==(Token*)0)
|
||||
/* error */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_("missing operator"))+1),_("missing operator"));
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
else switch (n[*i]->type)
|
||||
{
|
||||
/* STRING, FLOAT, INT */ /*{{{*/
|
||||
case STRING:
|
||||
case FLOAT:
|
||||
case INT:
|
||||
{
|
||||
return tcopy(*n[(*i)++]);
|
||||
}
|
||||
/*}}}*/
|
||||
/* OPERATOR */ /*{{{*/
|
||||
case OPERATOR:
|
||||
{
|
||||
if (n[*i]->u.op==OP)
|
||||
/* return paren term */ /*{{{*/
|
||||
{
|
||||
++(*i);
|
||||
result=term(n,i);
|
||||
if (result.type==EEK) return result;
|
||||
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP)
|
||||
{
|
||||
++(*i);
|
||||
return result;
|
||||
}
|
||||
tfree(&result);
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_(") expected"))+1),_(") expected"));
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (n[*i]->u.op==MINUS)
|
||||
/* return negated term */ /*{{{*/
|
||||
{
|
||||
++(*i);
|
||||
return(tneg(primary(n,i)));
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* return error, value expected */ /*{{{*/
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=mystrmalloc(_("value expected"));
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
}
|
||||
/*}}}*/
|
||||
/* LIDENT */ /*{{{*/
|
||||
case LIDENT:
|
||||
{
|
||||
ident=n[*i];
|
||||
++(*i);
|
||||
return findlabel(upd_sheet,ident->u.lident);
|
||||
}
|
||||
/*}}}*/
|
||||
/* FIDENT */ /*{{{*/
|
||||
case FIDENT:
|
||||
{
|
||||
ident=n[*i];
|
||||
++(*i);
|
||||
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==OP)
|
||||
/* parse arguments and closing paren of function call, return its value */ /*{{{*/
|
||||
{
|
||||
++(*i);
|
||||
argc=0;
|
||||
if (!(n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP))
|
||||
/* parse at least one argument */ /*{{{*/
|
||||
{
|
||||
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA)
|
||||
/* empty argument */ /*{{{*/
|
||||
{
|
||||
argv[argc].type=EMPTY;
|
||||
}
|
||||
/*}}}*/
|
||||
else argv[argc]=term(n,i);
|
||||
if (argv[argc].type==EEK) return argv[argc];
|
||||
++argc;
|
||||
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA)
|
||||
/* parse the following argument */ /*{{{*/
|
||||
{
|
||||
++(*i);
|
||||
if (argc<=MAXARGC)
|
||||
{
|
||||
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==COMMA || n[*i]->u.op==CP))
|
||||
{
|
||||
argv[argc].type=EMPTY;
|
||||
}
|
||||
else argv[argc]=term(n,i);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_("too many arguments"))+1),_("too many arguments"));
|
||||
for (j=0; j<=argc; ++j) tfree(&argv[j]);
|
||||
return result;
|
||||
}
|
||||
++argc;
|
||||
}
|
||||
/*}}}*/
|
||||
}
|
||||
/*}}}*/
|
||||
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP)
|
||||
/* eval function */ /*{{{*/
|
||||
{
|
||||
++(*i);
|
||||
result=tfuncall(ident,argc,argv);
|
||||
for (j=0; j<argc; ++j) tfree(&argv[j]);
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
/* ) expected */ /*{{{*/
|
||||
{
|
||||
for (j=0; j<argc; ++j) tfree(&argv[j]);
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_(") expected"))+1),_(") expected"));
|
||||
}
|
||||
/*}}}*/
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
else
|
||||
{
|
||||
result.type=EEK;
|
||||
result.u.err=mystrmalloc(_("( expected"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
default: ; /* fall through */
|
||||
}
|
||||
result.type=EEK;
|
||||
result.u.err=mystrmalloc(_("value expected"));
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
/* powterm -- parse and evaluate a x^y term */ /*{{{*/
|
||||
static Token powterm(Token *n[], int *i)
|
||||
{
|
||||
Token l;
|
||||
|
||||
l=primary(n,i);
|
||||
if (l.type==EEK) return l;
|
||||
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==POW)
|
||||
{
|
||||
Token result,r;
|
||||
|
||||
++(*i);
|
||||
r=primary(n,i);
|
||||
result=tpow(l,r);
|
||||
tfree(&l);
|
||||
tfree(&r);
|
||||
if (result.type==EEK) return result;
|
||||
l=result;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
/*}}}*/
|
||||
/* piterm -- parse and evaluate a product/division/modulo term */ /*{{{*/
|
||||
static Token piterm(Token *n[], int *i)
|
||||
{
|
||||
Token l;
|
||||
|
||||
l=powterm(n,i);
|
||||
if (l.type==EEK) return l;
|
||||
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==DIV || n[*i]->u.op==MUL || n[*i]->u.op==MOD))
|
||||
{
|
||||
Operator op;
|
||||
Token result,r;
|
||||
|
||||
op=n[*i]->u.op;
|
||||
++(*i);
|
||||
r=powterm(n,i);
|
||||
switch (op)
|
||||
{
|
||||
case MUL: result=tmul(l,r); break;
|
||||
case DIV: result=tdiv(l,r); break;
|
||||
case MOD: result=tmod(l,r); break;
|
||||
default: assert(0);
|
||||
}
|
||||
tfree(&l);
|
||||
tfree(&r);
|
||||
if (result.type==EEK) return result;
|
||||
l=result;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
/*}}}*/
|
||||
/* factor -- parse and evaluate a factor of sums/differences */ /*{{{*/
|
||||
static Token factor(Token *n[], int *i)
|
||||
{
|
||||
Token l;
|
||||
|
||||
l=piterm(n,i);
|
||||
if (l.type==EEK) return l;
|
||||
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==PLUS || n[*i]->u.op==MINUS))
|
||||
{
|
||||
Operator op;
|
||||
Token result,r;
|
||||
|
||||
op=n[*i]->u.op;
|
||||
++(*i);
|
||||
r=piterm(n,i);
|
||||
result=(op==PLUS ? tadd(l,r) : tsub(l,r));
|
||||
tfree(&l);
|
||||
tfree(&r);
|
||||
if (result.type==EEK) return result;
|
||||
l=result;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
/*}}}*/
|
||||
/* term -- parse and evaluate a relational term */ /*{{{*/
|
||||
static Token term(Token *n[], int *i)
|
||||
{
|
||||
Token l;
|
||||
|
||||
l=factor(n,i);
|
||||
if (l.type==EEK) return l;
|
||||
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op>=LT && n[*i]->u.op<=NE)
|
||||
{
|
||||
Operator op;
|
||||
Token result,r;
|
||||
|
||||
op=n[*i]->u.op;
|
||||
++(*i);
|
||||
r=factor(n,i);
|
||||
switch (op)
|
||||
{
|
||||
case LT: result=tlt(l,r); break;
|
||||
case LE: result=tle(l,r); break;
|
||||
case GE: result=tge(l,r); break;
|
||||
case GT: result=tgt(l,r); break;
|
||||
case ISEQUAL: result=teq(l,r); break;
|
||||
case ABOUTEQ: result=tabouteq(l,r); break;
|
||||
case NE: result=tne(l,r); break;
|
||||
default: assert(0);
|
||||
}
|
||||
tfree(&l);
|
||||
tfree(&r);
|
||||
if (result.type==EEK) return result;
|
||||
l=result;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* eval -- parse and evaluate token sequence */ /*{{{*/
|
||||
Token eval(Token **n)
|
||||
{
|
||||
Token result;
|
||||
int i;
|
||||
|
||||
assert(upd_sheet!=(Sheet*)0);
|
||||
i=0;
|
||||
result=term(n,&i);
|
||||
if (result.type==EEK) return result;
|
||||
if (n[i]!=(Token*)0)
|
||||
{
|
||||
tfree(&result);
|
||||
result.type=EEK;
|
||||
result.u.err=strcpy(malloc(strlen(_("parse error after term"))+1),_("parse error after term"));
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* eval_safe -- like eval, but handles null pointer to token sequence */ /*{{{*/
|
||||
Token eval_safe(Token **n)
|
||||
{
|
||||
Token result;
|
||||
if (n == EMPTY_TVEC)
|
||||
{
|
||||
result.type = EMPTY;
|
||||
return result;
|
||||
}
|
||||
return eval(n);
|
||||
}
|
9
src/common/parser.h
Normal file
9
src/common/parser.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
Token eval_safe(Token **n); /* OK to call on null ptr */
|
||||
Token eval(Token *n[]); /* Don't call with null ptr */
|
||||
|
||||
#endif
|
329
src/common/sc.c
Normal file
329
src/common/sc.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "eval.h"
|
||||
#include "main.h"
|
||||
#include "sheet.h"
|
||||
#include "sc.h"
|
||||
/*}}}*/
|
||||
|
||||
static const char *s2t_s;
|
||||
static char *s2t_t;
|
||||
|
||||
static int s2t_term(Sheet *sheet);
|
||||
|
||||
/* s2t_loc */ /*{{{*/
|
||||
static int s2t_loc(Sheet *sheet, const char **s, char **t)
|
||||
{
|
||||
int x,y;
|
||||
Location tmp;
|
||||
char label[10],*l;
|
||||
|
||||
l=label;
|
||||
if (**s>='A' && **s<='Z')
|
||||
{
|
||||
*l++=**s;
|
||||
*(*t)++=**s;
|
||||
x=*(*s)++-'A';
|
||||
}
|
||||
else return 0;
|
||||
if (**s>='A' && **s<='Z')
|
||||
{
|
||||
*l++=**s;
|
||||
*(*t)++=**s;
|
||||
x=x*26+(*(*s)++-'A');
|
||||
}
|
||||
if (**s>='0' && **s<='9')
|
||||
{
|
||||
*l++=**s;
|
||||
y=**s-'0';
|
||||
*(*t)++=*(*s)++;
|
||||
}
|
||||
else return 0;
|
||||
while (**s>='0' && **s<='9')
|
||||
{
|
||||
*l++=**s;
|
||||
y=y*10+(**s-'0');
|
||||
*(*t)++=*(*s)++;
|
||||
}
|
||||
*l='\0';
|
||||
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
||||
if (*getlabel(CELL_AT(sheet, tmp))=='\0') setlabel(sheet, tmp, label, 0);
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
/* s2t_range */ /*{{{*/
|
||||
static int s2t_range(Sheet *sheet)
|
||||
{
|
||||
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||
if (*s2t_s==':')
|
||||
{
|
||||
s2t_s++; *s2t_t++=',';
|
||||
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
/* s2t_primary */ /*{{{*/
|
||||
static int s2t_primary(Sheet *sheet)
|
||||
{
|
||||
if (*s2t_s=='@')
|
||||
/* @function */ /*{{{*/
|
||||
{
|
||||
++s2t_s;
|
||||
if (strncmp(s2t_s,"sum(",4)==0)
|
||||
/* @sum(range) -> sum(range) */ /*{{{*/
|
||||
{
|
||||
s2t_s+=4;
|
||||
*s2t_t++='s'; *s2t_t++='u'; *s2t_t++='m'; *s2t_t++='(';
|
||||
if (s2t_range(sheet)==0) return 0;
|
||||
*s2t_t++=')';
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(s2t_s,"rnd(",4)==0)
|
||||
/* @rnd(e) -> int(e,-1,1) */ /*{{{*/
|
||||
{
|
||||
s2t_s+=4;
|
||||
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||
if (s2t_term(sheet)==0) return 0;
|
||||
*s2t_t++=','; *s2t_t++='-'; *s2t_t++='1'; *s2t_t++=','; *s2t_t++='1'; *s2t_t++=')';
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(s2t_s,"floor(",6)==0)
|
||||
/* @floor(e) -> int(e,-2,-2) */ /*{{{*/
|
||||
{
|
||||
s2t_s+=6;
|
||||
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||
if (s2t_term(sheet)==0) return 0;
|
||||
*s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=')';
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(s2t_s,"ceil(",5)==0)
|
||||
/* @ceil(e) -> int(e,2,2) */ /*{{{*/
|
||||
{
|
||||
s2t_s+=5;
|
||||
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||
if (s2t_term(sheet)==0) return 0;
|
||||
*s2t_t++=','; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='2'; *s2t_t++=')';
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
else if ((*s2t_s>='0' && *s2t_s<='9') || *s2t_s=='.')
|
||||
/* number */ /*{{{*/
|
||||
{
|
||||
if (*s2t_s=='.') *s2t_t++='0'; else *s2t_t++=*s2t_s++;
|
||||
while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++;
|
||||
if (*s2t_s=='.')
|
||||
{
|
||||
*s2t_t++=*s2t_s++;
|
||||
while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*s2t_t++='.'; *s2t_t++='0';
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (*s2t_s>='A' && *s2t_s<='Z')
|
||||
/* cell value */ /*{{{*/
|
||||
{
|
||||
*s2t_t++='@'; *s2t_t++='(';
|
||||
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||
*s2t_t++=')';
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (*s2t_s) return 0;
|
||||
else return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
/* s2t_powterm */ /*{{{*/
|
||||
static int s2t_powterm(Sheet *sheet)
|
||||
{
|
||||
if (s2t_primary(sheet)==0) return 0;
|
||||
while (*s2t_s=='^')
|
||||
{
|
||||
*s2t_t++=*s2t_s++;
|
||||
if (s2t_primary(sheet)==0) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
/* s2t_piterm */ /*{{{*/
|
||||
static int s2t_piterm(Sheet *sheet)
|
||||
{
|
||||
if (s2t_powterm(sheet)==0) return 0;
|
||||
while (*s2t_s=='*' || *s2t_s=='/')
|
||||
{
|
||||
*s2t_t++=*s2t_s++;
|
||||
if (s2t_powterm(sheet)==0) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
/* s2t_term */ /*{{{*/
|
||||
static int s2t_term(Sheet *sheet)
|
||||
{
|
||||
if (s2t_piterm(sheet)==0) return 0;
|
||||
while (*s2t_s=='+' || *s2t_s=='-')
|
||||
{
|
||||
*s2t_t++=*s2t_s++;
|
||||
if (s2t_piterm(sheet)==0) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* loadsc */ /*{{{*/
|
||||
const char *loadsc(Sheet *sheet, const char *name)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
static char errbuf[80];
|
||||
FILE *fp;
|
||||
char buf[256];
|
||||
int line;
|
||||
size_t width;
|
||||
const char *err;
|
||||
Cell *cell;
|
||||
Location tmp;
|
||||
int x,y;
|
||||
/*}}}*/
|
||||
|
||||
if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno);
|
||||
freesheet(sheet,0);
|
||||
err=(const char*)0;
|
||||
line=1;
|
||||
while (fgets(buf,sizeof(buf),fp)!=(char*)0)
|
||||
{
|
||||
/* remove nl */ /*{{{*/
|
||||
width=strlen(buf);
|
||||
if (width>0 && buf[width-1]=='\n') buf[width-1]='\0';
|
||||
/*}}}*/
|
||||
if (buf[0] && buf[0]!='#')
|
||||
{
|
||||
if (strncmp(buf,"format ",7)==0) /* format col width precision whoknows */ /*{{{*/
|
||||
{
|
||||
char colstr[3];
|
||||
int col,colwidth,precision,whoknows;
|
||||
|
||||
sscanf(buf+7,"%s %d %d %d",colstr,&colwidth,&precision,&whoknows);
|
||||
col=(colstr[0]-'A'); if (colstr[1]) col=col*26+(colstr[1]-'A');
|
||||
OLOCATION(tmp);
|
||||
tmp[X] = col;
|
||||
cell = initcell(sheet, tmp);
|
||||
cell->adjust = RIGHT;
|
||||
cell->precision = precision;
|
||||
setwidth(sheet, col, 0, colwidth);
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(buf,"leftstring ",11)==0 || strncmp(buf,"rightstring ",12)==0) /* rightstring/leftstring cell = "string" */ /*{{{*/
|
||||
{
|
||||
int x,y;
|
||||
const char *s;
|
||||
Token **contents;
|
||||
|
||||
if (strncmp(buf,"leftstring ",11)==0) s=buf+11; else s=buf+12;
|
||||
x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A');
|
||||
y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0');
|
||||
s+=3;
|
||||
contents=scan(&s);
|
||||
if (contents==(Token**)0)
|
||||
{
|
||||
tvecfree(contents);
|
||||
sprintf(errbuf,_("Expression syntax error in line %d"),line);
|
||||
err=errbuf;
|
||||
goto eek;
|
||||
}
|
||||
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
||||
cell = initcell(sheet, tmp);
|
||||
cell->adjust = strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
|
||||
cell->contents[BASE] = contents;
|
||||
}
|
||||
/*}}}*/
|
||||
else if (strncmp(buf,"let ",4)==0) /* let cell = expression */ /*{{{*/
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
const char *s;
|
||||
Token **contents;
|
||||
char newbuf[512];
|
||||
/*}}}*/
|
||||
|
||||
s=buf+4;
|
||||
x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A');
|
||||
y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0');
|
||||
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
||||
if (getcont(CELL_ATC(sheet,x,y,0),BASE)==(Token**)0)
|
||||
{
|
||||
s+=3;
|
||||
s2t_s=s; s2t_t=newbuf;
|
||||
if (s2t_term(sheet)==0)
|
||||
{
|
||||
*s2t_t='\0';
|
||||
if (err==(const char*)0)
|
||||
{
|
||||
sprintf(errbuf,_("Unimplemented SC feature in line %d"),line);
|
||||
err=errbuf;
|
||||
}
|
||||
}
|
||||
*s2t_t='\0';
|
||||
s=newbuf;
|
||||
contents=scan(&s);
|
||||
if (contents==(Token**)0)
|
||||
{
|
||||
tvecfree(contents);
|
||||
sprintf(errbuf,_("Expression syntax error in line %d"),line);
|
||||
err=errbuf;
|
||||
goto eek;
|
||||
}
|
||||
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
||||
cell = initcell(sheet, tmp);
|
||||
cell->adjust = RIGHT;
|
||||
cell->contents[BASE] = contents;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
}
|
||||
++line;
|
||||
}
|
||||
/* set precisions for each column */ /*{{{*/
|
||||
for (x=0; x<sheet->dimx; ++x)
|
||||
{
|
||||
int prec;
|
||||
|
||||
prec=getprecision(CELL_ATC(sheet,x,0,0))==def_precision ? 2 : getprecision(CELL_ATC(sheet,x,0,0));
|
||||
for (y=1; y<sheet->dimy; ++y) if (CELL_ATC(sheet,x,y,0)) CELL_ATC(sheet,x,y,0)->precision=prec;
|
||||
}
|
||||
/*}}}*/
|
||||
eek:
|
||||
if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno);
|
||||
sheet->changed=0;
|
||||
cachelabels(sheet);
|
||||
forceupdate(sheet);
|
||||
return err;
|
||||
}
|
||||
/*}}}*/
|
8
src/common/sc.h
Normal file
8
src/common/sc.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef SC_H
|
||||
#define SC_H
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
const char *loadsc(Sheet *sheet, const char *name);
|
||||
|
||||
#endif
|
416
src/common/scanner.c
Normal file
416
src/common/scanner.c
Normal file
|
@ -0,0 +1,416 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#ifndef NO_POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "default.h"
|
||||
#include "func.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
#include "utf8.h"
|
||||
#include "scanner.h"
|
||||
/*}}}*/
|
||||
|
||||
const char *Type_Name[] =
|
||||
{ [EMPTY] = "EMPTY", [STRING] = "STRING", [FLOAT] = "FLOAT", [INT] = "INT",
|
||||
[OPERATOR] = "OPERATOR", [LIDENT] = "LABEL", [FIDENT] = "FUNCTION",
|
||||
[LOCATION] = "LOCATION", [EEK] = "ERROR"
|
||||
};
|
||||
|
||||
/* identcode -- return number of identifier */ /*{{{*/
|
||||
int identcode(const char *s, size_t len)
|
||||
{
|
||||
Tfunc *p;
|
||||
int fident;
|
||||
|
||||
for (p=tfunc,fident=0; p->name[0]!='\0' && (len!=strlen(p->name) || strncmp(s,p->name,len)); ++p,++fident);
|
||||
if (p->name[0]=='\0') return -1;
|
||||
else return fident;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* loc_in_box -- returns true if test is in the box determined by b and c */
|
||||
bool loc_in_box(const Location test,
|
||||
const Location b, const Location c)
|
||||
{
|
||||
for (Dimensions dim = X; dim < HYPER; ++dim)
|
||||
{
|
||||
if (test[dim] < b[dim] && test[dim] < c[dim]) return false;
|
||||
if (test[dim] > b[dim] && test[dim] > c[dim]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* charstring -- match quoted string and return token */ /*{{{*/
|
||||
static Token *charstring(const char **s)
|
||||
{
|
||||
const char *r;
|
||||
|
||||
r=*s;
|
||||
if (**s=='"')
|
||||
{
|
||||
++(*s);
|
||||
while (**s!='\0' && **s!='"') if (**s=='\\' && *((*s)+1)!='\0') (*s)+=2; else ++(*s);
|
||||
if (**s=='\0') { *s=r; return 0; }
|
||||
else
|
||||
{
|
||||
Token *n;
|
||||
char *t;
|
||||
|
||||
++(*s);
|
||||
n=malloc(sizeof(Token));
|
||||
n->type=STRING;
|
||||
t=n->u.string=malloc((size_t)(*s-r));
|
||||
/* Clean string of quotes. This may waste a few bytes, so? */
|
||||
++r;
|
||||
while (r<(*s-1)) if (*r=='\\') { *t++=*(r+1); r+=2; } else *t++=*r++;
|
||||
*t='\0';
|
||||
return n;
|
||||
}
|
||||
}
|
||||
else return (Token*)0;
|
||||
}
|
||||
/*}}}*/
|
||||
/* integer -- match an unsigned integer and return token */ /*{{{*/
|
||||
static Token *integer(const char **s)
|
||||
{
|
||||
const char *r;
|
||||
long i;
|
||||
|
||||
r=*s;
|
||||
i=posnumber(r,s);
|
||||
if (*s!=r && **s!='.' && **s!='e')
|
||||
{
|
||||
Token *n;
|
||||
|
||||
n=malloc(sizeof(Token));
|
||||
n->type=INT;
|
||||
n->u.integer=i;
|
||||
return n;
|
||||
}
|
||||
else { *s=r; return (Token*)0; }
|
||||
}
|
||||
/*}}}*/
|
||||
/* flt -- match a floating point number */ /*{{{*/
|
||||
static Token *flt(const char **s)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
const char *t;
|
||||
char *end;
|
||||
Token *n;
|
||||
double x;
|
||||
/*}}}*/
|
||||
|
||||
t=*s;
|
||||
x=strtod(t,&end);
|
||||
*s = end;
|
||||
if (t!=*s && dblfinite(x)==(const char*)0)
|
||||
{
|
||||
n=malloc(sizeof(Token));
|
||||
n->type=FLOAT;
|
||||
n->u.flt=x;
|
||||
return n;
|
||||
}
|
||||
else
|
||||
{
|
||||
*s=t;
|
||||
return (Token*)0;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* op -- match an op and return token */ /*{{{*/
|
||||
static Token *op(const char **s)
|
||||
{
|
||||
Token *n;
|
||||
Operator op;
|
||||
|
||||
switch (**s)
|
||||
{
|
||||
case '+': op=PLUS; break;
|
||||
case '-': op=MINUS; break;
|
||||
case '*': op=MUL; break;
|
||||
case '/': op=DIV; break;
|
||||
case '%': op=MOD; break;
|
||||
case '(': op=OP; break;
|
||||
case ')': op=CP; break;
|
||||
case ',': op=COMMA; break;
|
||||
case '^': op=POW; break;
|
||||
case '<': if (*(*s+1)=='=') { ++(*s); op=LE; } else op=LT; break;
|
||||
case '>': if (*(*s+1)=='=') { ++(*s); op=GE; } else op=GT; break;
|
||||
case '=': if (*(*s+1)=='=') { ++(*s); op=ISEQUAL; } else return (Token*)0; break;
|
||||
case '~': if (*(*s+1)=='=') { ++(*s); op=ABOUTEQ; } else return (Token*)0; break;
|
||||
case '!': if (*(*s+1)=='=') { ++(*s); op=NE; } else return (Token*)0; break;
|
||||
default: return (Token*)0;
|
||||
}
|
||||
n=malloc(sizeof(Token));
|
||||
n->type=OPERATOR;
|
||||
n->u.op=op;
|
||||
++(*s);
|
||||
return n;
|
||||
}
|
||||
/*}}}*/
|
||||
/* ident -- match an identifier and return token */ /*{{{*/
|
||||
static Token *ident(const char **s)
|
||||
{
|
||||
const char *begin;
|
||||
Token *result;
|
||||
|
||||
if (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$')
|
||||
{
|
||||
int fident;
|
||||
|
||||
begin=*s; ++(*s);
|
||||
while (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$' || isdigit((int)**s)) ++(*s);
|
||||
result=malloc(sizeof(Token));
|
||||
if ((fident=identcode(begin,(size_t)(*s-begin)))==-1)
|
||||
{
|
||||
result->type=LIDENT;
|
||||
result->u.lident=malloc((size_t)(*s-begin+1));
|
||||
(void)strncpy(result->u.lident,begin,(size_t)(*s-begin));
|
||||
result->u.lident[*s-begin]='\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
result->type=FIDENT;
|
||||
result->u.fident=fident;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return (Token*)0;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* scan -- scan string into tokens */ /*{{{*/
|
||||
Token **scan(const char **s)
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
Token **na,*n;
|
||||
const char *r;
|
||||
int i,j;
|
||||
/*}}}*/
|
||||
|
||||
/* compute number of tokens */ /*{{{*/
|
||||
r=*s;
|
||||
while (*r==' ') ++r;
|
||||
for (i=0; *r!='\0'; ++i)
|
||||
{
|
||||
const char *or;
|
||||
|
||||
or=r;
|
||||
while (*r==' ') ++r;
|
||||
n=charstring(&r);
|
||||
if (n==(Token*)0) n=op(&r);
|
||||
if (n==(Token*)0) n=integer(&r);
|
||||
if (n==(Token*)0) n=flt(&r);
|
||||
if (n==(Token*)0) n=ident(&r);
|
||||
if (or==r) { *s=r; return (Token**)0; }
|
||||
}
|
||||
/*}}}*/
|
||||
/* allocate token space */ /*{{{*/
|
||||
na=malloc(sizeof(Token*)*(i+1));
|
||||
/*}}}*/
|
||||
/* store tokens */ /*{{{*/
|
||||
r=*s;
|
||||
while (*r==' ') ++r;
|
||||
for (j=0; j<i; ++j)
|
||||
{
|
||||
while (*r==' ') ++r;
|
||||
n=charstring(&r);
|
||||
if (n==(Token*)0) n=op(&r);
|
||||
if (n==(Token*)0) n=integer(&r);
|
||||
if (n==(Token*)0) n=flt(&r);
|
||||
if (n==(Token*)0) n=ident(&r);
|
||||
na[j]=n;
|
||||
}
|
||||
na[j]=(Token*)0;
|
||||
/*}}}*/
|
||||
return na;
|
||||
}
|
||||
/*}}}*/
|
||||
/* printtok -- print a single token, passed by address, although not changed */ /*{{{*/
|
||||
size_t printtok(char* dest, size_t size, size_t field_width,
|
||||
int quote_strings, int use_scientific,
|
||||
int precision, int verbose_error, Token *tok)
|
||||
{
|
||||
size_t cur;
|
||||
|
||||
if (debug_level > 2) {
|
||||
printf("..Entering printtok; bufsize %d, field_width %d, qs %d, us %d, prec %d, verr %d\n", size, field_width, quote_strings, use_scientific, precision, verbose_error);
|
||||
}
|
||||
cur = 0;
|
||||
if (tok != NULLTOKEN) switch (tok->type)
|
||||
{
|
||||
/* EMPTY */ /*{{{*/
|
||||
case EMPTY: if (size > 0) dest[cur++] = '\0'; break;
|
||||
/*}}}*/
|
||||
/* STRING */ /*{{{*/
|
||||
case STRING:
|
||||
{
|
||||
char *str = tok->u.string;
|
||||
|
||||
if (quote_strings && cur<size) dest[cur++] = '"';
|
||||
for (;cur<size && *str != '\0'; ++str)
|
||||
{
|
||||
if (quote_strings && (*str == '"' || *str=='\\')) dest[cur++] = '\\';
|
||||
if (cur<size) dest[cur++]=*str;
|
||||
}
|
||||
if (quote_strings && cur<size) dest[cur++] = '"';
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* INT */ /*{{{*/
|
||||
case INT:
|
||||
{
|
||||
char buf[20];
|
||||
size_t buflen;
|
||||
|
||||
buflen=sprintf(buf,"%ld",tok->u.integer);
|
||||
assert(buflen<sizeof(buf));
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=buflen;
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* FLOAT */ /*{{{*/
|
||||
case FLOAT:
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
char buf[1024],*p;
|
||||
size_t len;
|
||||
/*}}}*/
|
||||
|
||||
len=sprintf(buf, use_scientific ? "%.*e" : "%.*f",
|
||||
precision == -1 ? DBL_DIG-2 : precision,
|
||||
tok->u.flt);
|
||||
assert(len<sizeof(buf));
|
||||
if (!use_scientific && precision==-1)
|
||||
{
|
||||
p=&buf[len-1];
|
||||
while (p>buf && *p=='0' && *(p-1)!='.') { *p='\0'; --p; --len; }
|
||||
}
|
||||
p=buf+len;
|
||||
while (*--p==' ') { *p='\0'; --len; }
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=len;
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* OPERATOR */ /*{{{*/
|
||||
case OPERATOR:
|
||||
{
|
||||
static const char *ops[]={ "+", "-", "*", "/", "(", ")", ",", "<", "<=", ">=", ">", "==", "~=", "!=", "^", "%" };
|
||||
|
||||
if ((size-cur)>1)
|
||||
{
|
||||
dest[cur++]=*ops[tok->u.op];
|
||||
if (*(ops[tok->u.op]+1) && size>cur) dest[cur++]=*(ops[tok->u.op]+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* LIDENT */ /*{{{*/
|
||||
case LIDENT:
|
||||
{
|
||||
size_t identlen;
|
||||
|
||||
identlen=strlen(tok->u.lident);
|
||||
if ((cur+identlen+1)<=size) strcpy(dest+cur,tok->u.lident);
|
||||
else (void)strncpy(dest+cur,tok->u.lident,size-cur-1);
|
||||
cur+=identlen;
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* FIDENT */ /*{{{*/
|
||||
case FIDENT:
|
||||
{
|
||||
size_t identlen;
|
||||
if (debug_level > 2) {
|
||||
printf("...Found function [%s].\n", tfunc[tok->u.fident].name);
|
||||
}
|
||||
identlen=strlen(tfunc[tok->u.fident].name);
|
||||
if ((cur+identlen+1)<=size) strcpy(dest+cur,tfunc[tok->u.fident].name);
|
||||
else (void)strncpy(dest+cur,tfunc[tok->u.fident].name,size-cur-1);
|
||||
cur+=identlen;
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* LOCATION */ /*{{{*/
|
||||
case LOCATION:
|
||||
{
|
||||
char buf[60];
|
||||
|
||||
sprintf(buf,"&(%d,%d,%d)",tok->u.location[0],tok->u.location[1],tok->u.location[2]);
|
||||
(void)strncpy(dest+cur,buf,size-cur-1);
|
||||
cur+=strlen(buf);
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* EEK */ /*{{{*/
|
||||
case EEK:
|
||||
{
|
||||
size_t errlen;
|
||||
|
||||
(void)strncpy(dest+cur,_("ERROR"),size-cur-1);
|
||||
cur += strlen(_("ERROR"));
|
||||
if (verbose_error)
|
||||
{
|
||||
(void)strncpy(dest+cur, ": ", size-cur-1);
|
||||
cur += 2;
|
||||
errlen = strlen(tok->u.err);
|
||||
if ((cur+errlen+1) <= size) strcpy(dest+cur, tok->u.err);
|
||||
else (void)strncpy(dest+cur, tok->u.err, size-cur-1);
|
||||
cur += errlen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* default */ /*{{{*/
|
||||
default: assert(0);
|
||||
/*}}}*/
|
||||
}
|
||||
if (cur<size) dest[cur] = 0;
|
||||
else
|
||||
{
|
||||
dest[size-1] = 0;
|
||||
cur = size;
|
||||
}
|
||||
if (field_width && mbslen(dest) > field_width) {
|
||||
for (cur = 0; cur < field_width; ++cur) dest[cur] = '#';
|
||||
dest[cur] = 0;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
/*}}}*/
|
||||
/* print -- print token sequence */ /*{{{*/
|
||||
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n)
|
||||
{
|
||||
size_t cur;
|
||||
|
||||
cur=0;
|
||||
if (n != EMPTY_TVEC) for (; cur<size-1 && (*n) != NULLTOKEN; ++n)
|
||||
cur += printtok(s+cur, size-cur, 0, quote, scientific, precision, 0, *n);
|
||||
if (cur<size) s[cur] = 0;
|
||||
else s[size-1] = 0;
|
||||
if (chars && mbslen(s) > chars) {
|
||||
for (cur=0; cur < chars; ++cur) s[cur] = '#';
|
||||
s[cur] = 0;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
68
src/common/scanner.h
Normal file
68
src/common/scanner.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef SCANNER_H
|
||||
#define SCANNER_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
EMPTY
|
||||
#ifndef __cplusplus
|
||||
, STRING, FLOAT, INT, OPERATOR, LIDENT, FIDENT, LOCATION, EEK
|
||||
#endif
|
||||
} Type;
|
||||
|
||||
extern const char *Type_Name[];
|
||||
|
||||
typedef enum { PLUS, MINUS, MUL, DIV, OP, CP, COMMA, LT, LE, GE, GT, ISEQUAL, ABOUTEQ, NE, POW, MOD } Operator;
|
||||
|
||||
typedef int Location[3]; /* NOTE: Locations are passed by REFERENCE not value */
|
||||
/* I.e., to accapt a Location argument, declare the parameter to be of type
|
||||
const Location*
|
||||
*/
|
||||
|
||||
typedef enum { X=0, Y=1, Z=2, HYPER} Dimensions;
|
||||
|
||||
#define OLOCATION(loc) ((void)memset(loc, 0, sizeof(Location)))
|
||||
#define IN_OCTANT(loc) (loc[X]>=0 && loc[Y]>=0 && loc[Z]>=0)
|
||||
#define LOCATION_GETS(la,lb) ((void)memcpy(la, lb, sizeof(Location)))
|
||||
#define SAME_LOC(la,lb) (memcmp(la,lb,sizeof(Location))==0)
|
||||
#define LOCATION_SUB(la,lb) (la)[X]-=(lb)[X]; (la)[Y]-=(lb)[Y]; (la)[Z]-=(lb)[Z];
|
||||
|
||||
bool loc_in_box(const Location test,
|
||||
const Location b, const Location c);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Type type;
|
||||
union
|
||||
{
|
||||
char *string;
|
||||
double flt;
|
||||
long integer;
|
||||
Operator op;
|
||||
char *lident;
|
||||
int fident;
|
||||
Location location;
|
||||
char *err;
|
||||
} u;
|
||||
} Token;
|
||||
|
||||
#define NULLTOKEN ((Token*)0)
|
||||
#define EMPTY_TVEC ((Token**)0)
|
||||
|
||||
int identcode(const char *s, size_t len);
|
||||
Token **scan(const char **s);
|
||||
size_t printtok(char* dest, size_t size, size_t field_width,
|
||||
int quote_strings, int use_scientific,
|
||||
int precision, int verbose_error, Token *tok);
|
||||
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
2164
src/common/sheet.c
Normal file
2164
src/common/sheet.c
Normal file
File diff suppressed because it is too large
Load diff
164
src/common/sheet.h
Normal file
164
src/common/sheet.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
#ifndef SHEET_H
|
||||
#define SHEET_H
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum { LEFT=0, RIGHT=1, CENTER=2, AUTOADJUST=3 } Adjust;
|
||||
|
||||
typedef enum { IN_X, IN_Y, IN_Z } Direction;
|
||||
|
||||
/* must be a prime */
|
||||
#define LABEL_CACHE 29
|
||||
|
||||
#define ASCENDING 001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int sortkey; /* OR-ed value of the above constants */
|
||||
} Sortkey;
|
||||
|
||||
typedef enum { BASE=0, ITERATIVE=1, CONTINGENT=2 } ContentVariety;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Token **contents[CONTINGENT];
|
||||
char *label;
|
||||
Token value;
|
||||
Token resvalue;
|
||||
Adjust adjust;
|
||||
int precision;
|
||||
unsigned int updated:1;
|
||||
unsigned int shadowed:1;
|
||||
unsigned int scientific:1;
|
||||
unsigned int locked:1;
|
||||
unsigned int transparent:1;
|
||||
unsigned int ignored:1;
|
||||
unsigned int clock_t0:1;
|
||||
unsigned int clock_t1:1;
|
||||
unsigned int clock_t2:1;
|
||||
unsigned int bold:1;
|
||||
unsigned int underline:1;
|
||||
} Cell;
|
||||
|
||||
#define NULLCELL ((Cell*)0)
|
||||
|
||||
struct Label
|
||||
{
|
||||
const char *label;
|
||||
Location location;
|
||||
struct Label *next;
|
||||
};
|
||||
|
||||
typedef enum { MARK_CYCLE = 0, GET_MARK_CUR = 1, GET_MARK_ALL = 2,
|
||||
MARKING = 3, MARKED = 4, UNMARKED = 5 } MarkState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct Label *labelcache[LABEL_CACHE];
|
||||
Location cur;
|
||||
Location mark1, mark2;
|
||||
MarkState marking;
|
||||
int offx, offy;
|
||||
Cell **sheet;
|
||||
int *column;
|
||||
int dimx, dimy, dimz;
|
||||
int orix, oriy, maxx, maxy;
|
||||
int width;
|
||||
char *name;
|
||||
unsigned int changed:1;
|
||||
unsigned int moveonly:1;
|
||||
unsigned int clk:1;
|
||||
void *display;
|
||||
} Sheet;
|
||||
|
||||
#define LOC_WITHINC(s,x,y,z) (x<s->dimx && y<s->dimy && z<s->dimz)
|
||||
#define LOC_WITHIN(s,l) (LOC_WITHINC(s,l[X],l[Y],l[Z]))
|
||||
#define CELL_ATC(s,x,y,z) (*((s)->sheet + (z)*(s)->dimy*(s)->dimx + (y)*(s)->dimx +(x)))
|
||||
#define CELL_AT(s,l) (CELL_ATC(s,l[X],l[Y],l[Z]))
|
||||
#define CELL_IS_NULLC(s,x,y,z) (CELL_ATC(s,x,y,z) == NULLCELL)
|
||||
#define CELL_IS_NULL(s,l) (CELL_AT(s,l) == NULLCELL)
|
||||
#define CELL_IS_GOODC(s,x,y,z) (LOC_WITHINC(s,x,y,z) && !CELL_IS_NULLC(s,x,y,z))
|
||||
#define CELL_IS_GOOD(s,l) (LOC_WITHIN(s,l) && !CELL_IS_NULL(s,l))
|
||||
#define SHADOWEDC(s,x,y,z) (CELL_IS_GOODC(s,x,y,z) && CELL_ATC(s,x,y,z)->shadowed)
|
||||
#define SHADOWED(s,l) (CELL_IS_GOOD(s,l) && CELL_AT(s,l)->shadowed)
|
||||
#define ALL_COORDS_IN_SHEETC(s,x,y,z) x=0; x<(s)->dimx; ++x) for (y=0; y<(s)->dimy; ++y) for (z=0; z<(s)->dimz; ++z
|
||||
#define ALL_LOCS_IN_SHEET(s,l) l[Z]=0; l[Z]<(s)->dimz; ++(l[Z])) for (l[Y]=0; l[Y]<(s)->dimy; ++(l[Y])) for (l[X]=0; l[X]<(s)->dimx; ++(l[X])
|
||||
#define ALL_LOCS_IN_REGION(s,l) l[Z]=(s)->mark1[Z]; l[Z]<=(s)->mark2[Z]; ++(l[Z])) for (l[Y]=(s)->mark1[Y]; l[Y]<=(s)->mark2[Y]; ++(l[Y])) for (l[X]=(s)->mark1[X]; l[X]<=(s)->mark2[X]; ++(l[X])
|
||||
#define ALL_CELLS_IN_SHEET(s,i,c) i=0,c=*((s)->sheet); i<(s)->dimx*(s)->dimy*(s)->dimz; ++i, c=*((s)->sheet+i)
|
||||
|
||||
extern Sheet *upd_sheet;
|
||||
extern Location upd_l;
|
||||
extern int max_eval;
|
||||
|
||||
void initialize_sheet(Sheet *sheet);
|
||||
void resize(Sheet *sheet, int x, int y, int z);
|
||||
Cell *initcell(Sheet *sheet, const Location at);
|
||||
Cell *safe_cell_at(Sheet *sheet, const Location at);
|
||||
Cell *curcell(Sheet *sheet);
|
||||
void cachelabels(Sheet *sheet);
|
||||
void freesheet(Sheet *sheet, int all);
|
||||
void forceupdate(Sheet *sheet);
|
||||
MarkState getmarkstate(Sheet *sheet);
|
||||
void dump_current_cell(Sheet *sheet);
|
||||
void freecell(Sheet *sheet, const Location at);
|
||||
int columnwidth(Sheet *sheet, int x, int z);
|
||||
void setwidth(Sheet *sheet, int x, int z, int width);
|
||||
int cellwidth(Sheet *sheet, const Location at);
|
||||
void putcont(Sheet *sheet, const Location at, Token **t, ContentVariety v);
|
||||
Token **getcont(const Cell *cell, ContentVariety v);
|
||||
Token getvalue(Sheet *sheet, const Location at);
|
||||
void update(Sheet *sheet);
|
||||
char *geterror(Sheet *sheet, const Location at);
|
||||
void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, const Location at);
|
||||
Adjust getadjust(const Cell *cell);
|
||||
void setadjust(Sheet *sheet, const Location at, Adjust adjust);
|
||||
void shadow(Sheet *sheet, const Location at, int yep);
|
||||
int shadowed(const Cell *cell);
|
||||
void bold(Sheet *sheet, const Location at, int yep);
|
||||
int isbold(const Cell *cell);
|
||||
void underline(Sheet *sheet, const Location at, int yep);
|
||||
int underlined(const Cell *cell);
|
||||
void lockcell(Sheet *sheet, const Location at, int yep);
|
||||
int locked(const Cell *cell);
|
||||
int transparent(const Cell *cell);
|
||||
void maketrans(Sheet *sheet, const Location at, int yep);
|
||||
void igncell(Sheet *sheet, const Location at, int yep);
|
||||
int ignored(const Cell *cell);
|
||||
void clk(Sheet *sheet, const Location at);
|
||||
void setscientific(Sheet *sheet, const Location at, int yep);
|
||||
int getscientific(const Cell *cell);
|
||||
void setprecision(Sheet *sheet, const Location at, int precision);
|
||||
int getprecision(const Cell* cell);
|
||||
const char *getlabel(const Cell* cell);
|
||||
void setlabel(Sheet *sheet, const Location at, const char *buf, int update);
|
||||
Token findlabel(Sheet *sheet, const char *label);
|
||||
void relabel(Sheet* sheet, const Location at,
|
||||
const char *oldlabel, const char *newlabel);
|
||||
|
||||
const char *savexdr(Sheet *sheet, const char *name, unsigned int *count);
|
||||
const char *savetbl(Sheet *sheet, const char *name, int body, const Location beg, const Location end, unsigned int *count);
|
||||
const char *savetext(Sheet *sheet, const char *name, const Location beg, const Location end, unsigned int *count);
|
||||
const char *savecsv(Sheet *sheet, const char *name, char sep, const Location beg, const Location end, unsigned int *count);
|
||||
const char *saveport(Sheet *sheet, const char *name, unsigned int *count);
|
||||
const char *loadxdr(Sheet *sheet, const char *name);
|
||||
const char *loadport(Sheet *sheet, const char *name);
|
||||
const char *loadcsv(Sheet *sheet, const char *name);
|
||||
|
||||
void insertcube(Sheet *sheet, const Location beg, const Location end, Direction ins);
|
||||
void deletecube(Sheet *sheet, const Location beg, const Location end, Direction ins);
|
||||
void moveblock(Sheet *sheet, const Location beg, const Location end, const Location dest, int copy);
|
||||
const char *sortblock(Sheet *sheet, const Location beg, const Location end, Direction dir, Sortkey *sk, size_t sklen);
|
||||
void mirrorblock(Sheet *sheet, const Location beg, const Location end, Direction dir);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
70
src/common/utf8.c
Normal file
70
src/common/utf8.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
UTF-8 wrapper for teapot
|
||||
Copyright (C) 2010 Joerg Walter
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
|
||||
size_t mbslen(const char *s)
|
||||
{
|
||||
const unsigned char *str = (unsigned char *)s;
|
||||
size_t chars = 0;
|
||||
|
||||
while (*str) {
|
||||
chars++;
|
||||
if (is_mbchar(*str++)) while (is_mbcont(*str)) str++;
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
char *mbspos(const char *s, int ch)
|
||||
{
|
||||
const unsigned char *str = (unsigned char *)s;
|
||||
int chars = 0;
|
||||
|
||||
if (ch < 0) {
|
||||
while (chars > ch) {
|
||||
chars--;
|
||||
while (is_mbcont(*--str));
|
||||
}
|
||||
} else {
|
||||
while (chars < ch && *str) {
|
||||
chars++;
|
||||
if (is_mbchar(*str++)) while (is_mbcont(*str)) str++;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *)(void *)str;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
size_t mbslen(const char *str)
|
||||
{
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
char *mbspos(const char *str, int ch)
|
||||
{
|
||||
return (char *)(void *)(str+ch);
|
||||
}
|
||||
|
||||
#endif
|
64
src/common/utf8.h
Normal file
64
src/common/utf8.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
UTF-8 wrapper for teapot
|
||||
Copyright (C) 2010 Joerg Walter
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UTF8_H
|
||||
#define UTF8_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
size_t mbslen(const char *str);
|
||||
char *mbspos(const char *str, int ch);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
|
||||
#define UTF8SZ 4
|
||||
static inline int is_mbcont(unsigned char c)
|
||||
{
|
||||
return (c >= 0x80 && c < 0xc0);
|
||||
}
|
||||
|
||||
static inline int is_mbchar(unsigned char c)
|
||||
{
|
||||
return (c >= 0x80);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define UTF8SZ 1
|
||||
static inline int is_mbcont(unsigned char c)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_mbchar(unsigned char c)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1171
src/common/wk1.c
Normal file
1171
src/common/wk1.c
Normal file
File diff suppressed because it is too large
Load diff
8
src/common/wk1.h
Normal file
8
src/common/wk1.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef WK1_H
|
||||
#define WK1_H
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
const char *loadwk1(Sheet *sheet, const char *name);
|
||||
|
||||
#endif
|
211
src/common/xdr.c
Normal file
211
src/common/xdr.c
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* Notes */ /*{{{C}}}*//*{{{*/
|
||||
/*
|
||||
|
||||
xdr_enum() is unusable, because enum_t may have a different size than
|
||||
an enum. The construction
|
||||
|
||||
int_value=*enum_value;
|
||||
result=xdr_int(xdrs,&int_value);
|
||||
*enum_value=int_value;
|
||||
return result;
|
||||
|
||||
solves the problem and works for both encoding and decoding.
|
||||
Unfortunately, I could not yet find such a solution for a variable sized
|
||||
array terminated by a special element.
|
||||
|
||||
*/
|
||||
/*}}}*/
|
||||
/* #includes */ /*{{{*/
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sheet.h"
|
||||
#include "xdr.h"
|
||||
/*}}}*/
|
||||
|
||||
/* xdr_token */ /*{{{*/
|
||||
static bool_t xdr_token(XDR *xdrs, Token *t)
|
||||
{
|
||||
int x,result;
|
||||
|
||||
if (xdrs->x_op==XDR_DECODE) (void)memset(t,0,sizeof(Token));
|
||||
x=t->type;
|
||||
if (t->type==OPERATOR) x|=t->u.op<<8;
|
||||
result=xdr_int(xdrs,&x);
|
||||
if ((x&0xff)==OPERATOR) t->u.op=(x>>8)&0xff;
|
||||
t->type=x&0xff;
|
||||
if (result==0) return result;
|
||||
switch (t->type)
|
||||
{
|
||||
/* EMPTY */ /*{{{*/
|
||||
case EMPTY:
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
/* STRING */ /*{{{*/
|
||||
case STRING:
|
||||
{
|
||||
return xdr_wrapstring(xdrs,&(t->u.string));
|
||||
}
|
||||
/*}}}*/
|
||||
/* FLOAT */ /*{{{*/
|
||||
case FLOAT:
|
||||
{
|
||||
return xdr_double(xdrs,&(t->u.flt));
|
||||
}
|
||||
/*}}}*/
|
||||
/* INT */ /*{{{*/
|
||||
case INT:
|
||||
{
|
||||
return xdr_long(xdrs,&(t->u.integer));
|
||||
}
|
||||
/*}}}*/
|
||||
/* OPERATOR */ /*{{{*/
|
||||
case OPERATOR:
|
||||
{
|
||||
return 1; /* since op is encoded in type */
|
||||
}
|
||||
/*}}}*/
|
||||
/* LIDENT */ /*{{{*/
|
||||
case LIDENT:
|
||||
{
|
||||
return xdr_wrapstring(xdrs,&(t->u.lident));
|
||||
}
|
||||
/*}}}*/
|
||||
/* FIDENT */ /*{{{*/
|
||||
case FIDENT:
|
||||
{
|
||||
return xdr_int(xdrs,&(t->u.fident));
|
||||
}
|
||||
/*}}}*/
|
||||
/* LOCATION */ /*{{{*/
|
||||
case LOCATION:
|
||||
{
|
||||
return (xdr_int(xdrs,&(t->u.location[0])) && xdr_int(xdrs,&(t->u.location[1])) && xdr_int(xdrs,&(t->u.location[2])));
|
||||
}
|
||||
/*}}}*/
|
||||
/* EEK */ /*{{{*/
|
||||
case EEK:
|
||||
{
|
||||
return xdr_wrapstring(xdrs,&(t->u.err));
|
||||
}
|
||||
/*}}}*/
|
||||
/* default -- should not happen */ /*{{{*/
|
||||
default: assert(0);
|
||||
/*}}}*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
/* xdr_tokenptr */ /*{{{*/
|
||||
static bool_t xdr_tokenptr(XDR *xdrs, Token **t)
|
||||
{
|
||||
return xdr_pointer(xdrs,(char**)t,sizeof(Token),(xdrproc_t)xdr_token);
|
||||
}
|
||||
/*}}}*/
|
||||
/* xdr_tokenptrvec */ /*{{{*/
|
||||
static bool_t xdr_tokenptrvec(XDR *xdrs, Token ***t)
|
||||
{
|
||||
unsigned int len;
|
||||
int result;
|
||||
|
||||
assert(t!=(Token***)0);
|
||||
if (xdrs->x_op!=XDR_DECODE)
|
||||
{
|
||||
Token **run;
|
||||
|
||||
if (*t==(Token**)0) len=0;
|
||||
else for (len=1,run=*t; *run!=(Token*)0; ++len,++run);
|
||||
}
|
||||
result=xdr_array(xdrs,(char**)t,&len,65536,sizeof(Token*),(xdrproc_t)xdr_tokenptr);
|
||||
if (len==0) *t=(Token**)0;
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
/* xdr_mystring */ /*{{{*/
|
||||
static bool_t xdr_mystring(XDR *xdrs, char **str)
|
||||
{
|
||||
static struct xdr_discrim arms[3]=
|
||||
{
|
||||
{ 0, (xdrproc_t)xdr_void },
|
||||
{ 1, (xdrproc_t)xdr_wrapstring },
|
||||
{ -1, (xdrproc_t)0 }
|
||||
};
|
||||
enum_t x;
|
||||
int res;
|
||||
|
||||
x=(*str!=(char*)0);
|
||||
res=xdr_union(xdrs, &x, (char*)str, arms, (xdrproc_t)0);
|
||||
if (!x) *str=(char*)0;
|
||||
return res;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
/* Notes */ /*{{{*/
|
||||
/*
|
||||
|
||||
The saved sheet consists of three xdr_int()s which specify x, y and z
|
||||
position of the cell saved with xdr_cell(). Perhaps xdr_cell could be
|
||||
given those as parameters, which would be more correct concerning the
|
||||
purpose of the xdr_functions. Then again, reading the position may
|
||||
fail (eof), whereas after the position has been read, xdr_cell() must
|
||||
not fail when loading a sheet.
|
||||
|
||||
*/
|
||||
/*}}}*/
|
||||
/* xdr_cell */ /*{{{*/
|
||||
bool_t xdr_cell(XDR *xdrs, Cell *cell)
|
||||
{
|
||||
int result,x;
|
||||
|
||||
assert(cell!=(Cell*)0);
|
||||
if (!(xdr_tokenptrvec(xdrs, &(cell->contents[BASE]))
|
||||
&& xdr_tokenptrvec(xdrs, &(cell->contents[ITERATIVE])) /* && xdr_token(xdrs, &(cell->value)) */ ))
|
||||
return 0;
|
||||
if (xdr_mystring(xdrs, &(cell->label))==0) return 0;
|
||||
x=cell->adjust;
|
||||
result=xdr_int(xdrs, &x);
|
||||
cell->adjust=x;
|
||||
if (result==0) return 0;
|
||||
if (xdr_int(xdrs, &(cell->precision))==0) return 0;
|
||||
x=(cell->updated&1)|((cell->shadowed&1)<<1)|((cell->scientific&1)<<2)|((cell->locked&1)<<3)|((cell->transparent&1)<<4)|((cell->ignored&1)<<5)|((cell->bold&1)<<6)|((cell->underline&1)<<7);
|
||||
result=xdr_int(xdrs, &x);
|
||||
cell->updated=((x&(1))!=0);
|
||||
cell->shadowed=((x&(1<<1))!=0);
|
||||
cell->scientific=((x&(1<<2))!=0);
|
||||
cell->locked=((x&(1<<3))!=0);
|
||||
cell->transparent=((x&(1<<4))!=0);
|
||||
cell->ignored=((x&(1<<5))!=0);
|
||||
cell->bold=((x&(1<<6))!=0);
|
||||
cell->underline=((x&(1<<7))!=0);
|
||||
return result;
|
||||
}
|
||||
/*}}}*/
|
||||
/* xdr_column */ /*{{{*/
|
||||
bool_t xdr_column(XDR *xdrs, int *x, int *z, int *width)
|
||||
{
|
||||
return (xdr_int(xdrs, x) && xdr_int(xdrs, z) && xdr_int(xdrs, width));
|
||||
}
|
||||
/*}}}*/
|
||||
/* xdr_magic */ /*{{{*/
|
||||
#define MAGIC0 (('#'<<24)|('!'<<16)|('t'<<8)|'e')
|
||||
#define MAGIC1 (('a'<<24)|('p'<<16)|('o'<<8)|'t')
|
||||
#define MAGIC2 (('\n'<<24)|('x'<<16)|('d'<<8)|'r')
|
||||
|
||||
bool_t xdr_magic(XDR *xdrs)
|
||||
{
|
||||
long m0,m1,m2;
|
||||
|
||||
m0=MAGIC0;
|
||||
m1=MAGIC1;
|
||||
m2=MAGIC2;
|
||||
return (xdr_long(xdrs,&m0) && m0==MAGIC0 && xdr_long(xdrs,&m1) && m1==MAGIC1 && xdr_long(xdrs,&m2) && m2==MAGIC2);
|
||||
}
|
||||
/*}}}*/
|
20
src/common/xdr.h
Normal file
20
src/common/xdr.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef XDR_H
|
||||
#define XDR_H
|
||||
|
||||
/* Thanks to curses. */
|
||||
#if 0
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#include "sheet.h"
|
||||
|
||||
bool_t xdr_cell(XDR *xdrs, Cell *cell);
|
||||
bool_t xdr_column(XDR *xdrs, int *x, int *z, int *width);
|
||||
bool_t xdr_magic(XDR *xdrs);
|
||||
|
||||
#endif
|
55
src/complete.c
Normal file
55
src/complete.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "complete.h"
|
||||
|
||||
void completefile(char *file, char *pos, size_t size)
|
||||
{
|
||||
struct dirent *direntp;
|
||||
char *dir, *slash, *complete;
|
||||
char next;
|
||||
int required, atmost;
|
||||
DIR *dirp;
|
||||
|
||||
next = *pos;
|
||||
*pos = 0;
|
||||
|
||||
if (!(complete=strrchr(file,'/'))) {
|
||||
dir = strdup(".");
|
||||
complete = file;
|
||||
|
||||
} else {
|
||||
if (complete == file) {
|
||||
dir = strdup("/");
|
||||
} else {
|
||||
dir = strdup(file);
|
||||
dir[complete-file] = 0;
|
||||
}
|
||||
complete++;
|
||||
}
|
||||
required = strlen(complete);
|
||||
|
||||
if (!(dirp = opendir(dir))) {
|
||||
free(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((direntp = readdir(dirp))) {
|
||||
if ((direntp->d_name[0] != '.' || complete[0] == '.') && !strncmp(complete, direntp->d_name, required)) {
|
||||
if (!next && strlen(direntp->d_name) > required) {
|
||||
strncpy(pos, direntp->d_name+required, size-(pos-file));
|
||||
file[size-1] = 0;
|
||||
break;
|
||||
} else if (direntp->d_name[required] == next && !strcmp(pos+1, direntp->d_name+required+1)) {
|
||||
next = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
free(dir);
|
||||
}
|
6
src/complete.h
Normal file
6
src/complete.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef COMPLETE_H
|
||||
#define COMPLETE_H
|
||||
|
||||
void completefile(char *, char *, size_t size);
|
||||
|
||||
#endif
|
1145
src/display.c
Normal file
1145
src/display.c
Normal file
File diff suppressed because it is too large
Load diff
38
src/display.h
Normal file
38
src/display.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
#include "main.h"
|
||||
#include "sheet.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Key c;
|
||||
char *str;
|
||||
} MenuChoice;
|
||||
|
||||
void display_main(Sheet *cursheet);
|
||||
void display_init(Sheet *cursheet, int always_redraw);
|
||||
void display_end(void);
|
||||
void redraw_cell(Sheet *sheet, const Location at);
|
||||
void redraw_sheet(Sheet *sheet);
|
||||
const char *line_file(const char *file, const char *pattern, const char *title, int create);
|
||||
int line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx);
|
||||
int line_ok(const char *prompt, int curx);
|
||||
void line_msg(const char *prompt, const char *msg);
|
||||
int keypressed(void);
|
||||
void show_text(const char *text);
|
||||
|
||||
Key show_menu(Sheet *cursheet);
|
||||
int line_menu(const char *prompt, const MenuChoice *choice, int curx);
|
||||
void find_helpfile(char *buf, int size, const char *argv0);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
871
src/fteapot.fl
Normal file
871
src/fteapot.fl
Normal file
|
@ -0,0 +1,871 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0300
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
decl {\#include <unistd.h>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <stdint.h>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <limits.h>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <fcntl.h>} {private global
|
||||
}
|
||||
|
||||
decl {\#define shadow _shadow} {private global
|
||||
}
|
||||
|
||||
decl {\#define transparent _transparent} {private global
|
||||
}
|
||||
|
||||
decl {\#define MenuChoice _MenuChoice} {private global
|
||||
}
|
||||
|
||||
decl {\#define Cell _Cell} {private global
|
||||
}
|
||||
|
||||
decl {\#include <FL/fl_message.H>} {private local
|
||||
}
|
||||
|
||||
decl {\#include <FL/fl_draw.H>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_Native_File_Chooser.H>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_File_Icon.H>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <FL/filename.H>} {private global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_Table.H>} {public global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_Select_Browser.H>} {public global
|
||||
}
|
||||
|
||||
decl {\#include <FL/Fl_Sys_Menu_Bar.H>} {public global
|
||||
}
|
||||
|
||||
decl {\#undef shadow} {private global
|
||||
}
|
||||
|
||||
decl {\#undef transparent} {private global
|
||||
}
|
||||
|
||||
decl {\#undef MenuChoice} {private global
|
||||
}
|
||||
|
||||
decl {\#undef Cell} {private global
|
||||
}
|
||||
|
||||
decl {\#include "misc.h"} {private global
|
||||
}
|
||||
|
||||
decl {\#include "display.h"} {public global
|
||||
}
|
||||
|
||||
class TeapotTable {open : {public Fl_Table}
|
||||
} {
|
||||
decl {Sheet *cursheet;} {protected local
|
||||
}
|
||||
decl {bool cut, updating;} {protected local
|
||||
}
|
||||
decl {static const TableContext ACTION = (TableContext)(1<<8);} {public local
|
||||
}
|
||||
decl {static const TableContext REFRESH = (TableContext)(1<<9);} {public local
|
||||
}
|
||||
Function {TeapotTable(int x, int y, int w, int h, const char *l=0) : Fl_Table(x, y, w, h, l), cut(false), updating(false)} {open
|
||||
} {
|
||||
code {end();
|
||||
col_resize_min(10);
|
||||
col_resize(true);
|
||||
col_header(header);
|
||||
row_resize(false);
|
||||
row_header(header);
|
||||
set_visible_focus();
|
||||
table_box(FL_THIN_UP_FRAME);} {}
|
||||
}
|
||||
Function {~TeapotTable()} {} {
|
||||
code {} {}
|
||||
}
|
||||
Function {sheet(Sheet *s)} {open return_type void
|
||||
} {
|
||||
code {cursheet = s;
|
||||
s->display = (void *)this;
|
||||
clear();
|
||||
update_table();
|
||||
do_callback(CONTEXT_NONE, 0, 0);} {}
|
||||
}
|
||||
Function {sheet()} {return_type {Sheet *}
|
||||
} {
|
||||
code {return cursheet;} {}
|
||||
}
|
||||
Function {draw_cell(TableContext context, int R, int C, int xx, int yy, int W, int H)} {open return_type void
|
||||
} {
|
||||
code {char s[1024];
|
||||
//printf("DRAW: %i @%i,%i - (%i,%i) %ix%i\\n", context, C,R, xx,yy, W,H);
|
||||
switch (context) {
|
||||
case CONTEXT_ENDPAGE:
|
||||
W = xx-x()-2;
|
||||
H = yy-y()-2;
|
||||
xx = x()+2;
|
||||
yy = y()+2;
|
||||
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||
fl_push_clip(xx, yy, W, H);
|
||||
fl_draw_box(FL_DIAMOND_UP_BOX, xx, yy, W, H, col_header_color());
|
||||
fl_color(FL_INACTIVE_COLOR);
|
||||
sprintf(s, "%d", cursheet->cur[Z]);
|
||||
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
|
||||
fl_pop_clip();
|
||||
break;
|
||||
|
||||
case CONTEXT_STARTPAGE:
|
||||
adjust_outside();
|
||||
if (Fl::event_button1()) update_sheet();
|
||||
break;
|
||||
|
||||
case CONTEXT_COL_HEADER:
|
||||
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||
fl_push_clip(xx, yy, W, H);
|
||||
fl_draw_box(FL_THIN_UP_BOX, xx, yy, W, H, col_header_color());
|
||||
fl_color(FL_FOREGROUND_COLOR);
|
||||
sprintf(s, "%d", C);
|
||||
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
|
||||
fl_pop_clip();
|
||||
return;
|
||||
|
||||
case CONTEXT_ROW_HEADER:
|
||||
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||
fl_push_clip(xx, yy, W, H);
|
||||
fl_draw_box(FL_THIN_UP_BOX, xx, yy, W, H, row_header_color());
|
||||
fl_color(FL_FOREGROUND_COLOR);
|
||||
sprintf(s, "%d", R);
|
||||
fl_draw(s, xx, yy, W, H, FL_ALIGN_CENTER);
|
||||
fl_pop_clip();
|
||||
return;
|
||||
|
||||
case CONTEXT_CELL: {
|
||||
while (SHADOWEDC(cursheet, C, R, cursheet->cur[Z])) xx -= W = col_width(--C);
|
||||
int x = C+1;
|
||||
while (SHADOWEDC(cursheet,x,R,cursheet->cur[Z])) W += col_width(x), x++;
|
||||
|
||||
fl_push_clip(xx, yy, W, H);
|
||||
bool selected = false;
|
||||
MarkState ms = getmarkstate(cursheet);
|
||||
Location test;
|
||||
test[X] = C; test[Y] = R; test[Z] = cursheet->cur[Z];
|
||||
if (ms != UNMARKED)
|
||||
selected = loc_in_box(test, cursheet->mark1, cursheet->mark2);
|
||||
bool iscurrent = C == cursheet->cur[X] && R == cursheet->cur[Y];
|
||||
fl_draw_box(iscurrent ? FL_BORDER_BOX : FL_THIN_DOWN_BOX, xx, yy, W, H,
|
||||
selected ? FL_SELECTION_COLOR : FL_BACKGROUND2_COLOR);
|
||||
if (Fl::focus() == this && iscurrent)
|
||||
draw_focus(FL_BORDER_BOX, xx, yy, W, H);
|
||||
fl_pop_clip();
|
||||
|
||||
Cell *cell = safe_cell_at(cursheet, test);
|
||||
|
||||
fl_push_clip(xx+3, yy+3, W-6, H-6);
|
||||
fl_color(FL_FOREGROUND_COLOR);
|
||||
fl_font(FL_HELVETICA | (isbold(cell) ? FL_BOLD : 0), 14);
|
||||
|
||||
printvalue(s, sizeof(s), 0, 0, getscientific(cell),
|
||||
getprecision(cell), cursheet, test);
|
||||
|
||||
int ww = 0, hh = 0;
|
||||
fl_measure(s, ww, hh, 0);
|
||||
if (ww > W-6) for (int i = 0; s[i]; i++) s[i] = '\#';
|
||||
|
||||
int adj = getadjust(cell);
|
||||
fl_draw(s, xx+3, yy+3, W-6, H-6, adj == RIGHT?FL_ALIGN_RIGHT:adj == LEFT?FL_ALIGN_LEFT:FL_ALIGN_CENTER);
|
||||
if (underlined(cell)) fl_xyline(xx, yy+H-7, xx+W);
|
||||
fl_pop_clip();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}} {selected
|
||||
}
|
||||
}
|
||||
Function {update_table()} {open return_type void
|
||||
} {
|
||||
code {if (updating) return;
|
||||
|
||||
updating = true;
|
||||
//printf("update_table: %ix%i@%i,%i; %i[%i], %i[%i]\\n", cursheet->dimx, cursheet->dimy, cursheet->curx, cursheet->cury, cursheet->offx, cursheet->maxx, cursheet->offy, cursheet->maxy);
|
||||
|
||||
if (cursheet->dimx > cols()) cols(cursheet->dimx);
|
||||
if (cursheet->dimy > rows()) rows(cursheet->dimy);
|
||||
adjust_outside();
|
||||
|
||||
for (int x = 0; x < cursheet->dimx; x++) {
|
||||
int w = columnwidth(cursheet, x, cursheet->cur[Z])*10;
|
||||
if (col_width(x) != w) col_width(x, w);
|
||||
}
|
||||
col_position(cursheet->offx);
|
||||
row_position(cursheet->offy);
|
||||
set_selection(cursheet->cur[Y], cursheet->cur[X],
|
||||
cursheet->cur[Y], cursheet->cur[X]);
|
||||
move_cursor(0,0);
|
||||
updating = false;} {}
|
||||
}
|
||||
Function {update_sheet()} {return_type void
|
||||
} {
|
||||
code {int x1, x2, y1, y2;
|
||||
|
||||
if (updating) return;
|
||||
updating = true;
|
||||
|
||||
get_selection(y1, x1, y2, x2);
|
||||
if (x1 != x2 || y1 != y2) {
|
||||
cursheet->mark1[X] = x1;
|
||||
cursheet->mark1[Y] = y1;
|
||||
cursheet->mark2[X] = x2;
|
||||
cursheet->mark2[Y] = y2;
|
||||
cursheet->mark1[Z] = cursheet->mark2[Z] = cursheet->cur[Z];
|
||||
cursheet->marking = MARKED;
|
||||
}
|
||||
moveto(cursheet, current_col, current_row, -1);
|
||||
visible_cells(cursheet->offy, cursheet->maxy, cursheet->offx, cursheet->maxx);
|
||||
cursheet->maxx -= cursheet->offx;
|
||||
cursheet->maxy -= cursheet->offy;
|
||||
|
||||
if (is_interactive_resize()) {
|
||||
for (int C = 0; C < cursheet->dimx; C++) {
|
||||
int w = (col_width(C) + 5)/10;
|
||||
if (w != columnwidth(cursheet, C, cursheet->cur[Z]))
|
||||
setwidth(cursheet, C, cursheet->cur[Z], w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updating = false;
|
||||
//printf("update_sheet: %ix%i@%i,%i; %i[%i], %i[%i] (%i,%i)-(%i,%i)\\n", cols(), rows(), cursheet->curx, cursheet->cury, cursheet->offx, cursheet->maxx, cursheet->offy, cursheet->maxy, x1, y1, x2, y2);} {}
|
||||
}
|
||||
Function {handle(int event)} {open return_type int
|
||||
} {
|
||||
code {if (event == FL_KEYDOWN) {
|
||||
int ctrl = Fl::event_ctrl();
|
||||
int alt = Fl::event_alt();
|
||||
int shift = Fl::event_shift();
|
||||
Key k = (Key)Fl::event_key();
|
||||
|
||||
switch ((unsigned int)k) {
|
||||
case FL_Escape: k = K_INVALID; break;
|
||||
case FL_BackSpace: k = K_BACKSPACE; break;
|
||||
case FL_F+1: k = ctrl?K_ABOUT:K_HELP; break;
|
||||
case FL_F+8: k = ctrl?K_RECALC:K_CLOCK; break;
|
||||
case FL_F+9: k = ctrl?K_RECALC:K_CLOCK; break;
|
||||
case FL_F+10: k = (Key)'/'; break;
|
||||
case FL_Tab: if (shift) { k = K_CLOCK; break; }
|
||||
case FL_Enter:
|
||||
case FL_KP_Enter: k = alt?K_MENTER:K_ENTER; break;
|
||||
case 'c': if (ctrl) { do_mark(cursheet, GET_MARK_CUR); cut = false; k = K_NONE; } break;
|
||||
case 'v': if (ctrl) { do_mark(cursheet, MARKED);
|
||||
k = cut ? BLOCK_MOVE : BLOCK_COPY;
|
||||
}
|
||||
break;
|
||||
case 'x': if (ctrl) { do_mark(cursheet, GET_MARK_CUR); cut = true, k = K_NONE; } break;
|
||||
case 'r': if (ctrl) k = K_RECALC; break;
|
||||
case 'd': if (ctrl && shift && debug_level > 0) k = K_DUMPCELL; break;
|
||||
case FL_Insert: if (ctrl) { do_mark(cursheet, GET_MARK_CUR); cut = false; } k = !shift?K_NONE:cut?BLOCK_MOVE:BLOCK_COPY; break;
|
||||
case FL_Delete: if (shift) { do_mark(cursheet, GET_MARK_CUR); cut = true; } k = shift?K_NONE:BLOCK_CLEAR; break;
|
||||
case FL_Home: k = ctrl?K_FIRSTL:shift?K_FSHEET:K_HOME; break;
|
||||
case FL_End: k = ctrl?K_LASTL:shift?K_LSHEET:K_END; break;
|
||||
case FL_Up: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_PPAGE:K_UP; break;
|
||||
case FL_Down: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_NPAGE:K_DOWN; break;
|
||||
case FL_Right: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_FPAGE:K_RIGHT; break;
|
||||
case FL_Left: if (shift) do_mark(cursheet, MARKING); k = ctrl?K_BPAGE:K_LEFT; break;
|
||||
case FL_Page_Down: k = shift?K_NSHEET:ctrl?K_LASTL :K_NPAGE; break;
|
||||
case FL_Page_Up: k = shift?K_PSHEET:ctrl?K_FIRSTL:K_PPAGE; break;
|
||||
}
|
||||
|
||||
if (k > 0 && (ctrl || alt)) return 0;
|
||||
|
||||
// Quick and dirty upper-case fix, fails for international chars on keyboards...
|
||||
if (shift && !alt && !ctrl && k >= 'a' && k <= 'z') k = (Key)(k - 'a' + 'A');
|
||||
|
||||
do_sheetcmd(cursheet, k, cursheet->moveonly);
|
||||
do_callback(ACTION, 0, 0);
|
||||
redraw();
|
||||
} else if (event == FL_FOCUS) {
|
||||
do_callback(REFRESH, 0, 0);
|
||||
return 1;
|
||||
} else if (event == FL_PUSH) {
|
||||
int ex = Fl::event_x() - x(), ey = Fl::event_y() - y();
|
||||
if (ex >= row_header_width() || ey >= col_header_height()) {
|
||||
int rc = Fl_Table::handle(event);
|
||||
do_callback(ACTION, 0, 0);
|
||||
return rc;
|
||||
}
|
||||
if (ex < row_header_width()/2) relmoveto(cursheet, 0, 0, -1);
|
||||
else relmoveto(cursheet, 0, 0, 1);
|
||||
return 1;
|
||||
} else if (event != FL_KEYUP) {
|
||||
return Fl_Table::handle(event);
|
||||
}
|
||||
|
||||
return 1;} {}
|
||||
}
|
||||
Function {adjust_outside()} {open protected return_type void
|
||||
} {
|
||||
code {int x1, x2, y1, y2;
|
||||
|
||||
if (!cols() || !rows()) {
|
||||
cols(1);
|
||||
rows(1);
|
||||
}
|
||||
|
||||
visible_cells(y1, y2, x1, x2);
|
||||
//printf("adj: (%i,%i)-(%i,%i) %ix%i\\n", x1, y1, x2, y2, cols(), rows());
|
||||
if (x2+2 < cols() && cols() > cursheet->dimx) cols(x2+2 < cursheet->dimx?cursheet->dimx:x2+2);
|
||||
else if (x2+1 == cols()) {
|
||||
int xpos = col_scroll_position(cols());
|
||||
int w = col_width(cols()-1);
|
||||
x2 += (tow + hscrollbar->value() - xpos) / w + 2;
|
||||
//printf(" : t: %i, w: %i, p: %i, r: %i\\n", tow, w, xpos, x2+1);
|
||||
cols(x2+1);
|
||||
}
|
||||
|
||||
if (y2+2 < rows() && rows() > cursheet->dimy) rows(y2+2 < cursheet->dimy?cursheet->dimy:y2+2);
|
||||
else if (y2+1 == rows()) {
|
||||
int ypos = row_scroll_position(rows());
|
||||
int h = row_height(rows()-1);
|
||||
y2 += (toh + vscrollbar->value() - ypos) / h + 2;
|
||||
rows(y2+1);
|
||||
}} {}
|
||||
}
|
||||
}
|
||||
|
||||
class MainWindow {open
|
||||
} {
|
||||
decl {static MainWindow *current;} {protected local
|
||||
}
|
||||
decl {int edit_rc;} {private local
|
||||
}
|
||||
Function {MainWindow(Sheet *sheet)} {open
|
||||
} {
|
||||
Fl_Window window {
|
||||
label teapot
|
||||
callback {if (Fl::event_key(FL_Escape)) table->take_focus();
|
||||
else if (do_sheetcmd(table->sheet(), K_QUIT, 0) && doanyway(table->sheet(), _("Sheet modified, leave anyway?"))) {
|
||||
line_label->deactivate();
|
||||
window->hide();
|
||||
}} open
|
||||
protected xywh {866 342 800 600} type Double when 0 hide resizable
|
||||
} {
|
||||
Fl_Menu_Bar menu {
|
||||
callback {Sheet *sheet = table->sheet();
|
||||
Key action = (Key)(intptr_t)o->mvalue()->user_data();
|
||||
|
||||
if (do_sheetcmd(sheet, action, sheet->moveonly) && doanyway(sheet, _("Sheet modified, leave anyway?"))) {
|
||||
window->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
table->update_table();
|
||||
table->redraw();} open
|
||||
xywh {0 0 800 25}
|
||||
class Fl_Sys_Menu_Bar
|
||||
} {
|
||||
Submenu {} {
|
||||
label {&File}
|
||||
xywh {25 25 67 24}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {&Open...}
|
||||
user_data K_LOADMENU
|
||||
xywh {5 5 30 20} shortcut 0x4006f
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Save}
|
||||
user_data K_SAVE
|
||||
xywh {0 0 30 20} shortcut 0x40073
|
||||
}
|
||||
MenuItem {} {
|
||||
label {Save &As...}
|
||||
user_data K_NAME
|
||||
xywh {0 0 30 20} shortcut 0x50053 divider
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Quit}
|
||||
user_data K_QUIT
|
||||
xywh {0 0 30 20} shortcut 0x40071
|
||||
}
|
||||
}
|
||||
Submenu {} {
|
||||
label {&Block}
|
||||
xywh {25 25 67 24}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {&Insert}
|
||||
user_data BLOCK_INSERT
|
||||
xywh {0 0 30 20} shortcut 0x90069
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Delete}
|
||||
user_data BLOCK_DELETE
|
||||
xywh {0 0 30 20} shortcut 0x90064 divider
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Move}
|
||||
user_data BLOCK_MOVE
|
||||
xywh {0 0 30 20} shortcut 0x9006d
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Copy}
|
||||
user_data BLOCK_COPY
|
||||
xywh {0 0 36 21} shortcut 0x90063 divider
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Fill}
|
||||
user_data BLOCK_FILL
|
||||
xywh {0 0 36 21} shortcut 0x90066
|
||||
}
|
||||
MenuItem {} {
|
||||
label {C&lear}
|
||||
user_data BLOCK_CLEAR
|
||||
xywh {0 0 36 21} shortcut 0x9006c divider
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Sort}
|
||||
user_data BLOCK_SORT
|
||||
xywh {0 0 36 21} shortcut 0x90073
|
||||
}
|
||||
MenuItem {} {
|
||||
label {Mi&rror}
|
||||
user_data BLOCK_MIRROR
|
||||
xywh {0 0 36 21} shortcut 0x90072
|
||||
}
|
||||
}
|
||||
Submenu {} {
|
||||
label {&View}
|
||||
xywh {0 0 70 21}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {Column &Width...}
|
||||
user_data K_COLWIDTH
|
||||
xywh {0 0 36 21} shortcut 0x80077
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Goto}
|
||||
user_data K_GOTO
|
||||
xywh {0 0 36 21} shortcut 0x40067
|
||||
}
|
||||
}
|
||||
Submenu {} {
|
||||
label {F&ormat} open
|
||||
xywh {5 5 70 21}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {L&abel...}
|
||||
user_data ADJUST_LABEL
|
||||
xywh {0 0 36 21} shortcut 0x80061 divider
|
||||
}
|
||||
MenuItem bold {
|
||||
label {&Bold}
|
||||
user_data ADJUST_BOLD
|
||||
protected xywh {0 0 34 21} shortcut 0x80062
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem underline {
|
||||
label {&Underline}
|
||||
user_data ADJUST_UNDERLINE
|
||||
protected xywh {0 0 34 21} shortcut 0x80075 divider
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem left {
|
||||
label {&Left}
|
||||
user_data ADJUST_LEFT
|
||||
protected xywh {0 0 36 21} shortcut 0x8006c
|
||||
code0 {o->flags |= FL_MENU_RADIO;}
|
||||
}
|
||||
MenuItem right {
|
||||
label {&Right}
|
||||
user_data ADJUST_RIGHT
|
||||
protected xywh {0 0 36 21} shortcut 0x80072
|
||||
code0 {o->flags |= FL_MENU_RADIO;}
|
||||
}
|
||||
MenuItem center {
|
||||
label {&Center}
|
||||
user_data ADJUST_CENTER
|
||||
protected xywh {0 0 36 21} shortcut 0x80063 divider
|
||||
code0 {o->flags |= FL_MENU_RADIO;}
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&Precision...}
|
||||
user_data ADJUST_PRECISION
|
||||
xywh {0 0 36 21} shortcut 0x80070 divider
|
||||
}
|
||||
MenuItem sci {
|
||||
label {&Scientific}
|
||||
user_data ADJUST_SCIENTIFIC
|
||||
protected xywh {0 0 36 21} shortcut 0x80073
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem shadow {
|
||||
label {Shadow&ed}
|
||||
user_data ADJUST_SHADOW
|
||||
protected xywh {0 0 36 21} shortcut 0x80065
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem transparent {
|
||||
label {&Transparent}
|
||||
user_data ADJUST_TRANSPARENT
|
||||
protected xywh {0 0 36 21} shortcut 0x80074 divider
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem lock {
|
||||
label {Lo&ck}
|
||||
user_data ADJUST_LOCK
|
||||
protected xywh {0 0 36 21} shortcut 0x80063
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
MenuItem ignore {
|
||||
label {&Ignore}
|
||||
user_data ADJUST_IGNORE
|
||||
protected xywh {0 0 36 21} shortcut 0x80069
|
||||
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||
}
|
||||
}
|
||||
Submenu {} {
|
||||
label {&Help} open
|
||||
xywh {25 25 67 24}
|
||||
} {
|
||||
MenuItem {} {
|
||||
label {&Manual}
|
||||
user_data K_HELP
|
||||
xywh {0 0 30 20} shortcut 0xffbe
|
||||
}
|
||||
MenuItem {} {
|
||||
label {&About}
|
||||
user_data K_ABOUT
|
||||
xywh {0 0 30 20}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group line_label {
|
||||
label { Input:} open
|
||||
protected xywh {0 25 800 25} box ROUND_UP_BOX align 20 deactivate
|
||||
} {
|
||||
Fl_Input line_input {
|
||||
callback {bool enterkey = Fl::event_key(FL_Enter) || Fl::event_key(FL_KP_Enter);
|
||||
if (Fl::focus() && (Fl::focus() != table || enterkey || Fl::event_key(FL_Escape))) {
|
||||
if (enterkey) edit_rc = 0;
|
||||
line_label->deactivate();
|
||||
}}
|
||||
protected xywh {75 27 723 21} box ROUND_DOWN_BOX labeltype NO_LABEL align 20 when 6 deactivate
|
||||
}
|
||||
}
|
||||
Fl_Box table {
|
||||
callback {Sheet *sheet = table->sheet();
|
||||
table->update_sheet();
|
||||
|
||||
const char *label = getlabel(curcell(sheet));
|
||||
char moveonly=sheet->moveonly ? *_("V") : *_("E");
|
||||
|
||||
char buf[1024];
|
||||
if (*label == 0)
|
||||
snprintf(buf, sizeof(buf), "%c @@(%d,%d,%d)=", moveonly,
|
||||
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
|
||||
else snprintf(buf, sizeof(buf), "%c @@(%s)=", moveonly, label);
|
||||
|
||||
if (moveonly && table->callback_context() == TeapotTable::ACTION) {
|
||||
char valbuf[1024] = "";
|
||||
if (Fl::event_key() == 'p' || Fl::event_button1())
|
||||
sprintf(valbuf, "(%i,%i,%i)",
|
||||
sheet->cur[X], sheet->cur[Y], sheet->cur[Z]);
|
||||
else if (Fl::event_key() == 'v')
|
||||
printvalue(valbuf, sizeof(valbuf), 0, 1,
|
||||
getscientific(curcell(sheet)), -1, sheet, sheet->cur);
|
||||
else if (Fl::event_key(FL_Tab)) line_input->take_focus();
|
||||
if (valbuf[0]) {
|
||||
line_input->insert(valbuf);
|
||||
line_input->take_focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *err;
|
||||
char val[1024];
|
||||
if ((err = geterror(sheet, sheet->cur))) {
|
||||
strncpy(val,err,sizeof(val));
|
||||
free(err);
|
||||
val[sizeof(val)-1] = 0;
|
||||
} else {
|
||||
print(val, sizeof(val), 0, 1, getscientific(curcell(sheet)), -1,
|
||||
getcont(curcell(sheet), BASE));
|
||||
Token **iter = getcont(curcell(sheet), ITERATIVE);
|
||||
if (iter != EMPTY_TVEC) {
|
||||
snprintf(val+strlen(val),sizeof(val)-strlen(val)," -> ");
|
||||
print(val+strlen(val), sizeof(val)-strlen(val), 0, 1,
|
||||
getscientific(curcell(sheet)), -1, iter);
|
||||
}
|
||||
}
|
||||
|
||||
line_edit(sheet, val, 0, buf, 0, 0);
|
||||
Cell *cell = curcell(sheet);
|
||||
int adj = getadjust(cell);
|
||||
if (adj == LEFT) left->setonly();
|
||||
else if (adj == RIGHT) right->setonly();
|
||||
else if (adj == CENTER) center->setonly();
|
||||
if (SHADOWEDC(sheet, sheet->cur[X]+1, sheet->cur[Y], sheet->cur[Z]))
|
||||
shadow->set();
|
||||
else shadow->clear();
|
||||
if (::transparent(cell)) transparent->set();
|
||||
else transparent->clear();
|
||||
if (locked(cell)) lock->set();
|
||||
else lock->clear();
|
||||
if (ignored(cell)) ignore->set();
|
||||
else ignore->clear();
|
||||
if (isbold(cell)) bold->set();
|
||||
else bold->clear();
|
||||
if (underlined(cell)) underline->set();
|
||||
else underline->clear();
|
||||
if (getscientific(cell)) sci->set();
|
||||
else sci->clear();}
|
||||
protected xywh {0 50 800 525} box DOWN_FRAME labeltype NO_LABEL resizable
|
||||
code0 {table->sheet(sheet);}
|
||||
class TeapotTable
|
||||
}
|
||||
Fl_Box status {
|
||||
label {teapot ready.}
|
||||
protected xywh {0 575 800 25} box GTK_ROUND_DOWN_BOX align 20
|
||||
}
|
||||
}
|
||||
code {current = this;} {}
|
||||
}
|
||||
Function {line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx)} {open return_type int
|
||||
} {
|
||||
code {if (line_label->active()) {
|
||||
if (x) line_msg(NULL, "Action not possible at this time.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
line_label->copy_label(prompt);
|
||||
|
||||
int ww = 0, hh = 0;
|
||||
line_label->measure_label(ww, hh);
|
||||
line_input->resize(line_label->x()+ww+5, line_input->y(), line_label->w()-ww-7, line_input->h());
|
||||
line_input->value(buf);
|
||||
|
||||
if (!x) return 0;
|
||||
|
||||
line_input->maximum_size(size);
|
||||
line_input->position(*x, *x);
|
||||
line_label->activate();
|
||||
line_input->activate();
|
||||
table->sheet()->moveonly = 1;
|
||||
line_input->take_focus();
|
||||
|
||||
edit_rc = -1;
|
||||
while (line_label->active()) Fl::wait();
|
||||
|
||||
memcpy(buf, line_input->value(), size);
|
||||
line_input->deactivate();
|
||||
table->sheet()->moveonly = 0;
|
||||
table->take_focus();
|
||||
return edit_rc;} {}
|
||||
}
|
||||
Function {line_msg(const char *prompt, const char *msg)} {return_type void
|
||||
} {
|
||||
code {char label[1024];
|
||||
snprintf(label, sizeof(label), "%s%s%s", prompt?prompt:"", prompt?" ":"", msg);
|
||||
status->copy_label(label);} {}
|
||||
}
|
||||
decl {friend void line_msg(const char*, const char*);} {private local
|
||||
}
|
||||
}
|
||||
|
||||
Function {line_file(const char *file, const char *pattern, const char *title, int create)} {open C return_type {const char *}
|
||||
} {
|
||||
code {static char buf[PATH_MAX];
|
||||
Fl_Native_File_Chooser chooser;
|
||||
|
||||
chooser.title(title);
|
||||
chooser.type(create?Fl_Native_File_Chooser::BROWSE_SAVE_FILE:Fl_Native_File_Chooser::BROWSE_FILE);
|
||||
chooser.filter(pattern);
|
||||
chooser.options((create?Fl_Native_File_Chooser::NEW_FOLDER:0)|Fl_Native_File_Chooser::SAVEAS_CONFIRM);
|
||||
|
||||
if (file) {
|
||||
fl_filename_absolute(buf, sizeof(buf), file);
|
||||
char *p = (char *)fl_filename_name(buf);
|
||||
*p = 0;
|
||||
chooser.directory(buf);
|
||||
}
|
||||
if (chooser.show()) return NULL;
|
||||
|
||||
strncpy(buf, chooser.filename(), sizeof(buf));
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
return buf;} {}
|
||||
}
|
||||
|
||||
Function {line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx)} {C return_type int
|
||||
} {
|
||||
code {if (sheet) return ((MainWindow*)((TeapotTable*)sheet->display)->parent()->user_data())->line_edit(sheet, buf, size, prompt, x, offx);
|
||||
|
||||
const char *val = fl_input("%s", buf, prompt);
|
||||
if (val) {
|
||||
strncpy(buf, val, size);
|
||||
buf[size-1] = 0;
|
||||
}
|
||||
|
||||
return !val;} {}
|
||||
}
|
||||
|
||||
Function {line_ok(const char *prompt, int curx)} {C return_type int
|
||||
} {
|
||||
code {int rc = !!fl_choice("%s", "&No", NULL, "&Yes", prompt);
|
||||
if (Fl::event_key(FL_Escape)) return -1;
|
||||
return rc;} {}
|
||||
}
|
||||
|
||||
Function {line_msg(const char *prompt, const char *msg)} {C return_type void
|
||||
} {
|
||||
code {MainWindow::current->line_msg(prompt, msg);} {}
|
||||
}
|
||||
|
||||
Function {keypressed()} {open C return_type int
|
||||
} {
|
||||
code {while (Fl::wait(.01)) if (Fl::event_key(FL_Escape)) return 1;
|
||||
return 0;} {}
|
||||
}
|
||||
|
||||
Function {line_menu(const char *prompt, const MenuChoice *choice, int curx)} {C return_type int
|
||||
} {
|
||||
Fl_Window line_menu_menu {
|
||||
label {Please Choose} open
|
||||
xywh {706 58 250 245} type Double hide resizable modal
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Please Choose:} open
|
||||
xywh {0 0 250 200} box ENGRAVED_BOX align 21
|
||||
} {
|
||||
Fl_Browser line_menu_browser {
|
||||
callback {line_menu_menu->hide();}
|
||||
xywh {5 25 240 170}
|
||||
class Fl_Select_Browser
|
||||
}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Cancel
|
||||
callback {line_menu_menu->hide();}
|
||||
xywh {5 205 240 35}
|
||||
}
|
||||
}
|
||||
code {line_menu_browser->clear();
|
||||
while (choice->str) {
|
||||
line_menu_browser->add(choice->str+1);
|
||||
choice++;
|
||||
}
|
||||
|
||||
line_menu_menu->show();
|
||||
while (line_menu_menu->shown()) Fl::wait();
|
||||
|
||||
return line_menu_browser->value()-1;} {}
|
||||
}
|
||||
|
||||
Function {redraw_sheet(Sheet *sheet)} {C return_type void
|
||||
} {
|
||||
code {TeapotTable *t = (TeapotTable*)sheet->display;
|
||||
t->update_table();
|
||||
t->redraw();} {}
|
||||
}
|
||||
|
||||
Function {redraw_cell(Sheet *sheet, const Location /* at */)} {C return_type void
|
||||
} {
|
||||
code {redraw_sheet(sheet);} {}
|
||||
}
|
||||
|
||||
Function {display_init(Sheet *sheet, int always_redraw)} {open C return_type void
|
||||
} {
|
||||
code {Fl::get_system_colors();
|
||||
\#ifdef ENABLE_HELP
|
||||
Fl_File_Icon::load_system_icons();
|
||||
\#endif
|
||||
Fl::scheme("gtk+");
|
||||
int ch = sheet->changed;
|
||||
resize(sheet, 1, 1, 1);
|
||||
sheet->changed = ch;
|
||||
new MainWindow(sheet);} {}
|
||||
}
|
||||
|
||||
Function {display_end()} {C return_type void
|
||||
} {
|
||||
code {} {}
|
||||
}
|
||||
|
||||
Function {display_main(Sheet *cursheet)} {C return_type void
|
||||
} {
|
||||
code {((TeapotTable *)cursheet->display)->parent()->show();
|
||||
Fl::run();} {}
|
||||
}
|
||||
|
||||
Function {show_menu(Sheet *sheet)} {C return_type Key
|
||||
} {
|
||||
code {return K_NONE;} {}
|
||||
}
|
||||
|
||||
decl {MainWindow *MainWindow::current;} {private global
|
||||
}
|
||||
|
||||
declblock {\#ifdef ENABLE_HELP} {after {\#endif}
|
||||
} {
|
||||
decl {\#include <FL/Fl_Help_Dialog.H>} {private global
|
||||
}
|
||||
Function {show_text(const char *text)} {open C return_type void
|
||||
} {
|
||||
code {Fl_Help_Dialog *d = new Fl_Help_Dialog();
|
||||
if (strchr(text, '<')) {
|
||||
d->value(text);
|
||||
} else {
|
||||
d->load(text);
|
||||
}
|
||||
d->resize(d->x(), d->y(), d->w()*3/2, d->h()*3/2);
|
||||
d->show();} {}
|
||||
}
|
||||
}
|
||||
|
||||
declblock {\#ifndef ENABLE_HELP} {after {\#endif}
|
||||
} {
|
||||
Function {show_text(const char *text)} {open C return_type void
|
||||
} {
|
||||
code {char *txt = striphtml(text);
|
||||
fl_message("%s", txt);
|
||||
free(txt);} {}
|
||||
}
|
||||
}
|
||||
|
||||
Function {find_helpfile(char *buf, int size, const char *argv0)} {open C return_type void
|
||||
} {
|
||||
code {fl_filename_absolute(buf, size, argv0);
|
||||
char *p = (char *)fl_filename_name(buf);
|
||||
strncpy(p, "../share/doc/teapot/html/index.html", buf+size-p);
|
||||
buf[size-1] = 0;
|
||||
|
||||
// Check if help exists in default installed location, fallback value is valid for build directory
|
||||
int test = open(buf, O_RDONLY);
|
||||
if (test < 0) strncpy(p, "html/index.html", buf+size-p);
|
||||
else close(test);
|
||||
buf[size-1] = 0;
|
||||
|
||||
// Try the configure-time determined value
|
||||
test = open(buf, O_RDONLY);
|
||||
if (test < 0) strncpy(buf, HELPFILE, size);
|
||||
else close(test);
|
||||
buf[size-1] = 0;
|
||||
|
||||
// Fall back to a sane value for unixoid systems
|
||||
test = open(buf, O_RDONLY);
|
||||
if (test < 0) strncpy(buf, "/usr/share/doc/teapot/html/index.html", size);
|
||||
else close(test);
|
||||
buf[size-1] = 0;
|
||||
|
||||
} {}
|
||||
}
|
247
src/graph.c
Normal file
247
src/graph.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||
#undef _POSIX_SOURCE
|
||||
#define _POSIX_SOURCE 1
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 2
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||
#ifdef OLD_REALLOC
|
||||
#define realloc(s,l) myrealloc(s,l)
|
||||
#endif
|
||||
extern char *optarg;
|
||||
extern int optind,opterr,optopt;
|
||||
int getopt(int argc, char * const *argv, const char *optstring);
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#include "csv.h"
|
||||
/*}}}*/
|
||||
|
||||
int main(int argc, char *argv[]) /*{{{*/
|
||||
{
|
||||
/* variables */ /*{{{*/
|
||||
struct Pair
|
||||
{
|
||||
const char *label;
|
||||
double value;
|
||||
int special;
|
||||
} *pair;
|
||||
int pairs;
|
||||
double height,width;
|
||||
int box;
|
||||
int nl;
|
||||
/*}}}*/
|
||||
|
||||
/* parse options */ /*{{{*/
|
||||
{
|
||||
int c;
|
||||
height=width=2.0;
|
||||
box=0;
|
||||
nl=1;
|
||||
while ((c=getopt(argc,argv,"bnw:h:?"))!=EOF) switch (c)
|
||||
{
|
||||
/* w width */ /*{{{*/
|
||||
case 'w':
|
||||
{
|
||||
char *end;
|
||||
|
||||
width=strtod(optarg,&end);
|
||||
if (*end!='\0')
|
||||
{
|
||||
fprintf(stderr,"graph: invalid width\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* h height */ /*{{{*/
|
||||
case 'h':
|
||||
{
|
||||
char *end;
|
||||
|
||||
height=strtod(optarg,&end);
|
||||
if (*end!='\0')
|
||||
{
|
||||
fprintf(stderr,"graph: invalid height\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*}}}*/
|
||||
/* n */
|
||||
case 'n':
|
||||
{
|
||||
nl=0;
|
||||
break;
|
||||
}
|
||||
/* b */
|
||||
case 'b':
|
||||
{
|
||||
box=1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fprintf(stderr,"Usage: graph [-b][-h height][-w width]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
/* get data */ /*{{{*/
|
||||
{
|
||||
char ln[256];
|
||||
int line,pairsz;
|
||||
|
||||
pairs=pairsz=0;
|
||||
pair=(struct Pair*)0;
|
||||
for (line=1; fgets(ln,sizeof(ln),stdin); ++line)
|
||||
{
|
||||
const char *s;
|
||||
const char *end;
|
||||
|
||||
if (pairs==pairsz)
|
||||
{
|
||||
if ((pair=realloc(pair,sizeof(struct Pair)*(pairsz+=128)))==(struct Pair*)0)
|
||||
{
|
||||
fprintf(stderr,"graph:%d:out of memory\n",line);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
s=ln;
|
||||
pair[pairs].label=csv_string(s,&end);
|
||||
if (s==end) fprintf(stderr,"graph:%d:invalid string, ignoring record\n",line);
|
||||
else
|
||||
{
|
||||
s=end;
|
||||
pair[pairs].value=csv_double(s,&end);
|
||||
if (s==end) fprintf(stderr,"graph:%d:invalid value, ignoring record\n",line);
|
||||
else
|
||||
{
|
||||
s=end;
|
||||
pair[pairs].special=csv_double(s,&end);
|
||||
if (s==end && *s!='\n') fprintf(stderr,"graph:%d:invalid mark value, ignoringrecord\n",line);
|
||||
else
|
||||
{
|
||||
s=end;
|
||||
if (*s!='\n') fprintf(stderr,"graph:%d:trailing garbage\n",line);
|
||||
}
|
||||
++pairs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
if (box) /* make box graph */ /*{{{*/
|
||||
{
|
||||
double height,boxwid,min,max,scale;
|
||||
int i;
|
||||
|
||||
height=2;
|
||||
boxwid=width/pairs;
|
||||
for (min=max=0.0,i=0; i<pairs; ++i)
|
||||
{
|
||||
if (pair[i].value<min) min=pair[i].value;
|
||||
else if (pair[i].value>max) max=pair[i].value;
|
||||
}
|
||||
scale=height/(max-min);
|
||||
printf("[\nFRAME: box invis wid %f ht %f\n",width,height);
|
||||
for (i=0; i<pairs; ++i)
|
||||
{
|
||||
double v;
|
||||
|
||||
v=fabs(pair[i].value);
|
||||
printf
|
||||
(
|
||||
"box wid %f ht %f with .%s at FRAME.sw + (%f,%f) \"%s\"\n",
|
||||
boxwid,
|
||||
v*scale,
|
||||
pair[i].value>0 ? "sw" : "nw",
|
||||
i*boxwid,
|
||||
-min*scale,
|
||||
pair[i].label
|
||||
);
|
||||
}
|
||||
printf("]"); if (nl) printf("\n");
|
||||
}
|
||||
/*}}}*/
|
||||
else /* make pie graph */ /*{{{*/
|
||||
{
|
||||
int anyspecial,i;
|
||||
double sum,scale,extra,arc;
|
||||
|
||||
for (sum=0.0,i=0,anyspecial=0; i<pairs; ++i)
|
||||
{
|
||||
sum+=pair[i].value;
|
||||
if (pair[i].special) anyspecial=1;
|
||||
}
|
||||
scale=2.0*M_PI/sum;
|
||||
printf("[\n");
|
||||
printf("box invis wid %f ht %f\n",width,width);
|
||||
if (anyspecial) width-=width/10.0;
|
||||
for (sum=0,i=0; i<pairs; sum+=pair[i].value,++i)
|
||||
{
|
||||
extra=(pair[i].special!=0)*width/20.0;
|
||||
for (arc=0; (arc+M_PI_4)<(pair[i].value*scale); arc+=M_PI_4)
|
||||
{
|
||||
printf
|
||||
(
|
||||
"arc from last box.c + (%f,%f) to last box.c + (%f,%f) rad %f\n",
|
||||
cos((sum+arc)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+arc)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
cos((sum+arc+M_PI_4)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+arc+M_PI_4)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
width/2.0
|
||||
);
|
||||
}
|
||||
printf
|
||||
(
|
||||
"arc from last box.c + (%f,%f) to last box.c + (%f,%f) rad %f\n",
|
||||
cos((sum+arc)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+arc)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
cos((sum+pair[i].value)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+pair[i].value)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
width/2.0
|
||||
);
|
||||
|
||||
printf
|
||||
(
|
||||
"line from last box.c + (%f,%f) to last box.c + (%f,%f)\n",
|
||||
cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
cos(sum*scale)*width/2.0+cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin(sum*scale)*width/2.0+sin((sum+pair[i].value/2.0)*scale)*extra
|
||||
);
|
||||
|
||||
printf
|
||||
(
|
||||
"line from last box.c + (%f,%f) to last box.c + (%f,%f)\n",
|
||||
cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||
cos((sum+pair[i].value)*scale)*width/2.0+cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||
sin((sum+pair[i].value)*scale)*width/2.0+sin((sum+pair[i].value/2.0)*scale)*extra
|
||||
);
|
||||
|
||||
printf
|
||||
(
|
||||
"\"%s\" at last box.c + (%f,%f)\n",
|
||||
pair[i].label,
|
||||
cos((sum+pair[i].value/2.0)*scale)*width*0.35,
|
||||
sin((sum+pair[i].value/2.0)*scale)*width*0.35
|
||||
);
|
||||
}
|
||||
printf("]"); if (nl) printf("\n");
|
||||
}
|
||||
/*}}}*/
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
Loading…
Add table
Add a link
Reference in a new issue