ngspice/xgraph/params.c

568 lines
12 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* $Header$ */
/*
* Xgraph Parameters
*
* This file contains routines for setting and retrieving
* various X style display parameters for xgraph.
*
* $Log$
* Revision 1.1 2004-01-25 09:00:49 pnenzi
*
* Added xgraph plotting program.
*
* Revision 1.2 1999/12/08 19:32:41 heideman
* strcasecmp portability fix
*
* Revision 1.1.1.1 1999/12/03 23:15:52 heideman
* xgraph-12.0
*
*/
#ifndef lint
static char rcsid[] = "$Id$";
#endif
#include <ctype.h>
#include <stdio.h>
#include "st.h"
#include "params.h"
#include "hard_devices.h"
#include "xgraph.h" /* for string.h */
/* For use by convenience macros */
params param_temp,
*param_temp_ptr;
XColor param_null_color =
{0, 0, 0, 0, 0, 0};
param_style param_null_style =
{STYLE, 0, (char *) 0};
static st_table *param_table = (st_table *) 0;
typedef struct param_full_defn {
param_types type;
char *text_form;
params *real_form;
} param_full;
#define ISO_FONT "*-*-%s-medium-r-normal-*-*-%d-*-*-*-*-iso8859-*"
static Display *param_disp;
static Colormap param_cmap;
static int param_scrn;
static void free_resource();
static params *resolve_entry();
static int strihash();
static int do_color();
static int do_font();
static int do_style();
static int do_bool();
#define DEF_INT "0"
#define DEF_STR ""
#define DEF_FONT "fixed"
#define DEF_PIXEL "black"
#define DEF_STYLE "1"
#define DEF_BOOL "false"
#define DEF_DBL "0.0"
#define DEF_MAX_FONT 1024
#define DEF_MAX_NAMES 10
#define DUP(str) \
strcpy((char *) Malloc((unsigned) (strlen(str)+1)), (str))
void
param_init(disp, cmap)
Display *disp; /* X Connection */
Colormap cmap; /* Colormap for colors */
/*
* Initializes parameter package. The display and colormap arguments
* are used to resolve font and pixel values.
*/
{
param_table = st_init_table(stricmp, strihash);
if (disp != NULL) {
param_disp = disp;
param_cmap = cmap;
/* This could also be a parameter for greater generality */
param_scrn = DefaultScreen(disp);
}
}
void
param_set(name, type, val)
char *name; /* Name of parameter */
param_types type; /* Type */
char *val; /* Text form for value */
/*
* Sets the parameter with the given name to have the type
* `type' and the text value `value'. This will be evaluated
* to its full form the first time it is referenced using
* param_get(). If it is already filled, the old value
* will be reclaimed.
*/
{
param_full *entry;
if (!param_table) {
(void) fprintf(stderr, "Parameter table not initialized\n");
return;
}
if (st_lookup(param_table, name, (char **) &entry)) {
if (entry->real_form)
free_resource(entry->real_form);
entry->real_form = (params *) 0;
}
else {
entry = (param_full *) Malloc(sizeof(param_full));
entry->text_form = (char *) 0;
entry->real_form = (params *) 0;
(void) st_insert(param_table, DUP(name), (char *) entry);
}
entry->type = type;
if (entry->text_form)
(void) Free((char *) (entry->text_form));
entry->text_form = DUP(val);
}
void
param_reset(name, val)
char *name; /* Name of parameter */
char *val; /* Text form for value */
/*
* This routine sets the value of an existing parameter to a new
* value. The type of the parameter remains the same. Changes
* in type should be done by using param_set() directly.
*/
{
param_full *entry;
if (!param_table) {
(void) fprintf(stderr, "Parameter table not initialized\n");
return;
}
if (st_lookup(param_table, name, (char **) &entry))
param_set(name, entry->type, val);
else
(void) fprintf(stderr, "Cannot reset unknown parameter `%s'\n", name);
}
params *
param_get(name, val)
char *name; /* Name of parameter */
params *val; /* Result value */
/*
* Retrieves a value from the parameter table. The value
* is placed in `val'. If successful, the routine will
* return `val'. Otherwise, it will return zero.
*/
{
param_full *entry;
if (!param_table) {
(void) fprintf(stderr, "Parameter table not initialized\n");
return (params *) 0;
}
if (st_lookup(param_table, name, (char **) &entry)) {
if (!entry->real_form)
entry->real_form = resolve_entry(name, entry->type,
entry->text_form);
*val = *(entry->real_form);
return val;
}
else {
return (params *) 0;
}
}
static void
free_resource(val)
params *val; /* Value to free */
/*
* Reclaims a resource based on its type.
*/
{
switch (val->type) {
case INT:
case STR:
case BOOL:
case DBL:
/* No reclaimation necessary */
break;
case PIXEL:
if ((val->pixv.value.pixel != WhitePixel(param_disp, param_scrn)) &&
(val->pixv.value.pixel != BlackPixel(param_disp, param_scrn)))
XFreeColors(param_disp, param_cmap, &(val->pixv.value.pixel), 1, 0);
break;
case FONT:
XFreeFont(param_disp, val->fontv.value);
break;
case STYLE:
(void) Free(val->stylev.dash_list);
break;
}
(void) Free((char *) val);
}
static params *
resolve_entry(name, type, form)
char *name; /* Name of item for errors */
param_types type; /* What type of thing */
char *form; /* Textual form */
/*
* Allocates and returns an appropriate parameter structure
* by translating `form' into its native type as given by `type'.
* If it can't translate the given form, it will fall back onto
* the default.
*/
{
static char paramstr[] =
"Parameter %s: can't translate `%s' into a %s (defaulting to `%s')\n";
params *result = (params *) Malloc(sizeof(params));
result->type = type;
switch (type) {
case INT:
if (sscanf(form, "%d", &result->intv.value) != 1) {
(void) fprintf(stderr, paramstr, name, form, "integer", DEF_INT);
result->intv.value = atoi(DEF_INT);
}
break;
case STR:
result->strv.value = form;
break;
case PIXEL:
if (!do_color(form, &result->pixv.value)) {
(void) fprintf(stderr, paramstr, name, form, "color", DEF_PIXEL);
(void) do_color(DEF_PIXEL, &result->pixv.value);
}
break;
case FONT:
if (!do_font(form, &result->fontv.value)) {
(void) fprintf(stderr, paramstr, name, form, "font", DEF_FONT);
(void) do_font(DEF_FONT, &result->fontv.value);
}
break;
case STYLE:
if (!do_style(form, &result->stylev)) {
(void) fprintf(stderr, paramstr, name, form, "line style",
DEF_STYLE);
(void) do_style(DEF_STYLE, &result->stylev);
}
break;
case BOOL:
if (!do_bool(form, &result->boolv.value)) {
(void) fprintf(stderr, paramstr, name, form, "boolean flag",
DEF_BOOL);
(void) do_bool(DEF_BOOL, &result->boolv.value);
}
break;
case DBL:
if (sscanf(form, "%lf", &result->dblv.value) != 1) {
(void) fprintf(stderr, paramstr, name, form, "double", DEF_DBL);
result->dblv.value = atof(DEF_DBL);
}
break;
}
return result;
}
static int
do_color(name, color)
char *name; /* Name for color */
XColor *color; /* Returned color */
/*
* Translates `name' into a color and attempts to get the pixel
* for the color using XAllocColor().
*/
{
int result = 1;
if (PM_INT("Output Device") == D_XWINDOWS) {
if (XParseColor(param_disp, param_cmap, name, color)) {
if (stricmp(name, "black") == 0) {
color->pixel = BlackPixel(param_disp, param_scrn);
XQueryColor(param_disp, param_cmap, color);
}
else if (stricmp(name, "white") == 0) {
color->pixel = WhitePixel(param_disp, param_scrn);
XQueryColor(param_disp, param_cmap, color);
}
else
result = XAllocColor(param_disp, param_cmap, color);
}
else
result = 0;
}
return result;
}
static int
do_font(name, font_info)
char *name; /* Name of desired font */
XFontStruct **font_info; /* Returned font information */
/*
* This routine translates a font name into a font structure. The
* font name can be in two forms. The first form is <family>-<size>.
* The family is a family name (like helvetica) and the size is
* in points (like 12). If the font is not in this form, it
* is assumed to be a regular X font name specification and
* is looked up using the standard means.
*/
{
char name_copy[DEF_MAX_FONT],
query_spec[DEF_MAX_FONT];
char *font_family,
*font_size,
**font_list;
int font_size_value,
font_count,
i;
/* First attempt to interpret as font family/size */
if (PM_INT("Output Device") == D_XWINDOWS) {
(void) strcpy(name_copy, name);
if (font_size = index(name_copy, '-')) {
*font_size = '\0';
font_family = name_copy;
font_size++;
font_size_value = atoi(font_size);
if (font_size_value > 0) {
/*
* Still a little iffy -- what about weight and roman vs. other
*/
(void) sprintf(query_spec, ISO_FONT,
font_family, font_size_value * 10);
font_list = XListFonts(param_disp, query_spec,
DEF_MAX_NAMES, &font_count);
/* Load first one that you can */
for (i = 0; i < font_count; i++)
if (*font_info = XLoadQueryFont(param_disp, font_list[i]))
break;
if (*font_info)
return 1;
}
}
/* Assume normal font name */
return (int) (*font_info = XLoadQueryFont(param_disp, name));
}
}
static int
do_style(list, val)
char *list; /* List of ones and zeros */
param_style *val; /* Line style returned */
/*
* Translates a string representation of a dash specification into
* a form suitable for use in XSetDashes(). Assumes `list'
* is a null terminated string of ones and zeros.
*/
{
char *i,
*spot,
last_char;
int count;
for (i = list; *i; i++)
if ((*i != '0') && (*i != '1'))
break;
if (!*i) {
val->len = 0;
last_char = '\0';
for (i = list; *i; i++) {
if (*i != last_char) {
val->len += 1;
last_char = *i;
}
}
val->dash_list = (char *) Malloc((unsigned)
(sizeof(char) * val->len + 1));
last_char = *list;
spot = val->dash_list;
count = 0;
for (i = list; *i; i++) {
if (*i != last_char) {
*spot++ = (char) count;
last_char = *i;
count = 1;
}
else
count++;
}
*spot = (char) count;
return 1;
}
else {
return 0;
}
}
static char *positive[] =
{"on", "yes", "true", "1", "affirmative", (char *) 0};
static char *negative[] =
{"off", "no", "false", "0", "negative", (char *) 0};
static int
do_bool(name, val)
char *name; /* String representation */
int *val; /* Returned value */
/*
* Translates a string representation into a suitable binary value.
* Can parse all kinds of interesting boolean type words.
*/
{
char **term;
for (term = positive; *term; term++) {
if (stricmp(name, *term) == 0)
break;
}
if (*term) {
*val = 1;
return 1;
}
for (term = negative; *term; term++)
if (stricmp(name, *term) == 0)
break;
if (*term) {
*val = 0;
return 1;
}
return 0;
}
/*ARGSUSED*/
static enum st_retval
dump_it(key, value, arg)
char *key,
*value,
*arg;
{
param_full *val = (param_full *) value;
(void) fprintf(stdout, "%s (", key);
switch (val->type) {
case INT:
(void) fprintf(stdout, "INT");
break;
case STR:
(void) fprintf(stdout, "STR");
break;
case PIXEL:
(void) fprintf(stdout, "PIXEL");
break;
case FONT:
(void) fprintf(stdout, "FONT");
break;
case STYLE:
(void) fprintf(stdout, "STYLE");
break;
case BOOL:
(void) fprintf(stdout, "BOOL");
break;
case DBL:
(void) fprintf(stdout, "DBL");
break;
}
(void) fprintf(stdout, ") = %s\n", val->text_form);
return ST_CONTINUE;
}
void
param_dump()
/*
* Dumps all of the parameter values to standard output.
*/
{
st_foreach(param_table, dump_it, (char *) 0);
}
#ifdef HAVE_STRCASECMP
int
stricmp(a, b)
char *a, *b;
{
return strcasecmp(a, b);
}
#else
int
stricmp(a, b)
register char *a,
*b;
/*
* This routine compares two strings disregarding case.
*/
{
register int value;
if ((a == (char *) 0) || (b == (char *) 0)) {
return a - b;
}
for ( /* nothing */ ;
((*a | *b) &&
!(value = ((isupper(*a) ? *a - 'A' + 'a' : *a) -
(isupper(*b) ? *b - 'A' + 'a' : *b))));
a++, b++)
/* Empty Body */ ;
return value;
}
#endif
static int
strihash(string, modulus)
register char *string;
int modulus;
/* Case insensitive computation */
{
register int val = 0;
register int c;
while ((c = *string++) != '\0') {
if (isupper(c))
c = tolower(c);
val = val * 997 + c;
}
return ((val < 0) ? -val : val) % modulus;
}