mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-03 08:25:07 +02:00
Added a ARG_UNUSED macro in utils/magic.h, which produces a simple cast to void to silence the warnings. The reasons this is used as opposed to an attribute is that most compilers should support this. Besides this, the macro can be easily searched for in the future to potentially remove (where possible) the unused parameters.
644 lines
16 KiB
C
644 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;
|
|
|
|
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)
|
|
{
|
|
|
|
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);
|
|
}
|