Reset parser in grace_set_project().
[grace.git] / src / utils.c
blob38c3f460bc5f38f245f98a66b47ad92913deb897
1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
3 *
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
5 *
6 * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
7 * Copyright (c) 1996-2003 Grace Development Team
8 *
9 * Maintained by Evgeny Stambulchik
12 * All Rights Reserved
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * misc utilities
34 #include <config.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <ctype.h>
40 #include <string.h>
41 #include <pwd.h>
42 #include <signal.h>
43 #include <sys/types.h>
44 #include <sys/resource.h>
45 #ifdef HAVE_SYS_SELECT_H
46 # include <sys/select.h>
47 #endif
48 #include <limits.h>
50 #ifdef HAVE_SETLOCALE
51 # include <locale.h>
52 #endif
54 #include "globals.h"
55 #include "utils.h"
56 #include "files.h"
57 #include "dicts.h"
58 #include "protos.h"
60 static void rereadConfig(Grace *grace);
61 static RETSIGTYPE actOnSignal(int signo);
64 * swap doubles and ints
66 void fswap(double *x, double *y)
68 double tmp;
70 tmp = *x;
71 *x = *y;
72 *y = tmp;
75 void iswap(int *x, int *y)
77 int tmp;
79 tmp = *x;
80 *x = *y;
81 *y = tmp;
84 int isoneof(int c, char *s)
86 while (*s) {
87 if (c == *s) {
88 return 1;
89 } else {
90 s++;
93 return 0;
96 int argmatch(char *s1, char *s2, int atleast)
98 int l1 = strlen(s1);
99 int l2 = strlen(s2);
101 if (l1 < atleast) {
102 return 0;
104 if (l1 > l2) {
105 return 0;
107 return (strncmp(s1, s2, l1) == 0);
111 * convert a string from lower to upper case
112 * leaving quoted strings alone
114 void lowtoupper(char *s)
116 unsigned int i, quoteon = FALSE;
118 for (i = 0; i < strlen(s); i++) {
119 if (s[i] == '"') {
120 if (!quoteon) {
121 quoteon = TRUE;
122 } else if ((i > 0) && (s[i-1] != '\\')) {
123 quoteon = FALSE;
126 if (quoteon == FALSE) {
127 if (!isprint(s[i])) {
128 s[i] = ' ';
129 } else if (s[i] >= 'a' && s[i] <= 'z') {
130 s[i] -= ' ';
137 * remove all that fortran nastiness
139 void convertchar(char *s)
141 while (*s++) {
142 if (*s == ',')
143 *s = ' ';
144 if (*s == 'D' || *s == 'd')
145 *s = 'e';
149 char *dayofweekstrs[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
150 char *dayofweekstrl[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
151 char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
152 char *monthl[] = {"January", "February", "March", "April", "May", "June",
153 "July", "August", "September", "October", "November", "December"};
155 int dayofweek(double j)
157 int i = (int) floor(j + 1.5);
158 return (i <= 0) ? 6 - (6 - i)%7 : i%7;
162 * escape quotes
164 char *escapequotes (char *s)
166 static char *es = NULL;
167 int i, k, n, len, elen;
169 if (s == NULL)
170 return NULL;
172 len = strlen(s);
173 es = xrealloc(es, (len + 1)*SIZEOF_CHAR);
174 strcpy(es, s);
175 n = 0;
176 while ((es = strchr(es, '\"'))) {
177 es++;
178 n++;
181 elen = len + n + 1;
182 es = xrealloc(es, elen*SIZEOF_CHAR);
184 i = k = 0;
185 while (i < len) {
186 if (s[i] == '\"') {
187 es[k] = '\\';
188 k++;
190 es[k] = s[i];
191 i++; k++;
193 es[elen-1] = '\0';
194 return es;
197 double mytrunc(double a)
199 if (a > 0.0) {
200 return floor(a);
201 } else {
202 return ceil(a);
207 * exit grace
209 void bailout(Grace *grace)
211 if ((grace->project && !quark_dirtystate_get(grace->project)) ||
212 yesno("Exit losing unsaved changes?", NULL, NULL, NULL)) {
213 grace_free(grace);
214 exit(0);
219 * Reread config (TODO)
221 static void rereadConfig(Grace *grace)
223 getparms(grace, "gracerc");
226 static void please_report_the_bug(void)
228 fprintf(stderr, "\nPlease use \"Help/Comments\" to report the bug.\n");
229 #ifdef HAVE_LESSTIF
230 fprintf(stderr, "NB: This version of Grace was compiled with LessTif.\n");
231 fprintf(stderr, " Make sure to read the FAQ carefully prior to\n");
232 fprintf(stderr, " reporting the bug, ESPECIALLY if the problem might\n");
233 fprintf(stderr, " be related to the graphical interface.\n");
234 #endif
238 * Warn about a possible bug displaying the passed message, try to save
239 * any unsaved work and abort
241 void emergency_exit(Grace *grace, int is_my_bug, char *msg)
244 * Since we got so far, memory is probably corrupted so it's better to use
245 * a static storage
247 static char buf[GR_MAXPATHLEN];
249 if (grace->rt->emergency_save != FALSE) {
250 /* don't mind signals anymore: we're in emergency save mode already */
251 grace->rt->interrupts++;
252 if (grace->rt->interrupts > 10) {
253 fprintf(stderr, "oh, no luck :-(\n");
254 please_report_the_bug();
255 abort();
257 return;
258 } else {
259 grace->rt->emergency_save = TRUE;
260 grace->rt->interrupts = 0;
261 fprintf(stderr, "\a\nOops! %s\n", msg);
262 if (quark_dirtystate_get(grace->project)) {
263 strcpy(buf, project_get_docname(grace->project));
264 strcat(buf, "$");
265 fprintf(stderr, "Trying to save your work into file \"%s\"... ", buf);
266 fflush(stderr);
267 grace->gui->noask = TRUE;
268 if (save_project(grace->project, buf) == RETURN_SUCCESS) {
269 fprintf(stderr, "ok!\n");
270 } else {
271 fprintf(stderr, "oh, no luck :-(\n");
274 if (is_my_bug) {
275 please_report_the_bug();
277 abort();
282 * Signal-handling routines
285 static RETSIGTYPE actOnSignal(int signo)
287 char *signame, buf[32];
289 installSignal();
291 switch (signo) {
292 #ifdef SIGHUP
293 case SIGHUP:
294 rereadConfig(grace);
295 break;
296 #endif
297 #ifdef SIGINT
298 case SIGINT:
299 #endif
300 #ifdef SIGQUIT
301 case SIGQUIT:
302 #endif
303 #ifdef SIGTERM
304 case SIGTERM:
305 #endif
306 bailout(grace);
307 break;
308 #ifdef SIGILL
309 case SIGILL:
310 signame = "SIGILL";
311 #endif
312 #ifdef SIGFPE
313 case SIGFPE:
314 signame = "SIGFPE";
315 #endif
316 #ifdef SIGBUS
317 case SIGBUS:
318 signame = "SIGBUS";
319 #endif
320 #ifdef SIGSEGV
321 case SIGSEGV:
322 signame = "SIGSEGV";
323 #endif
324 #ifdef SIGSYS
325 case SIGSYS:
326 signame = "SIGSYS";
327 #endif
328 sprintf(buf, "Got fatal signal %s!", signame);
329 emergency_exit(grace, TRUE, buf);
330 break;
331 default:
332 /* ignore the rest */
333 break;
337 void installSignal(void){
338 #ifdef SIGHUP
339 signal(SIGHUP, actOnSignal); /* hangup */
340 #endif
341 #ifdef SIGINT
342 signal(SIGINT, actOnSignal); /* interrupt */
343 #endif
344 #ifdef SIGQUIT
345 signal(SIGQUIT, actOnSignal); /* quit */
346 #endif
347 #ifdef SIGILL
348 signal(SIGILL, actOnSignal); /* illegal instruction */
349 #endif
350 #ifdef SIGFPE
351 signal(SIGFPE, actOnSignal); /* floating point exception */
352 #endif
353 #ifdef SIGBUS
354 signal(SIGBUS, actOnSignal); /* bus error */
355 #endif
356 #ifdef SIGSEGV
357 signal(SIGSEGV, actOnSignal); /* segmentation violation */
358 #endif
359 #ifdef SIGSYS
360 signal(SIGSYS, actOnSignal); /* bad argument to system call */
361 #endif
362 #ifdef SIGTERM
363 signal(SIGTERM, actOnSignal); /* software termination signal */
364 #endif
365 #ifdef SIGALRM
366 signal(SIGALRM, actOnSignal); /* timer */
367 #endif
368 #ifdef SIGIO
369 signal(SIGIO, actOnSignal); /* input/output ready */
370 #endif
373 /* create format string */
374 char *create_fstring(const Quark *q, int form, int prec, double loc, int type)
376 char format[64], eng_prefix[6];
377 static char s[MAX_STRING_LENGTH];
378 double tmp;
379 int m, d, y, h, mm, sec;
380 double arcmin, arcsec;
381 int exponent;
382 double mantissa;
383 int yprec;
384 Project *pr = project_get_data(q);
386 if (pr->two_digits_years) {
387 yprec = 2;
388 } else {
389 yprec = 4;
392 /* for locale decimal points */
393 set_locale_num(TRUE);
395 strcpy(format, "%.*lf");
396 switch (form) {
397 case FORMAT_DECIMAL:
398 sprintf(s, format, prec, loc);
399 tmp = atof(s); /* fix reverse axes problem when loc == -0.0 */
400 if (tmp == 0.0) {
401 strcpy(format, "%.*lf");
402 loc = 0.0;
403 sprintf(s, format, prec, loc);
405 break;
406 case FORMAT_EXPONENTIAL:
407 strcpy(format, "%.*le");
408 sprintf(s, format, prec, loc);
409 tmp = atof(s); /* fix reverse axes problem when loc == -0.0 */
410 if (tmp == 0.0) {
411 strcpy(format, "%.*le");
412 loc = 0.0;
413 sprintf(s, format, prec, loc);
415 break;
416 case FORMAT_SCIENTIFIC:
417 if (loc != 0.0) {
418 exponent = (int) floor(log10(fabs(loc)));
419 mantissa = loc/pow(10.0, (double) exponent);
420 if (type == LFORMAT_TYPE_EXTENDED) {
421 strcpy(format, "%.*f\\x\\c4\\C\\f{}10\\S%d\\N");
422 } else {
423 strcpy(format, "%.*fx10(%d)");
425 sprintf(s, format, prec, mantissa, exponent);
426 } else {
427 strcpy(format, "%.*f");
428 sprintf(s, format, prec, 0.0);
430 break;
431 case FORMAT_ENGINEERING:
432 if (loc != 0.0) {
433 exponent = (int) floor(log10(fabs(loc)));
434 if (exponent < -18) {
435 exponent = -18;
436 } else if (exponent > 18) {
437 exponent = 18;
438 } else {
439 exponent = (int) floor((double) exponent/3)*3;
441 } else {
442 exponent = 0;
444 switch (exponent) {
445 case -18: /* atto */
446 strcpy(eng_prefix, "a");
447 break;
448 case -15: /* fempto */
449 strcpy(eng_prefix, "f");
450 break;
451 case -12: /* pico */
452 strcpy(eng_prefix, "p");
453 break;
454 case -9: /* nano */
455 strcpy(eng_prefix, "n");
456 break;
457 case -6: /* micro */
458 if (type == LFORMAT_TYPE_EXTENDED) {
459 strcpy(eng_prefix, "\\xm\\f{}");
460 } else {
461 strcpy(eng_prefix, "mk");
463 break;
464 case -3: /* milli */
465 strcpy(eng_prefix, "m");
466 break;
467 case 3: /* kilo */
468 strcpy(eng_prefix, "k");
469 break;
470 case 6: /* Mega */
471 strcpy(eng_prefix, "M");
472 break;
473 case 9: /* Giga */
474 strcpy(eng_prefix, "G");
475 break;
476 case 12: /* Tera */
477 strcpy(eng_prefix, "T");
478 break;
479 case 15: /* Peta */
480 strcpy(eng_prefix, "P");
481 break;
482 case 18: /* Exza (spelling?) */
483 strcpy(eng_prefix, "E");
484 break;
485 default:
486 strcpy(eng_prefix, "");
487 break;
489 strcpy(format, "%.*f %s");
490 sprintf(s, format, prec, loc/(pow(10.0, exponent)), eng_prefix);
491 break;
492 case FORMAT_POWER:
493 if (loc < 0.0) {
494 loc = log10(-loc);
495 if (type == LFORMAT_TYPE_EXTENDED) {
496 strcpy(format, "-10\\S%.*lf\\N");
497 } else {
498 strcpy(format, "-10(%.*lf)\\N");
500 } else if (loc == 0.0) {
501 sprintf(format, "%.*f", prec, 0.0);
502 } else {
503 loc = log10(loc);
504 if (type == LFORMAT_TYPE_EXTENDED) {
505 strcpy(format, "10\\S%.*lf\\N");
506 } else {
507 strcpy(format, "10(%.*lf)\\N");
510 sprintf(s, format, prec, loc);
511 break;
512 case FORMAT_GENERAL:
513 strcpy(format, "%.*lg");
514 sprintf(s, format, prec, loc);
515 tmp = atof(s);
516 if (tmp == 0.0) {
517 strcpy(format, "%lg");
518 loc = 0.0;
519 sprintf(s, format, loc);
521 break;
522 case FORMAT_DDMMYY:
523 strcpy(format, "%02d-%02d-%0*d");
524 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
525 sprintf(s, format, d, m, yprec, y);
526 break;
527 case FORMAT_MMDDYY:
528 strcpy(format, "%02d-%02d-%0*d");
529 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
530 sprintf(s, format, m, d, yprec, y);
531 break;
532 case FORMAT_YYMMDD:
533 strcpy(format, "%0*d-%02d-%02d");
534 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
535 sprintf(s, format, yprec, y, m, d);
536 break;
537 case FORMAT_MMYY:
538 strcpy(format, "%02d-%0*d");
539 jul_to_cal_and_time(q, loc, ROUND_MONTH, &y, &m, &d, &h, &mm, &sec);
540 sprintf(s, format, m, yprec, y);
541 break;
542 case FORMAT_MMDD:
543 strcpy(format, "%02d-%02d");
544 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
545 sprintf(s, format, m, d);
546 break;
547 case FORMAT_MONTHDAY:
548 strcpy(format, "%s-%02d");
549 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
550 if (m - 1 < 0 || m - 1 > 11) {
551 sprintf(s, format, "???");
552 } else {
553 sprintf(s, format, months[m - 1], d);
555 break;
556 case FORMAT_DAYMONTH:
557 strcpy(format, "%02d-%s");
558 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
559 if (m - 1 < 0 || m - 1 > 11) {
560 sprintf(s, format, "???");
561 } else {
562 sprintf(s, format, d, months[m - 1]);
564 break;
565 case FORMAT_MONTHS:
566 strcpy(format, "%s");
567 jul_to_cal_and_time(q, loc, ROUND_MONTH, &y, &m, &d, &h, &mm, &sec);
568 if (m - 1 < 0 || m - 1 > 11) {
569 sprintf(s, format, "???");
570 } else {
571 sprintf(s, format, months[m - 1]);
573 break;
574 case FORMAT_MONTHSY:
575 strcpy(format, "%s-%0*d");
576 jul_to_cal_and_time(q, loc, ROUND_MONTH, &y, &m, &d, &h, &mm, &sec);
577 if (m - 1 < 0 || m - 1 > 11) {
578 sprintf(s, format, "???");
579 } else {
580 sprintf(s, format, months[m - 1], yprec, y);
582 break;
583 case FORMAT_MONTHL:
584 strcpy(format, "%s");
585 jul_to_cal_and_time(q, loc, ROUND_MONTH, &y, &m, &d, &h, &mm, &sec);
586 if (m - 1 < 0 || m - 1 > 11) {
587 sprintf(s, format, "???");
588 } else {
589 sprintf(s, format, monthl[m - 1]);
591 break;
592 case FORMAT_DAYOFWEEKS:
593 strcpy(format, "%s");
594 sprintf(s, format, dayofweekstrs[dayofweek(loc + pr->ref_date)]);
595 break;
596 case FORMAT_DAYOFWEEKL:
597 strcpy(format, "%s");
598 sprintf(s, format, dayofweekstrl[dayofweek(loc + pr->ref_date)]);
599 break;
600 case FORMAT_DAYOFYEAR:
601 strcpy(format, "%d");
602 jul_to_cal_and_time(q, loc, ROUND_DAY, &y, &m, &d, &h, &mm, &sec);
603 sprintf(s, format,
604 1 + (int) (cal_to_jul(y, m, d) - cal_to_jul(y, 1, 1)));
605 break;
606 case FORMAT_HMS:
607 strcpy(format, "%02d:%02d:%02d");
608 jul_to_cal_and_time(q, loc, ROUND_SECOND, &y, &m, &d, &h, &mm, &sec);
609 sprintf(s, format, h, mm, sec);
610 break;
611 case FORMAT_MMDDHMS:
612 strcpy(format, "%02d-%02d %02d:%02d:%02d");
613 jul_to_cal_and_time(q, loc, ROUND_SECOND, &y, &m, &d, &h, &mm, &sec);
614 sprintf(s, format, m, d, h, mm, sec);
615 break;
616 case FORMAT_MMDDYYHMS:
617 strcpy(format, "%02d-%02d-%d %02d:%02d:%02d");
618 jul_to_cal_and_time(q, loc, ROUND_SECOND, &y, &m, &d, &h, &mm, &sec);
619 sprintf(s, format, m, d, y, h, mm, sec);
620 break;
621 case FORMAT_YYMMDDHMS:
622 strcpy(format, "%0*d-%02d-%02d %02d:%02d:%02d");
623 jul_to_cal_and_time(q, loc, ROUND_SECOND, &y, &m, &d, &h, &mm, &sec);
624 sprintf(s, format, yprec, y, m, d, h, mm, sec);
625 break;
626 case FORMAT_DEGREESLON:
627 if (loc < 0.0) {
628 loc *= -1.0;
629 strcpy(format, "%.*lfW");
630 } else if (loc > 0.0) {
631 strcpy(format, "%.*lfE");
632 } else {
633 strcpy(format, "0");
635 sprintf(s, format, prec, loc);
636 break;
637 case FORMAT_DEGREESMMLON:
638 if (loc < 0.0) {
639 loc *= -1.0;
640 strcpy(format, "%d %.*lf' W");
641 } else if (loc > 0.0) {
642 strcpy(format, "%d %.*lf' E");
643 } else {
644 strcpy(format, "0 0'");
646 y = loc;
647 arcmin = (loc - y) * 60.0;
648 sprintf(s, format, y, prec, arcmin);
649 break;
650 case FORMAT_DEGREESMMSSLON:
651 if (loc < 0.0) {
652 loc *= -1.0;
653 strcpy(format, "%d %d' %.*lf\" W");
654 } else if (loc > 0.0) {
655 strcpy(format, "%d %d' %.*lf\" E");
656 } else {
657 strcpy(format, "0 0' 0\"");
659 y = loc;
660 arcsec = (loc - y) * 3600.0;
661 m = arcsec / 60.0;
662 arcsec = (arcsec - m * 60);
663 sprintf(s, format, y, m, prec, arcsec);
664 break;
665 case FORMAT_MMSSLON:
666 if (loc < 0.0) {
667 loc *= -1.0;
668 strcpy(format, "%d' %.*lf\" W");
669 } else if (loc > 0.0) {
670 strcpy(format, "%d' %.*lf\" E");
671 } else {
672 strcpy(format, "0 0' 0\"");
674 y = loc;
675 arcsec = (loc - y) * 3600.0;
676 m = arcsec / 60.0;
677 arcsec = (arcsec - m * 60);
678 sprintf(s, format, m, prec, arcsec);
679 break;
680 case FORMAT_DEGREESLAT:
681 if (loc < 0.0) {
682 loc *= -1.0;
683 strcpy(format, "%.*lfS");
684 } else if (loc > 0.0) {
685 strcpy(format, "%.*lfN");
686 } else {
687 strcpy(format, "0");
689 sprintf(s, format, prec, loc);
690 break;
691 case FORMAT_DEGREESMMLAT:
692 if (loc < 0.0) {
693 loc *= -1.0;
694 strcpy(format, "%d %.*lf' S");
695 } else if (loc > 0.0) {
696 strcpy(format, "%d %.*lf' N");
697 } else {
698 strcpy(format, "0 0'");
700 y = loc;
701 arcsec = (loc - y) * 60.0;
702 sprintf(s, format, y, prec, arcsec);
703 break;
704 case FORMAT_DEGREESMMSSLAT:
705 if (loc < 0.0) {
706 loc *= -1.0;
707 strcpy(format, "%d %d' %.*lf\" S");
708 } else if (loc > 0.0) {
709 strcpy(format, "%d %d' %.*lf\" N");
710 } else {
711 strcpy(format, "0 0' 0\"");
713 y = loc;
714 arcsec = (loc - y) * 3600.0;
715 m = arcsec / 60.0;
716 arcsec = (arcsec - m * 60);
717 sprintf(s, format, y, m, prec, arcsec);
718 break;
719 case FORMAT_MMSSLAT:
720 if (loc < 0.0) {
721 loc *= -1.0;
722 strcpy(format, "%d' %.*lf\" S");
723 } else if (loc > 0.0) {
724 strcpy(format, "%d' %.*lf\" N");
725 } else {
726 strcpy(format, "0 0' 0\"");
728 y = loc;
729 arcsec = (loc - y) * 3600.0;
730 m = arcsec / 60.0;
731 arcsec = (arcsec - m * 60);
732 sprintf(s, format, m, prec, arcsec);
733 break;
734 default:
735 sprintf(s, format, prec, loc);
736 break;
739 /* revert to POSIX */
740 set_locale_num(FALSE);
742 return(s);
745 char *get_grace_home(const Grace *grace)
747 return grace->rt->grace_home;
750 char *get_print_cmd(const Grace *grace)
752 return grace->rt->print_cmd;
755 void set_print_cmd(Grace *grace, const char *cmd)
757 grace->rt->print_cmd = copy_string(grace->rt->print_cmd, cmd);
760 char *get_editor(const Grace *grace)
762 return grace->rt->grace_editor;
765 void set_editor(Grace *grace, const char *cmd)
767 grace->rt->grace_editor = copy_string(grace->rt->grace_editor, cmd);
770 char *get_help_viewer(const Grace *grace)
772 return grace->rt->help_viewer;
775 void set_help_viewer(Grace *grace, const char *dir)
777 grace->rt->help_viewer = copy_string(grace->rt->help_viewer, dir);
780 char *get_docbname(const Quark *q)
782 return QIDSTR(q);
786 void errmsg(const char *buf)
788 #ifdef NONE_GUI
789 fprintf(stderr, "%s\n", buf);
790 #else
791 if (grace->gui->inwin) {
792 errwin(buf);
793 } else {
794 fprintf(stderr, "%s\n", buf);
796 #endif
799 int yesnoterm(char *msg)
801 return TRUE;
804 int yesno(char *msg, char *s1, char *s2, char *help_anchor)
806 if (grace->gui->noask) {
807 return TRUE;
809 #ifdef NONE_GUI
810 return (yesnoterm(msg));
811 #else
812 if (grace->gui->inwin) {
813 return (yesnowin(msg, s1, s2, help_anchor));
814 } else {
815 return (yesnoterm(msg));
817 #endif
820 void stufftext(char *s)
822 #ifdef NONE_GUI
823 printf(s);
824 #else
825 if (grace->gui->inwin) {
826 stufftextwin(s);
827 } else {
828 printf(s);
830 #endif
831 /* log results to file */
832 if (grace->rt->resfp != NULL) {
833 fprintf(grace->rt->resfp, s);
838 char *mybasename(const char *s)
840 int start, end;
841 static char basename[GR_MAXPATHLEN];
843 s = path_translate(s);
844 if (s == NULL) {
845 errmsg("Could not translate basename:");
846 return "???";
849 end = strlen(s) - 1;
851 /* root is a special case */
852 if (end == 0 && *s == '/'){
853 basename[0] = '/';
854 return basename;
857 /* strip trailing white space and slashes */
858 while (s[end] == '/' || s[end] == ' ' || s[end] == '\t') {
859 end--;
861 /* find start of basename */
862 start = end;
863 do {
864 start--;
865 } while (start >= 0 && s[start] != '/');
867 strncpy(basename, s + (start + 1), end - start);
868 basename[end - start] = '\0';
869 return basename;
872 int set_workingdir(Grace *grace, const char *wd)
874 char buf[GR_MAXPATHLEN];
876 strncpy(buf, wd, GR_MAXPATHLEN - 1);
877 if (buf[0] == '~') {
878 expand_tilde(grace, buf);
880 if (chdir(buf) >= 0) {
881 grace->rt->workingdir = copy_string(grace->rt->workingdir, buf);
882 if (grace->rt->workingdir[strlen(grace->rt->workingdir) - 1] != '/') {
883 grace->rt->workingdir = concat_strings(grace->rt->workingdir, "/");
885 return RETURN_SUCCESS;
886 } else {
887 return RETURN_FAILURE;
891 char *get_workingdir(const Grace *grace)
893 return grace->rt->workingdir;
896 char *get_username(const Grace *grace)
898 return grace->rt->username;
901 char *get_userhome(const Grace *grace)
903 return grace->rt->userhome;
906 /* TODO this needs some work */
907 void expand_tilde(const Grace *grace, char *buf)
909 char buf2[GR_MAXPATHLEN];
911 if (buf[0] == '~') {
912 if (strlen(buf) == 1) {
913 strcpy(buf, get_userhome(grace));
914 } else if (buf[1] == '/') {
915 if (strlen(buf) > 2) {
916 strcpy(buf2, get_userhome(grace));
917 strcat(buf2, buf + 1);
918 strcpy(buf, buf2);
919 } else {
920 strcpy(buf, get_userhome(grace));
922 } else {
923 char tmp[128], *pp = tmp, *q = buf + 1;
924 struct passwd *pent;
926 while (*q && (*q != '/')) {
927 *pp++ = *q++;
929 *pp = 0;
930 if ((pent = getpwnam(tmp)) != NULL) {
931 strcpy(buf2, pent->pw_dir);
932 strcat(buf2, "/");
933 strcat(buf2, q);
934 strcpy(buf, buf2);
935 } else {
936 errmsg("No user by that name");
942 void echomsg(char *msg)
944 stufftext(msg);
945 stufftext("\n");
948 int system_wrap(const char *string)
950 return system(string);
953 void msleep_wrap(unsigned int msec)
955 struct timeval timeout;
956 timeout.tv_sec = msec / 1000;
957 timeout.tv_usec = 1000 * (msec % 1000);
958 select(0, NULL, NULL, NULL, &timeout);
961 #ifdef HAVE_SETLOCALE
962 static int need_locale = FALSE;
963 static char *system_locale_string, *posix_locale_string;
964 #endif
966 int init_locale(void)
968 #ifdef HAVE_SETLOCALE
969 char *s;
970 s = setlocale(LC_NUMERIC, "");
971 if (s == NULL) {
972 /* invalid/unsupported locale */
973 return RETURN_FAILURE;
974 } else if (!strcmp(s, "C")) {
975 /* don't enable need_locale, since the system locale is C */
976 return RETURN_SUCCESS;
977 } else {
978 system_locale_string = copy_string(NULL, s);
979 s = setlocale(LC_NUMERIC, "C");
980 posix_locale_string = copy_string(NULL, s);
981 need_locale = TRUE;
982 return RETURN_SUCCESS;
984 #else
985 return RETURN_SUCCESS;
986 #endif
989 void set_locale_num(int flag)
991 #ifdef HAVE_SETLOCALE
992 if (need_locale) {
993 if (flag == TRUE) {
994 setlocale(LC_NUMERIC, system_locale_string);
995 } else {
996 setlocale(LC_NUMERIC, posix_locale_string);
999 #endif
1002 #ifdef DEBUG
1003 void set_debuglevel(Grace *grace, int level)
1005 grace->rt->debuglevel = level;
1008 int get_debuglevel(Grace *grace)
1010 return grace->rt->debuglevel;
1012 #endif
1014 char *q_labeling(Quark *q)
1016 RunTime *rt = rt_from_quark(q);
1017 char *buf;
1018 tickmarks *t;
1019 DObject *o;
1020 region *r;
1022 buf = xmalloc(strlen(QIDSTR(q)) + 128);
1023 if (!buf) {
1024 return NULL;
1027 switch (quark_fid_get(q)) {
1028 case QFlavorProject:
1029 sprintf(buf, "Project \"%s%s\" (%d graphs)", QIDSTR(q),
1030 quark_dirtystate_get(q) ? "*":"" , number_of_graphs(q));
1032 break;
1033 case QFlavorFrame:
1034 sprintf(buf, "Frame \"%s%s\"", QIDSTR(q),
1035 quark_dirtystate_get(q) ? "*":"");
1037 break;
1038 case QFlavorGraph:
1039 sprintf(buf, "Graph \"%s%s\" (type: %s, sets: %d)",
1040 QIDSTR(q),
1041 quark_dirtystate_get(q) ? "*":"",
1042 graph_types(rt, graph_get_type(q)), number_of_sets(q));
1044 break;
1045 case QFlavorSet:
1046 sprintf(buf, "Set \"%s%s\" (%s)",
1047 QIDSTR(q), quark_dirtystate_get(q) ? "*":"",
1048 set_types(rt, set_get_type(q)));
1050 break;
1051 case QFlavorAxis:
1052 t = axis_get_data(q);
1054 sprintf(buf, "%c Axis \"%s%s\"",
1055 t->type == AXIS_TYPE_X ? 'X':'Y', QIDSTR(q),
1056 quark_dirtystate_get(q) ? "*":"");
1058 break;
1059 case QFlavorDObject:
1060 o = object_get_data(q);
1062 sprintf(buf, "DObject \"%s%s\" (%s)",
1063 QIDSTR(q), quark_dirtystate_get(q) ? "*":"",
1064 object_types(o->type));
1066 break;
1067 case QFlavorAText:
1068 sprintf(buf, "AText \"%s%s\"",
1069 QIDSTR(q), quark_dirtystate_get(q) ? "*":"");
1071 break;
1072 case QFlavorRegion:
1073 r = region_get_data(q);
1075 sprintf(buf, "Region \"%s%s\" (%d pts)",
1076 QIDSTR(q), quark_dirtystate_get(q) ? "*":"",
1077 r->n);
1079 break;
1080 default:
1081 sprintf(buf, "??? \"%s%s\"", QIDSTR(q),
1082 quark_dirtystate_get(q) ? "*":"");
1083 break;
1086 return buf;