blob: 1c68d54e93f10791c773a842f37e9b51f43f4611 [file] [log] [blame]
/* plot, unix plot file to graphics device translators.
Copyright (C) 1989 Free Software Foundation, Inc.
plot is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY. No author or distributor accepts responsibility to
anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GNU General Public License for full details.
Everyone is granted permission to copy, modify and redistribute plot,
but only under the conditions described in the GNU General Public
License. A copy of this license is supposed to have been given to you
along with plot so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies. */
/* This file is the main routine for plot.
It includes code to read the plot file and call plot functions
to draw the graphics. */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef sequent
#include <strings.h>
#else
#include <string.h>
#endif
#include <math.h>
#include "libplot.h"
/*
extern int perror();
extern int exit();
extern int printf();
extern int fprintf();
extern int fclose();
#ifndef mips
extern char *sprintf();
#endif
#ifndef hpux
extern void *malloc();
extern void *realloc();
#endif
extern int fputs();
*/
extern void perror(const char *s);
/* #include "../COPYING" */
enum plot_instruction
{
ALABEL = 'T',
ARC = 'a',
CIRCLE = 'c',
COLOR = 'C',
CONT = 'n',
ERASE = 'e',
FILL = 'L',
FONT = 'F',
FONTSIZE = 'S',
LABEL = 't',
LINE = 'l',
LINEMOD = 'f',
MOVE = 'm',
POINT = 'p',
ROTATE = 'r',
SPACE = 's'
};
/* This flag specifies that the input contains unsigned (if zero) or
signed (if nonzero) two byte intgers. The default is signed. */
int signed_input = 1;
/* read in two byte intgers with high_byte_first. The default is to read the low
byte first. */
int high_byte_first = 0;
/* guess_byte_order is a flag which, if non-zero, indicated that the function
find_byte_order should be used to guess the byte order for the input file. */
int guess_byte_order = 1;
/* swap_bytes returns the bottom two bytes of its integer argument with
their bytes reversed. */
int swap_bytes(int x)
{
unsigned char a, b;
a = x & 0xff;
b = (x >> 8) & 0xff;
return ((a << 8)|b);
}
/* This is a set of known values for the maximum x (abscissa) values
specified in the plot size command for known devices. Using this
set we can construct a heuristic proceedure for recognizing plot
files in which the bytes of two byte integers are reversed. We can
recognize these files by looking for size commands containing these
known sizes in byte reversed form. The last entry should be 0. */
int known_size[32] = {
504, /* plot3d output 504x504 */
2048, /* versatek plotter 2048x2048 */
2100, /* plot3d output */
3120, /* Tektronix 4010 terminal 3120x3120 */
4096, /* GSI 300 terminal 4096x4096 */
0 /* the last entry should be 0 */
};
/* find_byte_order takes four integer arguments and matches third one
against a set of known values (sizes, see above). If there is a match
it merely returns. If there is no match, it check each of the values
again with the bottom two bytes reversed. If such a match is found, the
bottom two bytes of each argument is reversed, the high_byte_first flag
is inverted to indicated how two byte integers should be read and the
runction returns. */
void find_byte_order(int *x0, int *y0, int *x1, int * y1)
{
int i;
for (i=0; known_size[i]!=0; i++)
{
if (*x1 == known_size[i])
return;
}
/* now check to see if reversing the bytes allows a match... */
for (i=0; known_size[i]!=0; i++)
{
if (*x1 == swap_bytes (known_size[i]))
{
*x0 = swap_bytes( *x0);
*y0 = swap_bytes( *y0);
*x1 = swap_bytes( *x1);
*y1 = swap_bytes( *y1);
high_byte_first = ! high_byte_first;
return;
}
}
}
/* Read a byte */
#define read_byte(stream) (getc (stream))
/* Read a coordinate - a two byte integer. */
int coord(FILE *input)
{
int x;
if ( high_byte_first )
{
x = ((char) read_byte(input)) << 8; /* get sign from high byte */
x |= read_byte(input) & 0xFF; /* not from low byte */
}
else
{
x = read_byte (input) & 0xFF; /* ingnore sign in low byte */
x |= ((char) read_byte (input)) << 8; /* get sign from high byte */
}
if ( ! signed_input )
{
x &= 0xFFFF;
}
return x;
}
/* Read a string, change termination to null.
note: string (buffer) reads a newline terminated string. */
void read_string (FILE *input, char *buffer, int buffer_length)
{
int length=0;
char termination = '\n';
char c = '\0';
while (!feof (input))
{
if (length > buffer_length)
{
buffer_length *= 2;
buffer = (char *) realloc (buffer, buffer_length);
if (buffer <= (char *) 0)
{
perror ("realloc failed:");
exit (-1);
}
}
c = read_byte (input);
if (c == termination)
break;
buffer [length++] = c;
}
buffer [length] = '\0'; /* null terminate label */
}
/* read_plot reads a plot file from the standard input and calls
a plot function according to each plot instruction found in the
file. */
void read_plot(FILE *in_stream, char *buffer, int buffer_length)
{
char x_adjust, y_adjust;
int x0, y0, x1, y1, x2, y2;
int instruction;
instruction = read_byte (in_stream);
while (!feof (in_stream))
{
switch (instruction)
{
/* Note: we must get all but the last argument before calling to
ensure reading them in the proper order. */
case ALABEL:
x_adjust = read_byte (in_stream);
y_adjust = read_byte (in_stream);
read_string (in_stream, buffer, buffer_length);
alabel (x_adjust, y_adjust, buffer);
break;
case ARC:
x0 = coord (in_stream);
y0 = coord (in_stream);
x1 = coord (in_stream);
y1 = coord (in_stream);
x2 = coord (in_stream);
y2 = coord (in_stream);
arc (x0, y0, x1, y1, x2, y2);
break;
case CIRCLE:
x0 = coord (in_stream);
y0 = coord (in_stream);
x1 = coord (in_stream);
circle (x0, y0, x1);
break;
case COLOR:
x0 = coord (in_stream)&0xFFFF;
y0 = coord (in_stream)&0xFFFF;
x1 = coord (in_stream)&0xFFFF;
color (x0, y0, x1);
break;
case CONT:
x0 = coord (in_stream);
y0 = coord (in_stream);
cont (x0, y0);
break;
case ERASE:
erase (in_stream);
break;
case FILL:
fill (coord (in_stream)&0xFFFF); break;
case FONT:
read_string (in_stream, buffer, buffer_length);
fontname (buffer);
break;
case FONTSIZE:
fontsize (coord (in_stream));
break;
case LABEL:
read_string (in_stream, buffer, buffer_length);
label (buffer);
break;
case LINE:
x0 = coord (in_stream);
y0 = coord (in_stream);
x1 = coord (in_stream);
y1 = coord (in_stream);
line (x0, y0, x1, y1);
break;
case LINEMOD:
read_string (in_stream, buffer, buffer_length);
linemod (buffer);
break;
case MOVE:
x0 = coord (in_stream);
y0 = coord (in_stream);
move_nasko (x0, y0);
break;
case POINT:
x0 = coord (in_stream);
y0 = coord (in_stream);
point (x0, y0);
break;
case ROTATE:
x0 = coord (in_stream);
y0 = coord (in_stream);
x1 = coord (in_stream);
rotate (x0, y0, x1);
break;
case SPACE:
x0 = coord (in_stream);
y0 = coord (in_stream);
x1 = coord (in_stream);
y1 = coord (in_stream);
if (guess_byte_order)
find_byte_order(&x0, &y0, &x1, &y1);
space (x0, y0, x1, y1);
break;
default:
fprintf (stderr, "Unrecognized plot command `%c' ignored.\n", instruction);
}
instruction = read_byte (in_stream);
}
return;
}
int main (int argc, char *argv[])
{
int i;
char *buffer;
int buffer_length;
int named_plot=0; /* count named plot files on command line. */
int show_usage=0; /* remember whether to output usage message. */
int opened=0; /* remember whether we have opened output. */
buffer_length = 1024;
buffer = (char *) malloc (buffer_length);
if (buffer <= (char *) 0)
{
perror ("malloc failed:");
exit (-1);
}
for (i = 1; i < argc; i++)
{
if ((strcmp (argv [i], "-fontsize") == 0)
|| (strcmp (argv [i], "-fs") == 0))
{
/* Sizes supported by X: 8, 10, 12, 14, 18, and 24. */
fontsize (atoi (argv[i+1]));
i += 1;
}
else if ((strcmp (argv [i], "-fontname") == 0)
|| (strcmp (argv [i], "-fn") == 0))
{
fontname (argv [i+1]);
i += 1;
}
else if ((strcmp (argv [i], "-high-byte-first") == 0)
|| (strcmp (argv [i], "-h") == 0))
{
guess_byte_order = 0;
high_byte_first = 1;
}
else if ((strcmp (argv [i], "-low-byte-first") == 0)
|| (strcmp (argv [i], "-l") == 0))
{
guess_byte_order = 0;
high_byte_first = 0;
}
else if ((strcmp (argv [i], "-warranty") == 0)
|| (strcmp (argv [i], "-copying") == 0))
{
/*
for (i=0; copy_notice[i][0]>0; i++)
fputs (copy_notice[i], stdout);
*/
named_plot++;
}
else if ((strcmp (argv [i], "-help") == 0)
|| (strcmp (argv [i], "-V") == 0))
{
printf ("%s version %s\n", argv[0], "0.0");
show_usage++;
named_plot++;
}
else if ((strcmp (argv [i], "-signed") == 0))
{
signed_input=1;
}
else if ((strcmp (argv [i], "-unsigned") == 0))
{
signed_input=0;
}
else if ((strcmp (argv [i], "-") == 0))
{
read_plot (stdin, buffer, buffer_length);
named_plot++;
}
else
{
FILE *filep;
filep = fopen ( argv [i], "r");
if (filep == NULL)
{
fprintf (stderr, "Unrecognized option or file `%s' ignored.\n",
argv [i]);
show_usage++;
}
else
{
named_plot++;
if (!opened)
{
openpl ();
opened ++;
}
read_plot (filep, buffer, buffer_length);
fclose (filep);
}
}
}
/* if there were no named plot files on the command line, then read
the standard input. */
if (named_plot == 0)
{
if (!opened)
{
openpl ();
opened ++;
}
read_plot (stdin, buffer, buffer_length);
}
if (opened)
closepl();
if ( show_usage || !opened)
{
fprintf (stderr, "\n\
usage: %s [-fontsize|-fs SIZE] [-high-byte-first|-h]\n\
[-low-byte-first|-l] [-fontname|-fn FONTNAME]\n\
[-help|-V] [-copying|-warranty] [PLOT_FILE_NAMES ...]\n",
*argv);
fprintf (stderr, "\n\
%s version 0.9, Copyright (C) 1989 Free Software Foundation, Inc.\n\
%s comes with ABSOLUTELY NO WARRANTY. This is free software, and\n\
you are welcome to redistribute it. Type `%s -warranty' for warranty\n\
details and copying conditions.\n\n",
*argv, *argv, *argv);
}
return 0;
}