1 /* #includes */ /*{{{C}}}*//*{{{*/
2 #ifndef NO_POSIX_SOURCE
3 #undef _POSIX_SOURCE
4 #define _POSIX_SOURCE 1
5 #undef _POSIX_C_SOURCE
6 #define _POSIX_C_SOURCE 2
7 #undef _XOPEN_SOURCE
8 #define _XOPEN_SOURCE 500
9 #endif
10
11 #ifdef DMALLOC
12 #include "dmalloc.h"
13 #endif
14
15 #include <assert.h>
16 #include <ctype.h>
17 #include <float.h>
18 #include <limits.h>
19 #include <locale.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 extern char *optarg;
24 extern int optind,opterr,optopt;
25 int getopt(int argc, char * const *argv, const char *optstring);
26 #include <string.h>
27 #include <unistd.h>
28
29
30 #include "default.h"
31 #include "display.h"
32 #include "eval.h"
33 #include "htmlio.h"
34 #include "latex.h"
35 #include "context.h"
36 #include "main.h"
37 #include "misc.h"
38 #include "sc.h"
39 #include "scanner.h"
40 #include "utf8.h"
41 #include "parser.h"
42 #include "sheet.h"
43 #include "wk1.h"
44 /*}}}*/
45
46 /* variables */ /*{{{*/
47 char helpfile[PATH_MAX];
48 int batch=0;
49 unsigned int batchln=0;
50 int def_precision=DEF_PRECISION;
51 int quote=0;
52 int header=1;
53 static int usexdr=1;
54 /*}}}*/
55
get_mark(Sheet * sheet,int * x1,int * x2,int * y1,int * y2,int * z1,int * z2,int everything)56 static void get_mark(Sheet *sheet, int *x1, int *x2, int *y1, int *y2, int *z1, int *z2, int everything)
57 {
58 if (sheet->marking) {
59 posorder(&sheet->mark1x, &sheet->mark2x);
60 posorder(&sheet->mark1y, &sheet->mark2y);
61 posorder(&sheet->mark1z, &sheet->mark2z);
62 sheet->marking = 0;
63 }
64 if (x1) {
65 if (sheet->mark1x >= 0) {
66 *x1 = sheet->mark1x;
67 *x2 = sheet->mark2x;
68 *y1 = sheet->mark1y;
69 *y2 = sheet->mark2y;
70 *z1 = sheet->mark1z;
71 *z2 = sheet->mark2z;
72 } else if (everything) {
73 *x1 = 0;
74 *x2 = sheet->dimx-1;
75 *y1 = 0;
76 *y2 = sheet->dimy-1;
77 *z1 = 0;
78 *z2 = sheet->dimz-1;
79 } else {
80 *x1 = *x2 = sheet->curx;
81 *y1 = *y2 = sheet->cury;
82 *z1 = *z2 = sheet->curz;
83 }
84 }
85 }
86
moveto(Sheet * sheet,int x,int y,int z)87 void moveto(Sheet *sheet, int x, int y, int z)
88 {
89 int need_redraw = 0;
90 int xdir = x > sheet->curx?1:-1;
91
92 if (x >= 0) sheet->curx = x;
93 if (y >= 0) sheet->cury = y;
94 if (z >= 0) need_redraw++, sheet->curz = z;
95 while (sheet->curx > 0 && shadowed(sheet, sheet->curx, sheet->cury, sheet->curz)) sheet->curx += xdir;
96
97 if (sheet->marking) {
98 sheet->mark2x = sheet->curx;
99 sheet->mark2y = sheet->cury;
100 sheet->mark2z = sheet->curz;
101 }
102
103 if (sheet->curx <= sheet->offx && sheet->offx) need_redraw++, sheet->offx = (sheet->curx?sheet->curx-1:0);
104 if (sheet->cury <= sheet->offy && sheet->offy) need_redraw++, sheet->offy = (sheet->cury?sheet->cury-1:0);
105 if (sheet->curx >= sheet->offx+sheet->maxx) need_redraw++, sheet->offx = sheet->curx-sheet->maxx+2;
106 if (sheet->cury >= sheet->offy+sheet->maxy) need_redraw++, sheet->offy = sheet->cury-sheet->maxy+2;
107
108 if (need_redraw) redraw_sheet(sheet);
109 else if (x != sheet->curx || y != sheet->cury || z != sheet->curz) redraw_cell(sheet, sheet->curx, sheet->cury, sheet->curz);
110 }
111
relmoveto(Sheet * sheet,int x,int y,int z)112 void relmoveto(Sheet *sheet, int x, int y, int z)
113 {
114 moveto(sheet, sheet->curx+x, sheet->cury+y, (z?sheet->curz+z:-1));
115 }
116
117 /* line_numedit -- number line editor function */ /*{{{*/
line_numedit(int * n,const char * prompt,size_t * x,size_t * offx)118 static int line_numedit(int *n, const char *prompt, size_t *x, size_t *offx)
119 {
120 /* variables */ /*{{{*/
121 char buf[20];
122 const char *s;
123 Token **t;
124 int c;
125 /*}}}*/
126
127 /* asserts */ /*{{{*/
128 assert(prompt!=(char*)0);
129 assert(x!=(size_t*)0);
130 assert(offx!=(size_t*)0);
131 /*}}}*/
132 t=(Token**)0;
133 sprintf(buf,"%d",*n);
134 s=buf+strlen(buf);
135 do
136 {
137 tvecfree(t);
138 *x=s-buf;
139 if ((c=line_edit((Sheet*)0,buf,sizeof(buf),prompt,x,offx))<0) return c;
140 s=buf;
141 t=scan(&s);
142 } while ((*s!='\0' && t==(Token**)0) || !(t!=(Token**)0 && ((*t)==(Token*)0 || ((*t)->type==INT && (*t)->u.integer>=0 && *(t+1)==(Token*)0))));
143 if (t==(Token**)0 || *t==(Token*)0) *n=-1;
144 else *n=(*t)->u.integer;
145 tvecfree(t);
146 return 0;
147 }
148 /*}}}*/
149 /* line_lidedit -- label identifier line editor function */ /*{{{*/
line_idedit(char * ident,size_t size,const char * prompt,size_t * x,size_t * offx)150 static int line_idedit(char *ident, size_t size, const char *prompt, size_t *x, size_t *offx)
151 {
152 /* variables */ /*{{{*/
153 const char *s;
154 Token **t;
155 int c;
156 /*}}}*/
157
158 t=(Token**)0;
159 s=ident+strlen(ident);
160 do
161 {
162 tvecfree(t);
163 *x=s-ident;
164 if ((c=line_edit((Sheet*)0,ident,size,prompt,x,offx))<0) return c;
165 s=ident;
166 t=scan(&s);
167 } while ((*s!='\0' && t==(Token**)0) || !(t!=(Token**)0 && ((*t)==(Token*)0 || ((*t)->type==LIDENT && *(t+1)==(Token*)0))));
168 tvecfree(t);
169 return 0;
170 }
171 /*}}}*/
172 /* doanyway -- ask if action should be done despite unsaved changes */ /*{{{*/
doanyway(Sheet * sheet,const char * msg)173 int doanyway(Sheet *sheet, const char *msg)
174 {
175 int result;
176
177 if (sheet->changed) {
178 result=line_ok(msg,0);
179 if (result < 0) return 0;
180 return result;
181 }
182 return 1;
183 }
184 /*}}}*/
185
186 /* do_edit -- set or modify cell contents */ /*{{{*/
do_edit(Sheet * cursheet,Key c,const char * expr,int clocked)187 static int do_edit(Sheet *cursheet, Key c, const char *expr, int clocked)
188 {
189 /* variables */ /*{{{*/
190 char buf[1024];
191 const char *s;
192 size_t x,offx;
193 int curx,cury,curz;
194 Token **t;
195 /*}}}*/
196
197 if (locked(cursheet,cursheet->curx,cursheet->cury,cursheet->curz)) line_msg(_("Edit cell:"),_("Cell is locked"));
198 else
199 {
200 curx=cursheet->curx;
201 cury=cursheet->cury;
202 curz=cursheet->curz;
203 if (expr)
204 {
205 s=expr;
206 t=scan(&s);
207 if (*s!='\0' && t==(Token**)0) line_msg(clocked ? _("Clocked cell contents:") : _("Cell contents:"),"XXX invalid expression");
208 }
209 else
210 {
211 offx=0;
212 if (c==K_NONE)
213 {
214 print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked));
215 s=buf+strlen(buf);
216 }
217 else if (c==K_BACKSPACE)
218 {
219 print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked));
220 if (strlen(buf)) *mbspos(buf+strlen(buf),-1)='\0';
221 s=buf+strlen(buf);
222 }
223 else if (c==K_DC)
224 {
225 print(buf,sizeof(buf),0,1,getscientific(cursheet,cursheet->curx,cursheet->cury,cursheet->curz),-1,getcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,clocked));
226 memmove(buf,mbspos(buf,1),strlen(mbspos(buf,1))+1);
227 s=buf;
228 }
229 else if (isalpha(c))
230 {
231 buf[0] = '"';
232 buf[1] = c;
233 buf[2] = 0;
234 s=buf+2;
235 }
236 else
237 {
238 if (c < 256) buf[0]=c;
239 else buf[0] = 0;
240 buf[1]='\0';
241 s=buf+1;
242 }
243 do
244 {
245 int r;
246
247 x=mbslen(buf)-mbslen(s);
248 if ((r=line_edit(cursheet,buf,sizeof(buf),clocked ? _("Clocked cell contents:") : _("Cell contents:"),&x,&offx))<0) return r;
249 s=buf;
250 if (buf[0] == '"' && buf[strlen(buf)-1] != '"' && strlen(buf)+1 < sizeof(buf)) {
251 buf[strlen(buf)+1] = 0;
252 buf[strlen(buf)] = '"';
253 }
254 t=scan(&s);
255 } while (*s!='\0' && t==(Token**)0);
256 }
257 if (t!=(Token**)0 && *t==(Token*)0) { free(t); t=(Token**)0; }
258 moveto(cursheet,curx,cury,curz);
259 putcont(cursheet,cursheet->curx,cursheet->cury,cursheet->curz,t,clocked);
260 forceupdate(cursheet);
261 }
262 return 0;
263 }
264 /*}}}*/
265 /* do_label -- modify cell label */ /*{{{*/
do_label(Sheet * sheet)266 static int do_label(Sheet *sheet)
267 {
268 /* variables */ /*{{{*/
269 char buf[1024],oldlabel[1024];
270 size_t edx,offx,ok;
271 Token t;
272 int x,y,z,x1,y1,z1,x2,y2,z2;
273 int c;
274 /*}}}*/
275
276 assert(sheet!=(Sheet*)0);
277 if (sheet->mark1x==-1 && locked(sheet,sheet->curx,sheet->cury,sheet->curz)) line_msg(_("Cell label:"),_("Cell is locked"));
278 else
279 {
280 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
281 ok=edx=offx=0;
282 (void)strcpy(buf,getlabel(sheet,sheet->curx,sheet->cury,sheet->curz));
283 (void)strcpy(oldlabel,buf);
284 do
285 {
286 if ((c=line_idedit(buf,sizeof(buf),_("Cell label:"),&edx,&offx))<0) return c;
287 if (buf[0]=='\0') ok=1;
288 else
289 {
290 ok=((t=findlabel(sheet,buf)).type==EEK || (t.type==LOCATION && t.u.location[0]==sheet->curx && t.u.location[1]==sheet->cury && t.u.location[2]==sheet->curz));
291 tfree(&t);
292 }
293 } while (!ok);
294 setlabel(sheet,sheet->curx,sheet->cury,sheet->curz,buf,1);
295 if (buf[0]!='\0') for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) relabel(sheet,oldlabel,buf,x,y,z);
296 }
297 return -1;
298 }
299 /*}}}*/
300 /* do_columnwidth -- set the column width */ /*{{{*/
do_columnwidth(Sheet * cursheet)301 static int do_columnwidth(Sheet *cursheet)
302 {
303 /* variables */ /*{{{*/
304 size_t edx,offx;
305 int n;
306 int x,x1,x2,z,z1,z2;
307 int c;
308 /*}}}*/
309
310 offx=0;
311 edx=0;
312 n=columnwidth(cursheet,cursheet->curx,cursheet->curz);
313 do if ((c=line_numedit(&n,_("Column width:"),&edx,&offx))<0) return c; while (n<=0);
314 if (cursheet->mark1x==-1)
315 /* range is the current cell */ /*{{{*/
316 {
317 x1=x2=cursheet->curx;
318 z1=z2=cursheet->curz;
319 }
320 /*}}}*/
321 else
322 /* range is the marked cube */ /*{{{*/
323 {
324 x1=cursheet->mark1x; x2=cursheet->mark2x;
325 z1=cursheet->mark1z; z2=cursheet->mark2z;
326 }
327 /*}}}*/
328 for (x=x1; x<=x2; ++x) for (z=z1; z<=z2; ++z) setwidth(cursheet,x,z,n);
329 return -1;
330 }
331 /*}}}*/
332 /* do_attribute -- set cell attributes */ /*{{{*/
do_attribute(Sheet * cursheet,Key action)333 static void do_attribute(Sheet *cursheet, Key action)
334 {
335 /* variables */ /*{{{*/
336 int x,y,z;
337 int x1,y1,z1;
338 int x2,y2,z2;
339 int c = 0;
340 /*}}}*/
341
342 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
343
344 if (action != ADJUST_LOCK && cursheet->mark1x==-1 && action != ADJUST_LOCK && locked(cursheet,cursheet->curx,cursheet->cury,cursheet->curz))
345 {
346 line_msg(_("Cell attribute:"),_("Cell is locked"));
347 return;
348 }
349 switch ((int)action)
350 {
351 /* 0 -- adjust left */ /*{{{*/
352 case ADJUST_LEFT:
353 {
354 if (cursheet->mark1x != -1 && line_ok(_("Make block left-adjusted:"), 0) <= 0) break;
355 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,LEFT);
356 break;
357 }
358 /*}}}*/
359 /* 1 -- adjust right */ /*{{{*/
360 case ADJUST_RIGHT:
361 {
362 if (cursheet->mark1x != -1 && line_ok(_("Make block right-adjusted:"), 0) <= 0) break;
363 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,RIGHT);
364 break;
365 }
366 /*}}}*/
367 /* 2 -- adjust centered */ /*{{{*/
368 case ADJUST_CENTER:
369 {
370 if (cursheet->mark1x != -1 && line_ok(_("Make block centered:"), 0) <= 0) break;
371 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setadjust(cursheet,x,y,z,CENTER);
372 break;
373 }
374 /*}}}*/
375 /* 3 -- set scientific notation flag */ /*{{{*/
376 case ADJUST_SCIENTIFIC:
377 {
378 int n;
379
380 if (cursheet->mark1x==-1) n = !getscientific(cursheet,x1,y1,z1);
381 else n = line_ok(_("Make block notation scientific:"), getscientific(cursheet,x1,y1,z1));
382 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setscientific(cursheet,x,y,z,n);
383 break;
384 }
385 /*}}}*/
386 /* 5 -- set precision */ /*{{{*/
387 case ADJUST_PRECISION:
388 {
389 size_t ex,offx;
390 int n;
391
392 offx=0;
393 ex=0;
394 n=getprecision(cursheet,x1,y1,z1);
395 do if (line_numedit(&n,cursheet->mark1x==-1 ? _("Precision for cell:") : _("Precision for block:"),&ex,&offx)==-1) return; while (n!=-1 && (n==0 || n>20));
396 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) setprecision(cursheet,x,y,z,n);
397 break;
398 }
399 /*}}}*/
400 /* 6 -- shadow */ /*{{{*/
401 case ADJUST_SHADOW:
402 {
403 int n;
404
405 if (cursheet->mark1x==-1) n = !shadowed(cursheet,x1,y1,z1);
406 else n = line_ok(_("Shadow block:"), shadowed(cursheet,x1,y1,z1));
407 if (x1 == 0 && n == 1) {
408 line_msg(_("Shadow cell:"),_("You can not shadow cells in column 0"));
409 break;
410 }
411
412 if (n >= 0) {
413 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z)
414 {
415 int rx;
416
417 if (n==0) for (rx=x+1; shadowed(cursheet,rx,y,z); ++rx) shadow(cursheet,rx,y,z,0);
418 else if (x>0) shadow(cursheet,x,y,z,1);
419 }
420 }
421 break;
422 }
423 /*}}}*/
424 /* 7 -- transparent */ /*{{{*/
425 case ADJUST_TRANSPARENT:
426 {
427 int n;
428
429 if (cursheet->mark1x==-1) n = !transparent(cursheet,x1,y1,z1);
430 else n = line_ok(_("Make block transparent:"), transparent(cursheet,x1,y1,z1));
431 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) maketrans(cursheet,x,y,z,n);
432 break;
433 }
434 /*}}}*/
435 /* 8 -- bold */ /*{{{*/
436 case ADJUST_BOLD:
437 {
438 int n;
439
440 if (cursheet->mark1x==-1) n = !isbold(cursheet,x1,y1,z1);
441 else n = line_ok(_("Make block bold:"), isbold(cursheet,x1,y1,z1));
442 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) bold(cursheet,x,y,z,n);
443 break;
444 }
445 /*}}}*/
446 /* 9 -- underline */ /*{{{*/
447 case ADJUST_UNDERLINE:
448 {
449 int n;
450
451 if (cursheet->mark1x==-1) n = !underlined(cursheet,x1,y1,z1);
452 else n = line_ok(_("Make block underlined:"), underlined(cursheet,x1,y1,z1));
453 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) underline(cursheet,x,y,z,n);
454 break;
455 }
456 /*}}}*/
457 /* 1 -- edit label and goto end */ /*{{{*/
458 case ADJUST_LABEL:
459 {
460 do_label(cursheet);
461 return;
462 }
463 /*}}}*/
464 /* 2 -- lock */ /*{{{*/
465 case ADJUST_LOCK:
466 {
467 int n;
468
469 if (cursheet->mark1x==-1) n = !locked(cursheet,x1,y1,z1);
470 else n = line_ok(_("Lock block:"), locked(cursheet,x1,y1,z1));
471 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) lockcell(cursheet,x,y,z,n);
472
473 break;
474 }
475 /*}}}*/
476 /* 3 -- ignore */ /*{{{*/
477 case ADJUST_IGNORE:
478 {
479 int n;
480
481 if (cursheet->mark1x==-1) n = !ignored(cursheet,x1,y1,z1);
482 else n = line_ok(_("Ignore values of all cells in this block:"), ignored(cursheet,x1,y1,z1));
483 if (n >= 0) for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) igncell(cursheet,x,y,z,n);
484 break;
485 }
486 /*}}}*/
487 /* default -- should not happen */ /*{{{*/
488 default: assert(0);
489 /*}}}*/
490 }
491 if (c>=0)
492 {
493 if (cursheet->mark1x==-1) redraw_cell(cursheet, cursheet->curx, cursheet->cury, cursheet->curz);
494 else redraw_sheet(cursheet);
495 }
496 forceupdate(cursheet);
497 return;
498 }
499 /*}}}*/
500 /* do_savexdr -- save sheet as XDR file */ /*{{{*/
do_savexdr(Sheet * cursheet,const char * name)501 static int do_savexdr(Sheet *cursheet, const char *name)
502 {
503 char buf[PATH_MAX];
504 const char *msg;
505 unsigned int count;
506
507 if (!name) {
508 name = cursheet->name;
509
510 if (strcmp(name+strlen(name)-3,".tp")) {
511 snprintf(buf, sizeof(buf), "%s.tp", name);
512 name = buf;
513 }
514 }
515
516 if ((msg = savexdr(cursheet, name, &count))) {
517 line_msg(_("Save sheet to XDR file:"), msg);
518 return -2;
519 }
520
521 snprintf(buf, sizeof(buf), _("%u cells written"), count);
522 if (!batch) line_msg(_("Save sheet to XDR file:"),buf);
523 return -1;
524 }
525 /*}}}*/
526 /* do_saveport -- save sheet as portable ASCII file */ /*{{{*/
do_saveport(Sheet * cursheet,const char * name)527 static int do_saveport(Sheet *cursheet, const char *name)
528 {
529 char buf[PATH_MAX];
530 const char *msg;
531 unsigned int count;
532
533 if (!name) name = cursheet->name;
534
535 if ((msg = saveport(cursheet, name, &count))) {
536 line_msg(_("Save sheet to ASCII file:"),msg);
537 return -2;
538 }
539
540 snprintf(buf, sizeof(buf), _("%u cells written"), count);
541 if (!batch) line_msg(_("Save sheet to ASCII file:"),buf);
542 return -1;
543 }
544 /*}}}*/
545 /* do_savetbl -- save sheet as tbl file */ /*{{{*/
do_savetbl(Sheet * cursheet,const char * name)546 static int do_savetbl(Sheet *cursheet, const char *name)
547 {
548 char buf[PATH_MAX];
549 const char *msg;
550 int standalone=0;
551 int x1,y1,z1,x2,y2,z2;
552 unsigned int count;
553
554 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
555 if (!name) {
556 name = cursheet->name;
557 if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
558 }
559
560 if ((msg = savetbl(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) {
561 line_msg(_("Save in tbl format to file:"),msg);
562 return -2;
563 }
564
565 snprintf(buf, sizeof(buf), _("%u cells written"), count);
566 if (!batch) line_msg(_("Save in tbl format to file:"), buf);
567 return -1;
568 }
569 /*}}}*/
570 /* do_savelatex -- save sheet as LaTeX file */ /*{{{*/
do_savelatex(Sheet * cursheet,const char * name)571 static int do_savelatex(Sheet *cursheet, const char *name)
572 {
573 char buf[PATH_MAX];
574 const char *msg;
575 int standalone=0;
576 int x1,y1,z1,x2,y2,z2;
577 unsigned int count;
578
579 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
580 if (!name) {
581 name = cursheet->name;
582 if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
583 }
584
585 if ((msg = savelatex(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) {
586 line_msg(_("Save in LaTeX format to file:"),msg);
587 return -2;
588 }
589
590 snprintf(buf, sizeof(buf), _("%u cells written"), count);
591 if (!batch) line_msg(_("Save in LaTeX format to file:"), buf);
592 return -1;
593 }
594 /*}}}*/
595 /* do_savecontext -- save sheet as ConTeXt file */ /*{{{*/
do_savecontext(Sheet * cursheet,const char * name)596 static int do_savecontext(Sheet *cursheet, const char *name)
597 {
598 char buf[PATH_MAX];
599 const char *msg;
600 int standalone=0;
601 int x1,y1,z1,x2,y2,z2;
602 unsigned int count;
603
604 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
605 if (!name) {
606 name = cursheet->name;
607 if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
608 }
609
610 if ((msg = savecontext(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) {
611 line_msg(_("Save in ConTeXt format to file:"),msg);
612 return -2;
613 }
614
615 snprintf(buf, sizeof(buf), _("%u cells written"), count);
616 if (!batch) line_msg(_("Save in ConTeXt format to file:"), buf);
617 return -1;
618 }
619 /*}}}*/
620 /* do_savehtml -- save sheet as HTML file */ /*{{{*/
do_savehtml(Sheet * cursheet,const char * name)621 static int do_savehtml(Sheet *cursheet, const char *name)
622 {
623 char buf[PATH_MAX];
624 const char *msg;
625 int standalone=0;
626 int x1,y1,z1,x2,y2,z2;
627 unsigned int count;
628
629 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
630 if (!name) {
631 name = cursheet->name;
632 if ((standalone=line_ok(_("Save as stand-alone document:"),1))<0) return standalone;
633 }
634
635 if ((msg = savehtml(cursheet, name, !standalone, x1, y1, z1, x2, y2, z2, &count))) {
636 line_msg(_("Save in HTML format to file:"),msg);
637 return -2;
638 }
639
640 snprintf(buf, sizeof(buf), _("%u cells written"), count);
641 if (!batch) line_msg(_("Save in HTML format to file:"), buf);
642 return -1;
643 }
644 /*}}}*/
645 /* do_savetext -- save sheet as formatted text file */ /*{{{*/
do_savetext(Sheet * cursheet,const char * name)646 static int do_savetext(Sheet *cursheet, const char *name)
647 {
648 char buf[PATH_MAX];
649 const char *msg;
650 int x1,y1,z1,x2,y2,z2;
651 unsigned int count;
652
653 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
654 if (!name) name = cursheet->name;
655
656 if ((msg = savetext(cursheet, name, x1, y1, z1, x2, y2, z2, &count))) {
657 line_msg(_("Save in plain text format to file:"),msg);
658 return -2;
659 }
660
661 snprintf(buf, sizeof(buf), _("%u cells written"), count);
662 if (!batch) line_msg(_("Save in plain text format to file:"), buf);
663 return -1;
664 }
665 /*}}}*/
666 /* do_savecsv -- save sheet as CSV file */ /*{{{*/
do_savecsv(Sheet * cursheet,const char * name)667 static int do_savecsv(Sheet *cursheet, const char *name)
668 {
669 char buf[PATH_MAX];
670 const char *msg;
671 int x1,y1,z1,x2,y2,z2;
672 unsigned int count;
673 int sep = 0;
674 const char seps[4] = ",;\t";
675
676 get_mark(cursheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
677 if (!name) {
678 MenuChoice menu[4];
679 name = cursheet->name;
680
681 menu[0].str=mystrmalloc(_("cC)omma (,)")); menu[0].c='\0';
682 menu[1].str=mystrmalloc(_("sS)emicolon (;)")); menu[1].c='\0';
683 menu[2].str=mystrmalloc(_("tT)ab (\\t)")); menu[2].c='\0';
684 menu[3].str=(char*)0;
685 sep=line_menu(_("Choose separator:"),menu,0);
686 if (sep < 0) return sep;
687 }
688
689 if ((msg = savecsv(cursheet, name, seps[sep], x1, y1, z1, x2, y2, z2, &count))) {
690 line_msg(_("Save in CSV format to file:"),msg);
691 return -2;
692 }
693
694 snprintf(buf, sizeof(buf), _("%u cells written"), count);
695 if (!batch) line_msg(_("Save in CSV format to file:"), buf);
696 return -1;
697 }
698 /*}}}*/
699 /* do_loadxdr -- load sheet from XDR file */ /*{{{*/
do_loadxdr(Sheet * cursheet)700 static int do_loadxdr(Sheet *cursheet)
701 {
702 const char *msg;
703
704 if ((msg=loadxdr(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from XDR file:"),msg);
705 return -1;
706 }
707 /*}}}*/
708 /* do_loadport -- load sheet from portable ASCII file */ /*{{{*/
do_loadport(Sheet * cursheet)709 static int do_loadport(Sheet *cursheet)
710 {
711 const char *msg;
712 /*}}}*/
713
714 if ((msg=loadport(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from ASCII file:"),msg);
715 return -1;
716 }
717 /*}}}*/
718 /* do_loadsc -- load sheet from SC file */ /*{{{*/
do_loadsc(Sheet * cursheet)719 static int do_loadsc(Sheet *cursheet)
720 {
721 const char *msg;
722
723 if ((msg=loadsc(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from SC file:"),msg);
724 return -1;
725 }
726 /*}}}*/
727 /* do_loadwk1 -- load sheet from WK1 file */ /*{{{*/
do_loadwk1(Sheet * cursheet)728 static int do_loadwk1(Sheet *cursheet)
729 {
730 const char *msg;
731
732 if ((msg=loadwk1(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from WK1 file:"),msg);
733 return -1;
734 }
735 /*}}}*/
736 /* do_loadcsv -- load/merge sheet from CSV file */ /*{{{*/
do_loadcsv(Sheet * cursheet)737 static int do_loadcsv(Sheet *cursheet)
738 {
739 const char *msg;
740
741 if ((msg=loadcsv(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from CSV file:"),msg);
742 return -1;
743 }
744 /*}}}*/
745 /* do_mark -- set mark */ /*{{{*/
do_mark(Sheet * cursheet,int force)746 void do_mark(Sheet *cursheet, int force)
747 {
748 if (force==0)
749 {
750 if (!cursheet->marking && cursheet->mark1x==-1) force=1;
751 else if (cursheet->marking) force=2;
752 else force=3;
753 }
754 switch (force)
755 {
756 case 1:
757 {
758 cursheet->mark1x=cursheet->mark2x=cursheet->curx;
759 cursheet->mark1y=cursheet->mark2y=cursheet->cury;
760 cursheet->mark1z=cursheet->mark2z=cursheet->curz;
761 cursheet->marking=1;
762 break;
763 }
764 case 2:
765 {
766 cursheet->marking=0;
767 break;
768 }
769 case 3:
770 {
771 cursheet->mark1x=-1;
772 break;
773 }
774 default: assert(0);
775 }
776 }
777 /*}}}*/
778 static int do_name(Sheet *cursheet);
779 /* do_save -- save sheet */ /*{{{*/
do_save(Sheet * cursheet)780 static int do_save(Sheet *cursheet)
781 {
782 const char *ext = cursheet->name;
783 if (ext==(char*)0) return do_name(cursheet);
784
785 ext += strlen(ext)-1;
786
787 if (!strcmp(ext-3, ".tpa")) return do_saveport(cursheet, NULL);
788 if (!strcmp(ext-3, ".tbl")) return do_savetbl(cursheet, NULL);
789 if (!strcmp(ext-5, ".latex")) return do_savelatex(cursheet, NULL);
790 if (!strcmp(ext-4, ".html")) return do_savehtml(cursheet, NULL);
791 if (!strcmp(ext-3, ".csv")) return do_savecsv(cursheet, NULL);
792 if (!strcmp(ext-3, ".txt")) return do_savetext(cursheet, NULL);
793 if (!strcmp(ext-3, ".tex")) return do_savecontext(cursheet, NULL);
794 return do_savexdr(cursheet, NULL);
795 }
796 /*}}}*/
797 /* do_name -- (re)name sheet */ /*{{{*/
do_name(Sheet * cursheet)798 static int do_name(Sheet *cursheet)
799 {
800 const char *name;
801
802 name = line_file(cursheet->name, _("Teapot \t*.tp\nTeapot ASCII \t*.tpa\ntbl \t*.tbl\nLaTeX \t*.latex\nHTML \t*.html\nCSV \t*.csv\nFormatted ASCII \t*.txt\nConTeXt \t*.tex"), _("New file name:"), 1);
803 if (!name) return -1;
804
805 if (cursheet->name!=(char*)0) free(cursheet->name);
806 cursheet->name=strdup(name);
807 return do_save(cursheet);
808 }
809 /*}}}*/
810 /* do_load -- load sheet */ /*{{{*/
do_load(Sheet * cursheet)811 static int do_load(Sheet *cursheet)
812 {
813 const char *name, *ext;
814
815 if (doanyway(cursheet, _("Sheet modified, load new file anyway?")) != 1) return -1;
816
817 name = line_file(cursheet->name, _("Teapot \t*.tp\nTeapot ASCII \t*.tpa\nSC Spreadsheet Calculator \t*.sc\nLotus 1-2-3 \t*.wk1\nCSV \t*.csv"), _("Load sheet:"), 0);
818 if (!name) return -1;
819 if (cursheet->name!=(char*)0) free(cursheet->name);
820 cursheet->name=strdup(name);
821
822 ext = name+strlen(name)-1;
823 if (!strcmp(ext-3, ".tpa")) return do_loadport(cursheet);
824 if (!strcmp(ext-2, ".sc")) return do_loadsc(cursheet);
825 if (!strcmp(ext-3, ".wk1")) return do_loadwk1(cursheet);
826 if (!strcmp(ext-3, ".csv")) return do_loadcsv(cursheet);
827 return do_loadxdr(cursheet);
828 }
829 /*}}}*/
830
831 /* do_clear -- clear block */ /*{{{*/
do_clear(Sheet * sheet)832 static int do_clear(Sheet *sheet)
833 {
834 /* variables */ /*{{{*/
835 int x,y,z;
836 int x1,y1,z1;
837 int x2,y2,z2;
838 int c;
839 /*}}}*/
840
841 if (sheet->mark1x==-1 && locked(sheet,sheet->curx,sheet->cury,sheet->curz)) line_msg(_("Clear cell:"),_("Cell is locked"));
842 else
843 {
844 if (sheet->mark1x!=-1)
845 {
846 if ((c=line_ok(_("Clear block:"),0))<0) return c;
847 else if (c!=1) return -1;
848 }
849 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
850 for (x=x1; x<=x2; ++x) for (y=y1; y<=y2; ++y) for (z=z1; z<=z2; ++z) freecell(sheet,x,y,z);
851 cachelabels(sheet);
852 forceupdate(sheet);
853 }
854 return -1;
855 }
856 /*}}}*/
857 /* do_insert -- insert block */ /*{{{*/
do_insert(Sheet * sheet)858 static int do_insert(Sheet *sheet)
859 {
860 /* variables */ /*{{{*/
861 int x1,y1,z1,x2,y2,z2,reply;
862 /*}}}*/
863
864 /* ask for direction of insertation */ /*{{{*/
865 {
866 MenuChoice menu[4];
867
868 menu[0].str=mystrmalloc(_("cC)olumn")); menu[0].c='\0';
869 menu[1].str=mystrmalloc(_("rR)ow")); menu[1].c='\0';
870 menu[2].str=mystrmalloc(_("dD)epth")); menu[2].c='\0';
871 menu[3].str=(char*)0;
872 reply=line_menu(_("Insert:"),menu,0);
873 free(menu[0].str);
874 free(menu[1].str);
875 free(menu[2].str);
876 if (reply<0) return reply;
877 }
878 /*}}}*/
879 if (sheet->mark1x==-1)
880 /* ask if current cell or whole dimension should be used */ /*{{{*/
881 {
882 /* variables */ /*{{{*/
883 MenuChoice menu[3];
884 int r;
885 /*}}}*/
886
887 /* show menu */ /*{{{*/
888 switch (reply)
889 {
890 case 0: menu[0].str=mystrmalloc(_("wW)hole column")); break;
891 case 1: menu[0].str=mystrmalloc(_("wW)hole line")); break;
892 case 2: menu[0].str=mystrmalloc(_("wW)hole sheet")); break;
893 default: assert(0);
894 }
895 menu[1].str=mystrmalloc(_("sS)ingle cell")); menu[1].c='\0';
896 menu[2].str=(char*)0;
897 r=line_menu(_("Insert:"),menu,0);
898 free(menu[0].str);
899 free(menu[1].str);
900 /*}}}*/
901 switch (r)
902 {
903 /* 0 -- use whole dimension */ /*{{{*/
904 case 0:
905 {
906 switch (reply)
907 {
908 /* 0 -- use whole column */ /*{{{*/
909 case 0:
910 {
911 x1=x2=sheet->curx;
912 y1=0; y2=sheet->dimy;
913 z1=z2=sheet->curz;
914 break;
915 }
916 /*}}}*/
917 /* 1 -- use whole line */ /*{{{*/
918 case 1:
919 {
920 x1=0; x2=sheet->dimx;
921 y1=y2=sheet->cury;
922 z1=z2=sheet->curz;
923 break;
924 }
925 /*}}}*/
926 /* 2 -- use whole layer */ /*{{{*/
927 case 2:
928 {
929 x1=0; x2=sheet->dimx;
930 y1=0; y2=sheet->dimy;
931 z1=z2=sheet->curz;
932 break;
933 }
934 /*}}}*/
935 /* default -- should not happen */ /*{{{*/
936 default: assert(0);
937 /*}}}*/
938 }
939 break;
940 }
941 /*}}}*/
942 /* 1 -- use current cell */ /*{{{*/
943 case 1:
944 {
945 x1=x2=sheet->curx;
946 y1=y2=sheet->cury;
947 z1=z2=sheet->curz;
948 break;
949 }
950 /*}}}*/
951 /* -2,-1 -- go up or abort */ /*{{{*/
952 case -2:
953 case -1: return r;
954 /*}}}*/
955 /* default -- should not happen */ /*{{{*/
956 default: assert(0);
957 /*}}}*/
958 }
959 }
960 /*}}}*/
961 else
962 /* range is the marked cube */ /*{{{*/
963 {
964 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
965 }
966 /*}}}*/
967 switch (reply)
968 {
969 /* 0 -- columns */ /*{{{*/
970 case 0: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_X); break;
971 /*}}}*/
972 /* 1 -- rows */ /*{{{*/
973 case 1: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break;
974 /*}}}*/
975 /* 2 -- depth */ /*{{{*/
976 case 2: insertcube(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break;
977 /*}}}*/
978 }
979 return 0;
980 }
981 /*}}}*/
982 /* do_delete -- delete block */ /*{{{*/
do_delete(Sheet * sheet)983 static int do_delete(Sheet *sheet)
984 {
985 /* variables */ /*{{{*/
986 int x1,y1,z1,x2,y2,z2,reply;
987 /*}}}*/
988
989 firstmenu:
990 /* ask for direction of deletion */ /*{{{*/
991 {
992 MenuChoice menu[4];
993
994 menu[0].str=mystrmalloc(_("cC)olumn")); menu[0].c='\0';
995 menu[1].str=mystrmalloc(_("rR)ow")); menu[1].c='\0';
996 menu[2].str=mystrmalloc(_("dD)epth")); menu[2].c='\0';
997 menu[3].str=(char*)0;
998 reply=line_menu(_("Delete:"),menu,0);
999 free(menu[0].str);
1000 free(menu[1].str);
1001 free(menu[2].str);
1002 if (reply<0) return reply;
1003 }
1004 /*}}}*/
1005 if (sheet->mark1x==-1)
1006 /* ask if range is the current cell or whole dimension should be used */ /*{{{*/
1007 {
1008 /* variables */ /*{{{*/
1009 MenuChoice menu[3];
1010 int r;
1011 /*}}}*/
1012
1013 /* show menu */ /*{{{*/
1014 switch (reply)
1015 {
1016 case 0: menu[0].str=mystrmalloc(_("wW)hole column")); break;
1017 case 1: menu[0].str=mystrmalloc(_("wW)hole line")); break;
1018 case 2: menu[0].str=mystrmalloc(_("wW)hole sheet")); break;
1019 default: assert(0);
1020 }
1021 menu[1].str=mystrmalloc(_("sS)ingle cell")); menu[1].c='\0';
1022 menu[2].str=(char*)0;
1023 r=line_menu(_("Delete:"),menu,0);
1024 free(menu[0].str);
1025 free(menu[1].str);
1026 /*}}}*/
1027 switch (r)
1028 {
1029 /* 0 -- use whole dimension */ /*{{{*/
1030 case 0:
1031 {
1032 switch (reply)
1033 {
1034 /* 0 -- use whole column */ /*{{{*/
1035 case 0:
1036 {
1037 x1=x2=sheet->curx;
1038 y1=0; y2=sheet->dimy;
1039 z1=z2=sheet->curz;
1040 break;
1041 }
1042 /*}}}*/
1043 /* 1 -- use whole line */ /*{{{*/
1044 case 1:
1045 {
1046 x1=0; x2=sheet->dimx;
1047 y1=y2=sheet->cury;
1048 z1=z2=sheet->curz;
1049 break;
1050 }
1051 /*}}}*/
1052 /* 2 -- use whole layer */ /*{{{*/
1053 case 2:
1054 {
1055 x1=0; x2=sheet->dimx;
1056 y1=0; y2=sheet->dimy;
1057 z1=z2=sheet->curz;
1058 break;
1059 }
1060 /*}}}*/
1061 /* default -- should not happen */ /*{{{*/
1062 default: assert(0);
1063 /*}}}*/
1064 }
1065 break;
1066 }
1067 /*}}}*/
1068 /* 1 -- use current cell */ /*{{{*/
1069 case 1:
1070 {
1071 x1=x2=sheet->curx;
1072 y1=y2=sheet->cury;
1073 z1=z2=sheet->curz;
1074 break;
1075 }
1076 /*}}}*/
1077 /* -1 -- abort */ /*{{{*/
1078 case -1: return -1;
1079 /*}}}*/
1080 /* -2 -- go back to previous menu */ /*{{{*/
1081 case -2: goto firstmenu;
1082 /*}}}*/
1083 /* default -- should not happen */ /*{{{*/
1084 default: assert(0);
1085 /*}}}*/
1086 }
1087 }
1088 /*}}}*/
1089 else
1090 /* range is the marked cube */ /*{{{*/
1091 {
1092 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
1093 }
1094 /*}}}*/
1095 switch(reply)
1096 {
1097 /* 0 -- columns */ /*{{{*/
1098 case 0: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_X); break;
1099 /*}}}*/
1100 /* 1 -- rows */ /*{{{*/
1101 case 1: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break;
1102 /*}}}*/
1103 /* 2 -- depth */ /*{{{*/
1104 case 2: deletecube(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break;
1105 /*}}}*/
1106 }
1107 return -1;
1108 }
1109 /*}}}*/
1110 /* do_move -- copy or move a block */ /*{{{*/
do_move(Sheet * sheet,int copy,int force)1111 static int do_move(Sheet *sheet, int copy, int force)
1112 {
1113 int c;
1114
1115 c=-1;
1116 if (sheet->mark1x==-1) line_msg(copy ? _("Copy block:") : _("Move block:"),_("No block marked"));
1117 else if (force || (c=line_ok(copy ? _("Copy block:") : _("Move block:"),0))==1)
1118 {
1119 int x1,y1,z1;
1120 int x2,y2,z2;
1121
1122 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
1123 moveblock(sheet,x1,y1,z1,x2,y2,z2,sheet->curx,sheet->cury,sheet->curz,copy);
1124 if (!copy) sheet->mark1x=-1;
1125 }
1126 if (c<0) return c; else return -1;
1127 }
1128 /*}}}*/
1129 /* do_fill -- fill a block */ /*{{{*/
do_fill(Sheet * sheet)1130 static int do_fill(Sheet *sheet)
1131 {
1132 /* variables */ /*{{{*/
1133 size_t offx,edx;
1134 int cols,rows,layers;
1135 int x,y,z;
1136 int x1,y1,z1;
1137 int x2,y2,z2;
1138 int c;
1139 /*}}}*/
1140
1141 if (sheet->mark1x==-1) line_msg(_("Fill block:"),_("No block marked"));
1142 else
1143 {
1144 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 0);
1145 cols=rows=layers=1;
1146 firstmenu:
1147 offx=0;
1148 edx=0;
1149 do if ((c=line_numedit(&cols,_("Number of column-wise repetitions:"),&edx,&offx))<0) return c; while (cols<=0);
1150 secondmenu:
1151 offx=0;
1152 edx=0;
1153 do
1154 {
1155 c=line_numedit(&rows,_("Number of row-wise repetitions:"),&edx,&offx);
1156 if (c==-1) return -1;
1157 else if (c==-2) goto firstmenu;
1158 } while (rows<=0);
1159 offx=0;
1160 edx=0;
1161 do
1162 {
1163 c=line_numedit(&layers,_("Number of depth-wise repetitions:"),&edx,&offx);
1164 if (c==-1) return -1;
1165 else if (c==-2) goto secondmenu;
1166 } while (layers<=0);
1167 for (x=0; x<cols; ++x) for (y=0; y<rows; ++y) for (z=0; z<layers; ++z) moveblock(sheet,x1,y1,z1,x2,y2,z2,sheet->curx+x*(x2-x1+1),sheet->cury+y*(y2-y1+1),sheet->curz+z*(z2-z1+1),1);
1168 }
1169 return -1;
1170 }
1171 /*}}}*/
1172 /* do_sort -- sort block */ /*{{{*/
do_sort(Sheet * sheet)1173 static int do_sort(Sheet *sheet)
1174 {
1175 /* variables */ /*{{{*/
1176 MenuChoice menu1[4],menu2[3],menu3[3];
1177 Sortkey sk[MAX_SORTKEYS];
1178 unsigned int key;
1179 size_t x,offx;
1180 const char *msg;
1181 Direction in_dir=(Direction)-2; /* cause run time error */
1182 int x1,y1,z1,x2,y2,z2;
1183 int doit=-1;
1184 int c;
1185 int last;
1186 /*}}}*/
1187
1188 /* note and order block coordinates */ /*{{{*/
1189 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
1190 /*}}}*/
1191 /* build menues */ /*{{{*/
1192 menu1[0].str=mystrmalloc(_("cC)olumn")); menu1[0].c='\0';
1193 menu1[1].str=mystrmalloc(_("rR)ow")); menu1[1].c='\0';
1194 menu1[2].str=mystrmalloc(_("dD)epth")); menu1[2].c='\0';
1195 menu1[3].str=(char*)0;
1196 menu2[0].str=mystrmalloc(_("sS)ort region")); menu2[0].c='\0';
1197 menu2[1].str=mystrmalloc(_("aA)dd key")); menu2[1].c='\0';
1198 menu2[2].str=(char*)0;
1199 menu3[0].str=mystrmalloc(_("aA)scending")); menu3[0].c='\0';
1200 menu3[1].str=mystrmalloc(_("dD)escending")); menu3[0].c='\0';
1201 menu3[2].str=(char*)0;
1202 /*}}}*/
1203
1204 last=-1;
1205 /* ask for sort direction */ /*{{{*/
1206 zero: switch (c=line_menu(_("Sort block:"),menu1,0))
1207 {
1208 /* 0 -- in X */ /*{{{*/
1209 case 0: in_dir=IN_X; break;
1210 /*}}}*/
1211 /* 1 -- in Y */ /*{{{*/
1212 case 1: in_dir=IN_Y; break;
1213 /*}}}*/
1214 /* 2 -- in Z */ /*{{{*/
1215 case 2: in_dir=IN_Z; break;
1216 /*}}}*/
1217 /* -2,-1 -- abort */ /*{{{*/
1218 case -2:
1219 case -1: goto greak;
1220 /*}}}*/
1221 /* default -- should not happen */ /*{{{*/
1222 default: assert(0);
1223 /*}}}*/
1224 }
1225 last=0;
1226 /*}}}*/
1227 key=0;
1228 do
1229 {
1230 /* ask for positions */ /*{{{*/
1231 one: if (in_dir==IN_X) sk[key].x=0; else /* ask for x position */ /*{{{*/
1232 {
1233 x=0;
1234 offx=0;
1235 sk[key].x=0;
1236 do
1237 {
1238 c=line_numedit(&(sk[key].x),_("X position of key vector:"),&x,&offx);
1239 if (c==-1) goto greak;
1240 else if (c==-2) switch (last)
1241 {
1242 case -1: goto greak;
1243 case 0: goto zero;
1244 case 2: goto two;
1245 case 3: goto three;
1246 case 5: goto five;
1247 }
1248 } while (sk[key].x<0);
1249 last=1;
1250 }
1251 /*}}}*/
1252 two: if (in_dir==IN_Y) sk[key].y=0; else /* ask for y position */ /*{{{*/
1253 {
1254 x=0;
1255 offx=0;
1256 sk[key].y=0;
1257 do
1258 {
1259 c=line_numedit(&(sk[key].y),_("Y position of key vector:"),&x,&offx);
1260 if (c==-1) goto greak;
1261 else if (c==-2) switch (last)
1262 {
1263 case -1: goto greak;
1264 case 0: goto zero;
1265 case 1: goto one;
1266 case 3: goto three;
1267 case 5: goto five;
1268 default: assert(0);
1269 }
1270 } while (sk[key].y<0);
1271 last=2;
1272 }
1273 /*}}}*/
1274 three: if (in_dir==IN_Z) sk[key].z=0; else /* ask for z position */ /*{{{*/
1275 {
1276 x=0;
1277 offx=0;
1278 sk[key].z=0;
1279 do
1280 {
1281 c=line_numedit(&(sk[key].z),_("Z position of key vector:"),&x,&offx);
1282 if (c==-1) goto greak;
1283 else if (c==-2) switch (last)
1284 {
1285 case -1: goto greak;
1286 case 0: goto zero;
1287 case 1: goto one;
1288 case 2: goto two;
1289 case 5: goto five;
1290 default: assert(0);
1291 }
1292 } while (sk[key].z<0);
1293 last=3;
1294 }
1295 /*}}}*/
1296 /*}}}*/
1297 /* ask for sort key */ /*{{{*/
1298 four: sk[key].sortkey=0;
1299 switch (c=line_menu(_("Sort block:"),menu3,0))
1300 {
1301 /* 0 -- ascending */ /*{{{*/
1302 case 0: sk[key].sortkey|=ASCENDING; break;
1303 /*}}}*/
1304 /* 1 -- descending */ /*{{{*/
1305 case 1: sk[key].sortkey&=~ASCENDING; break;
1306 /*}}}*/
1307 /* -1 -- abort */ /*{{{*/
1308 case -1: goto greak;
1309 /*}}}*/
1310 /* -2 -- go to first menu */ /*{{{*/
1311 case -2: switch (last)
1312 {
1313 case -1: goto greak;
1314 case 1: goto one;
1315 case 2: goto two;
1316 case 3: goto three;
1317 default: assert(0);
1318 }
1319 /*}}}*/
1320 /* default -- should not happen */ /*{{{*/
1321 default: assert(0);
1322 /*}}}*/
1323 }
1324 last=4;
1325 /*}}}*/
1326 ++key;
1327 five:
1328 if (key==MAX_SORTKEYS) /* ask for sort comfirmation */ /*{{{*/
1329 {
1330 c=line_ok(_("Sort block:"),0);
1331 if (c==-1) goto greak;
1332 else if (c==-2) goto four;
1333 else if (c==0) doit=1;
1334 }
1335 /*}}}*/
1336 else /* ask for sort or adding another key */ /*{{{*/
1337 switch (line_menu(_("Sort block:"),menu2,0))
1338 {
1339 /* 0 -- sort it */ /*{{{*/
1340 case 0: doit=1; break;
1341 /*}}}*/
1342 /* 1 -- add another key */ /*{{{*/
1343 case 1: doit=0; break;
1344 /*}}}*/
1345 /* -1 -- abort */ /*{{{*/
1346 case -1: goto greak;
1347 /*}}}*/
1348 case -2: goto four;
1349 /* default -- should not happen */ /*{{{*/
1350 default: assert(0);
1351 /*}}}*/
1352 }
1353 /*}}}*/
1354 last=5;
1355 } while (!doit);
1356 c=-1;
1357 if ((msg=sortblock(sheet,x1,y1,z1,x2,y2,z2,in_dir,sk,key))!=(const char*)0) line_msg(_("Sort block:"),msg);
1358 greak:
1359 /* free menues */ /*{{{*/
1360 free((char*)menu1[0].str);
1361 free((char*)menu1[1].str);
1362 free((char*)menu1[2].str);
1363 free((char*)menu2[0].str);
1364 free((char*)menu2[1].str);
1365 free((char*)menu2[2].str);
1366 free((char*)menu3[0].str);
1367 free((char*)menu3[1].str);
1368 free((char*)menu3[2].str);
1369 /*}}}*/
1370 return c;
1371 }
1372 /*}}}*/
1373 /* do_batchsort -- sort block in a batch*/ /*{{{*/
do_batchsort(Sheet * sheet,Direction dir,char * arg)1374 static void do_batchsort(Sheet *sheet, Direction dir, char* arg)
1375 {
1376 Sortkey sk[MAX_SORTKEYS];
1377 int x1,y1,z1,x2,y2,z2;
1378 unsigned int key = 0;
1379 char* next;
1380 while( *arg != '\0' )
1381 {
1382 while (isspace((int)*arg)) arg++;
1383 sk[key].x=sk[key].y=sk[key].z=sk[key].sortkey=0;
1384 switch (*arg)
1385 {
1386 case 'a': sk[key].sortkey|=ASCENDING; arg++; break;
1387 case 'd': sk[key].sortkey&=~ASCENDING; arg++; break;
1388 }
1389 if ( *arg != '\0' && dir != IN_X ) { sk[key].x=strtol(arg, &next, 10); arg = next; }
1390 if ( *arg != '\0' && dir != IN_Y ) { sk[key].y=strtol(arg, &next, 10); arg = next; }
1391 if ( *arg != '\0' && dir != IN_Z ) { sk[key].z=strtol(arg, &next, 10); arg = next; }
1392 key++;
1393 }
1394 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
1395 sortblock(sheet, x1, y1, z1, x2, y2, z2, dir, sk, key);
1396 }
1397 /*}}}*/
1398 /* do_mirror -- mirror block */ /*{{{*/
do_mirror(Sheet * sheet)1399 static int do_mirror(Sheet *sheet)
1400 {
1401 /* variables */ /*{{{*/
1402 int x1,y1,z1,x2,y2,z2,reply;
1403 /*}}}*/
1404
1405 /* note and order block coordinates */ /*{{{*/
1406 get_mark(sheet, &x1, &x2, &y1, &y2, &z1, &z2, 1);
1407 /*}}}*/
1408 /* ask for direction of mirroring */ /*{{{*/
1409 {
1410 MenuChoice menu[4];
1411
1412 menu[0].str=mystrmalloc(_("lL)eft-right")); menu[0].c='\0';
1413 menu[1].str=mystrmalloc(_("uU)pside-down")); menu[1].c='\0';
1414 menu[2].str=mystrmalloc(_("fF)ront-back")); menu[2].c='\0';
1415 menu[3].str=(char*)0;
1416 reply=line_menu(_("Mirror block:"),menu,0);
1417 free(menu[0].str);
1418 free(menu[1].str);
1419 free(menu[2].str);
1420 if (reply<0) return reply;
1421 }
1422 /*}}}*/
1423 switch (reply)
1424 {
1425 /* 0 -- left-right */ /*{{{*/
1426 case 0: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_X); break;
1427 /*}}}*/
1428 /* 1 -- upside-down */ /*{{{*/
1429 case 1: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_Y); break;
1430 /*}}}*/
1431 /* 2 -- front-back */ /*{{{*/
1432 case 2: mirrorblock(sheet,x1,y1,z1,x2,y2,z2,IN_Z); break;
1433 /*}}}*/
1434 default: assert(0);
1435 }
1436 return 0;
1437 }
1438 /*}}}*/
1439 /* do_goto -- go to a specific cell */ /*{{{*/
do_goto(Sheet * sheet,const char * expr)1440 static int do_goto(Sheet *sheet, const char *expr)
1441 {
1442 /* variables */ /*{{{*/
1443 char buf[1024];
1444 const char *s;
1445 size_t x,offx;
1446 Token **t;
1447 int c;
1448 /*}}}*/
1449
1450 assert(sheet!=(Sheet*)0);
1451 buf[0]='\0';
1452 x=offx=0;
1453 if (expr) strcpy(buf,expr);
1454 else if ((c=line_edit(sheet,buf,sizeof(buf),_("Go to location:"),&x,&offx))<0) return c;
1455 s=buf;
1456 t=scan(&s);
1457 if (t!=(Token**)0)
1458 {
1459 Token value;
1460
1461 upd_x=sheet->curx;
1462 upd_y=sheet->cury;
1463 upd_z=sheet->curz;
1464 upd_sheet=sheet;
1465 value=eval(t);
1466 tvecfree(t);
1467 if (value.type==LOCATION && value.u.location[0]>=0 && value.u.location[1]>=0 && value.u.location[2]>=0)
1468 moveto(sheet,value.u.location[0],value.u.location[1],value.u.location[2]);
1469 else
1470 line_msg(_("Go to location:"),_("Not a valid location"));
1471 tfree(&value);
1472 }
1473 return -1;
1474 }
1475 /*}}}*/
1476
1477 /* do_sheetcmd -- process one key press */ /*{{{*/
do_sheetcmd(Sheet * cursheet,Key c,int moveonly)1478 int do_sheetcmd(Sheet *cursheet, Key c, int moveonly)
1479 {
1480 switch ((int)c)
1481 {
1482 case K_GOTO: do_goto(cursheet, (const char *)0); break;
1483 case K_COLWIDTH: do_columnwidth(cursheet); break;
1484 case BLOCK_CLEAR: do_clear(cursheet); redraw_sheet(cursheet); break;
1485 case BLOCK_INSERT: do_insert(cursheet); redraw_sheet(cursheet); break;
1486 case BLOCK_DELETE: do_delete(cursheet); redraw_sheet(cursheet); break;
1487 case BLOCK_MOVE: do_move(cursheet,0,0); redraw_sheet(cursheet); break;
1488 case BLOCK_COPY: do_move(cursheet,1,0); redraw_sheet(cursheet); break;
1489 case BLOCK_FILL: do_fill(cursheet); redraw_sheet(cursheet); break;
1490 case BLOCK_SORT: do_sort(cursheet); redraw_sheet(cursheet); break;
1491 case BLOCK_MIRROR: do_mirror(cursheet); redraw_sheet(cursheet); break;
1492 case ADJUST_LEFT:
1493 case ADJUST_RIGHT:
1494 case ADJUST_CENTER:
1495 case ADJUST_SCIENTIFIC:
1496 case ADJUST_PRECISION:
1497 case ADJUST_SHADOW:
1498 case ADJUST_BOLD:
1499 case ADJUST_UNDERLINE:
1500 case ADJUST_TRANSPARENT:
1501 case ADJUST_LABEL:
1502 case ADJUST_LOCK:
1503 case ADJUST_IGNORE: do_attribute(cursheet, c); break;
1504 /* UP -- move up */ /*{{{*/
1505 case K_UP:
1506 {
1507 relmoveto(cursheet, 0, -1, 0);
1508 break;
1509 }
1510 /*}}}*/
1511 /* DOWN -- move down */ /*{{{*/
1512 case K_DOWN:
1513 {
1514 relmoveto(cursheet, 0, 1, 0);
1515 break;
1516 }
1517 /*}}}*/
1518 /* LEFT -- move left */ /*{{{*/
1519 case K_LEFT:
1520 {
1521 relmoveto(cursheet, -1, 0, 0);
1522 break;
1523 }
1524 /*}}}*/
1525 /* RIGHT -- move right */ /*{{{*/
1526 case K_RIGHT:
1527 {
1528 relmoveto(cursheet, 1, 0, 0);
1529 break;
1530 }
1531 /*}}}*/
1532 /* FIRSTL -- move to first line */ /*{{{*/
1533 case K_FIRSTL:
1534 case '<':
1535 {
1536 moveto(cursheet, -1, 0, -1);
1537 break;
1538 }
1539 /*}}}*/
1540 /* LASTL -- move to last line */ /*{{{*/
1541 case K_LASTL:
1542 case '>':
1543 {
1544 moveto(cursheet, -1, (cursheet->dimy ? cursheet->dimy-1 : 0), -1);
1545 break;
1546 }
1547 /*}}}*/
1548 /* HOME -- move to beginning of line */ /*{{{*/
1549 case K_HOME:
1550 {
1551 moveto(cursheet, 0, -1, -1);
1552 break;
1553 }
1554 /*}}}*/
1555 /* END -- move to end of line */ /*{{{*/
1556 case K_END:
1557 {
1558 moveto(cursheet, (cursheet->dimx ? cursheet->dimx-1 : 0), -1, -1);
1559 break;
1560 }
1561 /*}}}*/
1562 /* + -- move one sheet down */ /*{{{*/
1563 case K_NSHEET:
1564 case '+':
1565 {
1566 relmoveto(cursheet, 0, 0, 1);
1567 break;
1568 }
1569 /*}}}*/
1570 /* - -- move one sheet up */ /*{{{*/
1571 case K_PSHEET:
1572 case '-':
1573 {
1574 relmoveto(cursheet, 0, 0, -1);
1575 break;
1576 }
1577 /*}}}*/
1578 /* * -- move to bottom sheet */ /*{{{*/
1579 case K_LSHEET:
1580 case '*':
1581 {
1582 moveto(cursheet, -1, -1, (cursheet->dimz ? cursheet->dimz-1 : 0));
1583 break;
1584 }
1585 /*}}}*/
1586 /* _ -- move to top sheet */ /*{{{*/
1587 case K_FSHEET:
1588 case '_':
1589 {
1590 moveto(cursheet, -1, -1, 0);
1591 break;
1592 }
1593 /*}}}*/
1594 /* ENTER -- edit current cell */ /*{{{*/
1595 case K_ENTER: if (moveonly) break; do_edit(cursheet,'\0',(const char*)0,0); break;
1596 /*}}}*/
1597 /* MENTER -- edit current clocked cell */ /*{{{*/
1598 case K_MENTER: if (moveonly) break; do_edit(cursheet,'\0',(const char*)0,1); break;
1599 /*}}}*/
1600 /* ", @, digit -- edit current cell with character already in buffer */ /*{{{*/
1601 case K_BACKSPACE:
1602 case K_DC:
1603 case '"':
1604 case '@':
1605 case '0':
1606 case '1':
1607 case '2':
1608 case '3':
1609 case '4':
1610 case '5':
1611 case '6':
1612 case '7':
1613 case '8':
1614 case '9': if (moveonly) break; do_edit(cursheet,c,(const char*)0,0); break;
1615 /*}}}*/
1616 /* MARK -- toggle block marking */ /*{{{*/
1617 case '.':
1618 case K_MARK: if (moveonly) break; do_mark(cursheet,0); break;
1619 /*}}}*/
1620 /* _("Save sheet file format:") -- save menu */ /*{{{*/
1621 case K_SAVEMENU: if (moveonly) break; do_save(cursheet); break;
1622 /*}}}*/
1623 /* _("Load sheet file format:") -- load menu */ /*{{{*/
1624 case K_LOAD:
1625 case K_LOADMENU: if (moveonly) break; do_load(cursheet); break;
1626 /*}}}*/
1627 /* _("nN)ame") -- set name */ /*{{{*/
1628 case K_NAME: if (moveonly) break; do_name(cursheet); break;
1629 /*}}}*/
1630 #ifdef ENABLE_HELP
1631 case K_HELP: show_text(helpfile); break;
1632 #else
1633 case K_HELP: show_text(_("Sorry, manual is not installed.")); break;
1634 #endif
1635 case K_ABOUT: show_text(_("<html><head><title>About teapot</title></head><body><center><pre>\n\n"
1636 " ` ',` ' ' \n"
1637 " ` ' ` ' ' \n"
1638 " `' ' '`' \n"
1639 " ' ` ' '` \n"
1640 " ' '` ' ` '`` ` \n"
1641 " `. Table Editor And Planner, or: \n"
1642 " , . , , . . \n"
1643 " ` ' ` ' ' \n"
1644 " `::\\ /:::::::::::::::::\\ ___ \n"
1645 " `::\\ /:::::::::::::::::::\\,'::::\\ \n"
1646 " :::\\/:::::::::::::::::::::\\/ \\:\\ \n"
1647 " :::::::::::::::::::::::::::\\ ::: \n"
1648 " ::::::::::::::::::::::::::::; /:;' \n"
1649 " `::::::::::::::::::::::::::::_/:;' \n"
1650 " `::::::::::::::::::::::::::::' \n"
1651 " `////////////////////////' \n"
1652 " `:::::::::::::::::::::' \n"
1653 "</pre>\n"
1654 "<p>Teapot " VERSION "</p>\n"
1655 "\n"
1656 "<p>Original Version: Michael Haardt<br>\n"
1657 "Current Maintainer: Joerg Walter<br>\n"
1658 "Home Page: <a href='http://www.syntax-k.de/projekte/teapot/'>http://www.syntax-k.de/projekte/teapot/</a></p>\n"
1659 "\n"
1660 "<p>Copyright 1995-2006 Michael Haardt,<br>\n"
1661 "Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)</p></center>\n"
1662 "\f"
1663 "<p>This program is free software: you can redistribute it and/or modify\n"
1664 "it under the terms of the GNU General Public License as published by\n"
1665 "the Free Software Foundation, either version 3 of the License, or\n"
1666 "(at your option) any later version.</p>\n"
1667 "\n"
1668 "<p>This program is distributed in the hope that it will be useful,\n"
1669 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1670 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1671 "GNU General Public License for more details.</p>\n"
1672 "\n"
1673 "<p>You should have received a copy of the GNU General Public License\n"
1674 "along with this program. If not, see <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.</p>"
1675 "</body></html>"));
1676 break;
1677 /* MENU, / -- main menu */ /*{{{*/
1678 case '/': if (!moveonly && do_sheetcmd(cursheet, show_menu(cursheet), 0)) return 1; break;
1679 /*}}}*/
1680 /* _("sS)ave") -- save in current native format */ /*{{{*/
1681 case K_SAVE: do_save(cursheet); break;
1682 /*}}}*/
1683 /* _("cC)opy") -- copy block */ /*{{{*/
1684 case K_COPY: if (moveonly) break; do_move(cursheet,1,1); break;
1685 /*}}}*/
1686 /* RECALC -- recalculate */ /*{{{*/
1687 case K_RECALC: if (moveonly) break; forceupdate(cursheet); break;
1688 /*}}}*/
1689 /* _("Usage: clock(condition,location[,location])") -- clock */ /*{{{*/
1690 case K_CLOCK:
1691 {
1692 int x,y,z;
1693
1694 for (x=0; x<cursheet->dimx; ++x)
1695 for (y=0; y<cursheet->dimy; ++y)
1696 for (z=0; z<cursheet->dimz; ++z)
1697 clk(cursheet,x,y,z);
1698 update(cursheet);
1699 break;
1700 }
1701 /*}}}*/
1702 /* NPAGE -- page down */ /*{{{*/
1703 case K_NPAGE:
1704 {
1705 cursheet->offy+=(cursheet->maxy-3);
1706 relmoveto(cursheet, 0, cursheet->maxy-3, 0);
1707 break;
1708 }
1709 /*}}}*/
1710 /* PPAGE -- page up */ /*{{{*/
1711 case K_PPAGE:
1712 {
1713 cursheet->offy = (cursheet->offy>=(cursheet->maxy-3) ? cursheet->offy-(cursheet->maxy-3) : 0);
1714 relmoveto(cursheet, 0, (cursheet->cury>=(cursheet->maxy-3) ? -(cursheet->maxy-3) : -cursheet->cury), 0);
1715 break;
1716 }
1717 /*}}}*/
1718 /* FPAGE -- page right */ /*{{{*/
1719 case K_FPAGE:
1720 {
1721 cursheet->offx+=cursheet->width;
1722 relmoveto(cursheet, cursheet->width, 0, 0);
1723 break;
1724 }
1725 /*}}}*/
1726 /* BPAGE -- page left */ /*{{{*/
1727 case K_BPAGE:
1728 {
1729 cursheet->offx=(cursheet->offx>=cursheet->width ? cursheet->offx-cursheet->width : 0);
1730 relmoveto(cursheet, (cursheet->curx>=cursheet->width ? -cursheet->width : -cursheet->curx), 0, 0);
1731 break;
1732 }
1733 /*}}}*/
1734 /* SAVEQUIT -- save and quit */ /*{{{*/
1735 case K_SAVEQUIT:
1736 {
1737 if (moveonly) break;
1738 if (do_save(cursheet)!=-2) return 1;
1739 break;
1740 }
1741 /*}}}*/
1742 /* _("qQ)uit") -- quit */ /*{{{*/
1743 case K_QUIT: if (moveonly) break; return 1;
1744 /*}}}*/
1745 default:
1746 if (isalpha(c) && !moveonly) do_edit(cursheet,c,(const char*)0,0);
1747 break;
1748 }
1749 return 0;
1750 }
1751 /*}}}*/
1752
1753 /* main */ /*{{{*/
main(int argc,char * argv[])1754 int main(int argc, char *argv[])
1755 {
1756 /* variables */ /*{{{*/
1757 Sheet sheet,*cursheet;
1758 int o;
1759 const char *loadfile;
1760 int always_redraw=0;
1761 char ln[1024];
1762 /*}}}*/
1763
1764 setlocale(LC_ALL, "");
1765 find_helpfile(helpfile, sizeof(helpfile), argv[0]);
1766
1767 /* parse options */ /*{{{*/
1768 while ((o=getopt(argc,argv,"abhnrqHp:?"))!=EOF) switch (o)
1769 {
1770 /* a -- use ascii as default */ /*{{{*/
1771 case 'a':
1772 {
1773 usexdr=0;
1774 break;
1775 }
1776 /*}}}*/
1777 /* b -- run batch */ /*{{{*/
1778 case 'b': batch=1; break;
1779 /*}}}*/
1780 /* n -- no quoted strings */ /*{{{*/
1781 case 'n': quote=0; break;
1782 /*}}}*/
1783 /* q -- force quoted strings */ /*{{{*/
1784 case 'q': quote=1; break;
1785 /*}}}*/
1786 /* H -- no row/column headers */ /*{{{*/
1787 case 'H': header=0; break;
1788 /*}}}*/
1789 /* r -- always redraw */ /*{{{*/
1790 case 'r':
1791 {
1792 always_redraw=1;
1793 break;
1794 }
1795 /*}}}*/
1796 /* p -- precision */ /*{{{*/
1797 case 'p':
1798 {
1799 long n;
1800 char *end;
1801
1802 n=strtol(optarg,&end,0);
1803 if (*end || n<0 || n>DBL_DIG)
1804 {
1805 fprintf(stderr,_("teapot: precision must be between 0 and %d.\n"),DBL_DIG);
1806 exit(1);
1807 }
1808 def_precision=n;
1809 break;
1810 }
1811 /*}}}*/
1812 /* default -- includes ? and h */ /*{{{*/
1813 default:
1814 {
1815 fprintf(stderr,_(
1816 "Usage: %s [-a] [-b] [-n] [-H] [-r] [-p digits] [file]\n"
1817 " -a: use ASCII file format as default\n"
1818 " -b: batch mode\n"
1819 " -q: display strings in quotes\n"
1820 " -H: hide row/column headers\n"
1821 " -r: redraw more often\n"
1822 " -p: set decimal precision\n"
1823 ), argv[0]);
1824 exit(1);
1825 }
1826 /*}}}*/
1827 }
1828 loadfile=(optind<argc ? argv[optind] : (const char*)0);
1829 /*}}}*/
1830 /* create empty sheet */ /*{{{*/
1831 cursheet=&sheet;
1832 cursheet->curx=cursheet->cury=cursheet->curz=0;
1833 cursheet->offx=cursheet->offy=0;
1834 cursheet->dimx=cursheet->dimy=cursheet->dimz=0;
1835 cursheet->sheet=(Cell**)0;
1836 cursheet->column=(int*)0;
1837 cursheet->orix=0;
1838 cursheet->oriy=0;
1839 cursheet->maxx=0;
1840 cursheet->maxy=0;
1841 cursheet->name=(char*)0;
1842 cursheet->mark1x=-1;
1843 cursheet->marking=0;
1844 cursheet->changed=0;
1845 cursheet->moveonly=0;
1846 cursheet->clk=0;
1847 (void)memset(cursheet->labelcache,0,sizeof(cursheet->labelcache));
1848 /*}}}*/
1849 /* start display */ /*{{{*/
1850 if (!batch) {
1851 display_init(&sheet, always_redraw);
1852 line_msg((const char*)0,"");
1853 }
1854 /*}}}*/
1855 if (loadfile) /* load given sheet */ /*{{{*/
1856 {
1857 const char *msg;
1858
1859 cursheet->name=mystrmalloc(loadfile);
1860 if (usexdr)
1861 {
1862 if ((msg=loadxdr(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from XDR file:"),msg);
1863 }
1864 else
1865 {
1866 if ((msg=loadport(cursheet,cursheet->name))!=(const char*)0) line_msg(_("Load sheet from ASCII file:"),msg);
1867 }
1868 }
1869 /*}}}*/
1870 if (batch) /* process batch */ /*{{{*/
1871 while (fgets(ln,sizeof(ln),stdin)!=(char*)0)
1872 {
1873 /* variables */ /*{{{*/
1874 size_t len;
1875 char *cmd,*arg;
1876 /*}}}*/
1877
1878 /* set cmd and arg */ /*{{{*/
1879 ++batchln;
1880 len=strlen(ln);
1881 if (len && ln[len-1]=='\n') ln[len-1]='\0';
1882 cmd=ln; while (isspace((int)*cmd)) ++cmd;
1883 arg=cmd;
1884 while (*arg && !isspace((int)*arg)) ++arg;
1885 while (isspace((int)*arg)) *arg++='\0';
1886 /*}}}*/
1887
1888 /* goto location */ /*{{{*/
1889 if (strcmp(cmd,"goto")==0) do_goto(cursheet,arg);
1890 /*}}}*/
1891 /* from location */ /*{{{*/
1892 else if (strcmp(cmd,"from")==0)
1893 {
1894 do_goto(cursheet,arg);
1895 do_mark(cursheet,1);
1896 }
1897 /*}}}*/
1898 /* to location */ /*{{{*/
1899 else if (strcmp(cmd,"to")==0)
1900 {
1901 do_goto(cursheet,arg);
1902 do_mark(cursheet,2);
1903 }
1904 /*}}}*/
1905 /* save-tbl file */ /*{{{*/
1906 else if (strcmp(cmd,"save-tbl")==0) do_savetbl(cursheet,arg);
1907 /*}}}*/
1908 /* save-latex file */ /*{{{*/
1909 else if (strcmp(cmd,"save-latex")==0) do_savelatex(cursheet,arg);
1910 /*}}}*/
1911 /* save-context file */ /*{{{*/
1912 else if (strcmp(cmd,"save-context")==0) do_savecontext(cursheet,arg);
1913 /*}}}*/
1914 /* save-csv file */ /*{{{*/
1915 else if (strcmp(cmd,"save-csv")==0) do_savecsv(cursheet,arg);
1916 /*}}}*/
1917 /* save-html file */ /*{{{*/
1918 else if (strcmp(cmd,"save-html")==0) do_savehtml(cursheet,arg);
1919 /*}}}*/
1920 /* load-csv file */ /*{{{*/
1921 else if (strcmp(cmd,"load-csv")==0) { loadcsv(cursheet,arg); forceupdate(cursheet); }
1922 /*}}}*/
1923 /* sort in x direction */ /*{{{*/
1924 else if (strcmp(cmd,"sort-x")==0) do_batchsort(cursheet, IN_X, arg);
1925 /*}}}*/
1926 /* sort in y direction */ /*{{{*/
1927 else if (strcmp(cmd,"sort-y")==0) do_batchsort(cursheet, IN_Y, arg);
1928 /*}}}*/
1929 /* sort in z direction */ /*{{{*/
1930 else if (strcmp(cmd,"sort-z")==0) do_batchsort(cursheet, IN_Z, arg);
1931 /*}}}*/
1932 /* this is an unknown command */ /*{{{*/
1933 else line_msg(_("Unknown batch command:"),cmd);
1934 /*}}}*/
1935 }
1936 /*}}}*/
1937 else /* process interactive input */ /*{{{*/
1938 {
1939 display_main(cursheet);
1940 display_end();
1941 }
1942 /*}}}*/
1943 freesheet(cursheet,1);
1944 fclose(stdin);
1945 return 0;
1946 }
1947 /*}}}*/
1948