magic/graphics/grDStyle.c

645 lines
16 KiB
C

/* grDStyle.c -
*
* Parse and read in the display style file.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*
* Portions of this code are Copyright (C) 2003 Open Circuit Design, Inc.,
* for MultiGiG Ltd.
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grDStyle.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "utils/magic.h"
#include "utils/malloc.h"
#include "utils/styles.h"
#include "utils/utils.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "graphics/glyphs.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "graphics/graphicsInt.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "dbwind/dbwind.h"
/* C99 compat */
#include "utils/main.h"
/* imports from other graphics files */
extern void (*grSetSPatternPtr)();
extern void (*grDefineCursorPtr)();
/* data structures local to this file only */
/* Define a linked-list record to keep track of styles prior */
/* to allocating the fixed array GrStyleTable. */
typedef struct _dstylelink {
GR_STYLE_LINE style;
char shortname;
struct _dstylelink *next;
} dstylelink;
/* data structures local to the graphics module */
extern int grBitPlaneMask; /* Mask of the valid bit-plane bits. */
static GrGlyphs *grCursorGlyphs = NULL;
static dstylelink *dstylehead = NULL;
global int **GrStippleTable = NULL;
global int grNumStipples = 0;
/* MUST be the same indices as the constants in graphicsInt.h */
const char * const fillStyles[] = {
"solid",
"cross",
"outline",
"stipple",
"grid",
NULL };
/* Internal constants for each section of the style file. */
/* These are bitmask-mapped so the display style reader */
/* can check that the section are read in proper order. */
#define IGNORE -1
#define DISP_STYLES 1
#define LAYOUT_STYLES 2
#define PALE_STYLES 4
#define STIPPLES 8
#define DISP_VERSION 16
#define STRLEN 200
/* Global variables to export to other modules */
int GrStyleNames[128]; /* short names for styles */
GR_STYLE_LINE *GrStyleTable;
bool
GrDrawGlyphNum(num, xoff, yoff)
int num;
int xoff;
int yoff;
{
Point p;
p.p_x = xoff;
p.p_y = yoff;
if (num >= grCursorGlyphs->gr_num) return FALSE;
GrDrawGlyph(grCursorGlyphs->gr_glyph[num], &p);
return TRUE;
}
/*
* ----------------------------------------------------------------------------
*
* GrGetStyleFromName --
*
* Return an integer style number given a "long name".
*
* Results:
* Integer style number, or -1 if no style matches the name.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
int
GrGetStyleFromName(stylename)
char *stylename;
{
int style;
int maxstyles = TECHBEGINSTYLES + (DBWNumStyles * 2);
for (style = 0; style < maxstyles; style++)
if (GrStyleTable[style].longname != NULL)
if (!strcmp(stylename, GrStyleTable[style].longname))
break;
return (style == maxstyles) ? -1 : style;
}
/*
* ----------------------------------------------------------------------------
*
* GrResetStyles --
*
* Free memory associated with the display styles in preparation for
* re-reading the styles file.
*
* Results:
* None.
*
* Side effects:
* Allocated memory free'd.
*
* ----------------------------------------------------------------------------
*/
void
GrResetStyles()
{
int i;
if (DBWNumStyles == 0) return; /* Nothing has been allocated yet */
for (i = 0; i < TECHBEGINSTYLES + (DBWNumStyles * 2); i++)
if (GrStyleTable[i].longname != NULL)
freeMagic(GrStyleTable[i].longname);
freeMagic((char *)GrStyleTable);
GrStyleTable = NULL;
DBWNumStyles = 0;
}
/*
* ----------------------------------------------------------------------------
* styleBuildDisplayStyle:
*
* Take one line of the display_styles section and process it.
*
* Results:
* True if things worked, false otherwise.
*
* Side effects:
* none
* ----------------------------------------------------------------------------
*/
bool
styleBuildDisplayStyle(line, version)
char *line;
int version;
{
bool res;
int argsread;
int ord = 1, mask, color, outline, nfill, stipple;
char shortName, longName[52];
char fill[42], ordstr[12], colorName[30];
dstylelink *newstyle, *sstyle;
char v6scanline[] = "%10s %o %29s %o %40s %d %c %50s";
char v7scanline[] = "%10s %i %29s %i %40s %d %c %50s";
char *scanline = (version > 6) ? v7scanline : v6scanline;
res = TRUE;
if ((argsread = sscanf(line, scanline,
ordstr, &mask, colorName, &outline, fill, &stipple,
&shortName, &longName)) < 7)
{
res = FALSE;
}
else
{
newstyle = (dstylelink *)mallocMagic(sizeof(dstylelink));
newstyle->next = dstylehead;
dstylehead = newstyle; /* note that dstylehead has styles
* in reverse order.
*/
/* Allow colors to be specified by index or by name */
if (version > 6)
{
if (sscanf(colorName, "%i", &color) <= 0)
color = GrNameToColor(colorName);
}
else
{
if (sscanf(colorName, "%o", (unsigned int *)&color) <= 0)
color = GrNameToColor(colorName);
}
newstyle->style.mask = (mask & grBitPlaneMask);
newstyle->style.color = (color & grBitPlaneMask);
newstyle->style.outline = outline;
if (StrIsInt(ordstr))
{
newstyle->style.idx = atoi(ordstr);
if (newstyle->style.idx > ord)
ord = newstyle->style.idx + 1;
}
else
newstyle->style.idx = ord++;
nfill = LookupFull(fill, fillStyles);
if (nfill < 0)
res = FALSE;
newstyle->style.fill = nfill;
newstyle->style.stipple = stipple;
/* Add short style name reverse lookup table entry */
newstyle->shortname = shortName & 0x7f;
if (argsread == 8)
newstyle->style.longname = StrDup(NULL, longName);
else
newstyle->style.longname = NULL;
}
return(res);
}
/*
* ----------------------------------------------------------------------------
* styleBuildStippleStyle:
*
* Take one line of the stipples section and process it.
*
* Results:
* True if things worked, false otherwise.
*
* Side effects:
* none
* ----------------------------------------------------------------------------
*/
bool
styleBuildStipplesStyle(line, version)
char *line;
int version;
{
bool res;
int ord;
int row[8];
char v6scanline[] = "%d %o %o %o %o %o %o %o %o";
char v7scanline[] = "%d %x %x %x %x %x %x %x %x";
char *scanline = (version > 6) ? v7scanline : v6scanline;
res = TRUE;
if (sscanf(line, scanline,
&ord, &(row[0]), &(row[1]), &(row[2]), &(row[3]),
&(row[4]), &(row[5]), &(row[6]), &(row[7]) ) != 9)
{
res = FALSE;
}
else
{
if (ord < 0)
res = FALSE;
else
{
int i, j, ns, **sttable;
ns = MAX(grNumStipples, ord + 1);
if (ns > grNumStipples)
{
/* Grab in blocks of 8 to avoid over-use of malloc. . . */
if (ns < (grNumStipples + 8)) ns = grNumStipples + 8;
sttable = (int **)mallocMagic(ns * sizeof(int *));
for (i = 0; i < grNumStipples; i++)
sttable[i] = GrStippleTable[i];
for (; i < ns; i++)
{
sttable[i] = (int *)mallocMagic(8 * sizeof(int));
for (j = 0; j < 8; j++)
sttable[i][j] = 0;
}
if (GrStippleTable) freeMagic((char *)GrStippleTable);
GrStippleTable = sttable;
grNumStipples = ns;
}
for (i = 0; i < 8; i++)
GrStippleTable[ord][i] = row[i];
}
}
return(res);
}
/*
* ----------------------------------------------------------------------------
* GrLoadCursors --
*
* Loads the graphics cursors from a given file. There must not be
* any window locks set, as this routine may need to write to the
* display.
*
* Results:
* True if things worked, false otherwise.
*
* Side effects:
* Cursor patterns are loaded, which may involve writing to the
* display. The file from which the cursors are read is determined
* by combining grCursorType (a driver-dependent string) with a
* ".glyphs" extension.
* ----------------------------------------------------------------------------
*/
bool
GrLoadCursors(path, libPath)
char *path;
char *libPath;
{
if (grCursorGlyphs != (GrGlyphs *) NULL)
{
GrFreeGlyphs(grCursorGlyphs);
grCursorGlyphs = (GrGlyphs *) NULL;
}
if (!GrReadGlyphs(grCursorType, path, libPath, &grCursorGlyphs))
{
return FALSE;
}
if (grDefineCursorPtr == NULL)
TxError("Display does not have a programmable cursor.\n");
else
(*grDefineCursorPtr)(grCursorGlyphs);
return TRUE;
}
/*
* ----------------------------------------------------------------------------
* GrLoadStyles:
*
* Reads in a display style file. This has the effect of setting the
* box styles and stipple patterns.
*
* Results:
* -1 if the file contained a format error.
* -2 if the file was not found.
* 0 if everything went OK.
*
* Side effects:
* global variables are changed.
* ----------------------------------------------------------------------------
*/
int
GrLoadStyles(techType, path, libPath)
char *techType; /* Type of styles wanted by the technology
* file (usually "std"). We tack two things
* onto this name: the type of styles
* wanted by the display, and a version
* suffix. This three-part name is used
* to look up the actual display styles
* file.
*/
char *path;
char *libPath;
{
FILE *inp;
int res = 0;
int i, scount = 0, processed = DISP_VERSION;
char fullName[256];
dstylelink *sstyle;
int MaxTechStyles = 0, MaxTileStyles = 0;
/* The dstyle file format version number was buried in the filename */
/* prior to version 6. Therefore versions which do not have a */
/* "version" keyword in the file should default to version 5. */
int version = 5;
/* Reset number of styles to zero */
GrResetStyles();
for (i = 0; i < 128; i++) GrStyleNames[i] = 0;
(void) sprintf(fullName, "%.100s.%.100s.dstyle", techType, grDStyleType);
inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL);
if (inp == NULL)
{
/* Try old format ".dstyle5"? */
(void) sprintf(fullName, "%.100s.%.100s.dstyle5", techType, grDStyleType);
inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL);
if (inp == NULL)
{
TxError("Couldn't open display styles file \"%s\"\n", fullName);
return(-2);
}
}
else
{
char line[STRLEN], sectionName[STRLEN];
char *sres;
bool newSection = FALSE;
int section;
while (TRUE)
{
sres = fgets(line, STRLEN, inp);
if (sres == NULL) break;
if (StrIsWhite(line, FALSE))
newSection = TRUE;
else if (line[0] == '#')
{
/* comment line */
}
else if (newSection)
{
if (sscanf(line, "%s", sectionName) != 1)
{
TxError("File contained format error: "
"unable to read section name.\n");
res = -1;
}
if (strcmp(sectionName, "version") == 0)
{
if (sscanf(line, "%*s %d", &version) != 1)
{
TxError("DStyle format version could not be "
"read: assuming version 6\n");
version = 6;
}
section = DISP_VERSION;
}
else if (strcmp(sectionName, "display_styles") == 0)
{
int locbitplanes;
if ((processed & (LAYOUT_STYLES | PALE_STYLES)) != 0)
{
TxError("DStyle sections out of order: display_styles must "
"come before layout_styles and pale_styles\n");
res = -1;
}
section = DISP_STYLES;
scount = 0;
}
else if (strcmp(sectionName, "layout_styles") == 0)
{
if ((processed & PALE_STYLES) != 0)
{
TxError("DStyle sections out of order: layout_styles must "
"come before pale_styles\n");
MainExit(1);
}
section = LAYOUT_STYLES;
if (scount < TECHBEGINSTYLES)
{
TxError("Error: Display style file defines only %d of "
"%d required internal styles.\n", scount,
TECHBEGINSTYLES);
}
else if (scount > TECHBEGINSTYLES)
{
TxError("Error: Display style file defines too many (%d) "
"internal styles; should be %d.\n", scount,
TECHBEGINSTYLES);
}
scount = 0;
}
else if (strcmp(sectionName, "pale_styles") == 0)
{
section = PALE_STYLES;
MaxTechStyles = scount + TECHBEGINSTYLES;
scount = 0;
}
else if (strcmp(sectionName, "stipples") == 0)
{
section = STIPPLES;
if (grNumStipples > 0)
{
while (grNumStipples > 0)
freeMagic((char *)GrStippleTable[--grNumStipples]);
freeMagic((char *)GrStippleTable);
GrStippleTable = NULL;
}
}
else
{
if (StrIsInt(sectionName))
{
TxError("Unexpected empty line in .dstyle file.\n");
newSection = FALSE;
goto recovery;
}
TxError("Bad section name \"%s\" in .dstyle file.\n",
sectionName);
section = IGNORE;
}
newSection = FALSE;
processed |= section;
}
else
{
int newres;
recovery:
newres = TRUE;
switch (section)
{
case LAYOUT_STYLES:
case PALE_STYLES:
case DISP_STYLES:
newres = styleBuildDisplayStyle(line, version);
scount++;
break;
case STIPPLES:
newres = styleBuildStipplesStyle(line, version);
break;
case DISP_VERSION:
case IGNORE:
break;
default:
TxError("Internal error in GrStyle\n");
break;
}
if (!newres)
{
TxError("Style line contained format error: %s", line);
res = -1;
}
}
}
}
if (fclose(inp) == EOF)
TxError("Could not close styles file.\n");
if ((processed | STIPPLES) != (LAYOUT_STYLES | DISP_STYLES
| PALE_STYLES | STIPPLES | DISP_VERSION))
{
TxError("Not all required style sections were read. Missing"
" sections are:");
if (!(processed & DISP_STYLES))
TxError(" display_styles");
if (!(processed & LAYOUT_STYLES))
TxError(" layout_styles");
if (!(processed & PALE_STYLES))
TxError(" pale_styles");
if (!(processed & DISP_VERSION))
TxError(" version");
TxError("\n");
res = -1;
}
else
{
if (grSetSPatternPtr)
(*grSetSPatternPtr)(GrStippleTable, grNumStipples);
if ((MaxTechStyles - TECHBEGINSTYLES) != scount)
{
TxError("Error: Number of pale styles (%d) is different from "
"the number of layout styles (%d)\n",
scount, MaxTechStyles - TECHBEGINSTYLES);
res = -1;
}
else
{
DBWNumStyles = scount;
MaxTileStyles = MaxTechStyles + scount;
GrStyleTable = (GR_STYLE_LINE *)mallocMagic(MaxTileStyles *
sizeof(GR_STYLE_LINE));
/* Fill in table backwards, since linked list is a stack */
sstyle = dstylehead;
for (i = MaxTileStyles - 1; i >= 0; i--)
{
if (sstyle == NULL)
{
GrStyleTable[i].longname = NULL;
break;
}
else
{
GrStyleTable[i] = sstyle->style;
/* Add short style name reverse lookup table entry */
GrStyleNames[(int)(sstyle->shortname)] = i;
freeMagic(sstyle);
sstyle = sstyle->next;
}
}
dstylehead = NULL;
}
}
if (res != 0) GrResetStyles();
return(res);
}