1 /* grDStyle.c -
2  *
3  *	Parse and read in the display style file.
4  *
5  *     *********************************************************************
6  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
7  *     * Permission to use, copy, modify, and distribute this              *
8  *     * software and its documentation for any purpose and without        *
9  *     * fee is hereby granted, provided that the above copyright          *
10  *     * notice appear in all copies.  The University of California        *
11  *     * makes no representations about the suitability of this            *
12  *     * software for any purpose.  It is provided "as is" without         *
13  *     * express or implied warranty.  Export of this software outside     *
14  *     * of the United States of America may require an export license.    *
15  *     *********************************************************************
16  *
17  * Portions of this code are Copyright (C) 2003 Open Circuit Design, Inc.,
18  * for MultiGiG Ltd.
19  */
20 
21 #ifndef lint
22 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 $";
23 #endif  /* not lint */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 
30 #include "utils/magic.h"
31 #include "utils/malloc.h"
32 #include "utils/styles.h"
33 #include "utils/utils.h"
34 #include "textio/textio.h"
35 #include "utils/geometry.h"
36 #include "graphics/glyphs.h"
37 #include "windows/windows.h"
38 #include "graphics/graphics.h"
39 #include "graphics/graphicsInt.h"
40 #include "tiles/tile.h"
41 #include "utils/hash.h"
42 #include "database/database.h"
43 #include "dbwind/dbwind.h"
44 
45 /* imports from other graphics files */
46 extern void (*grSetSPatternPtr)();
47 extern void (*grDefineCursorPtr)();
48 
49 /* data structures local to this file only */
50 
51 /* Define a linked-list record to keep track of styles prior    */
52 /* to allocating the fixed array GrStyleTable.                  */
53 
54 typedef struct _dstylelink {
55     GR_STYLE_LINE       style;
56     char		shortname;
57     struct _dstylelink  *next;
58 } dstylelink;
59 
60 /* data structures local to the graphics module */
61 
62 extern int grBitPlaneMask;	/* Mask of the valid bit-plane bits. */
63 
64 static GrGlyphs *grCursorGlyphs = NULL;
65 static dstylelink *dstylehead = NULL;
66 
67 global int **GrStippleTable = NULL;
68 global int grNumStipples = 0;
69 
70 /* MUST be the same indices as the constants in graphicsInt.h */
71 char *fillStyles[] = {
72 	"solid",
73 	"cross",
74 	"outline",
75 	"stipple",
76 	"grid",
77 	NULL };
78 
79 
80 
81 /* Internal constants for each section of the style file. */
82 /* These are bitmask-mapped so the display style reader	  */
83 /* can check that the section are read in proper order.	  */
84 
85 #define IGNORE		-1
86 #define	DISP_STYLES	1
87 #define	LAYOUT_STYLES	2
88 #define	PALE_STYLES	4
89 #define	STIPPLES	8
90 #define DISP_VERSION	16
91 
92 #define	STRLEN	200
93 
94 /* Global variables to export to other modules */
95 
96 int GrStyleNames[128];		/* short names for styles */
97 GR_STYLE_LINE *GrStyleTable;
98 
99 
100 
101 bool
GrDrawGlyphNum(num,xoff,yoff)102 GrDrawGlyphNum(num, xoff, yoff)
103     int num;
104     int xoff;
105     int yoff;
106 {
107     Point p;
108 
109     p.p_x = xoff;
110     p.p_y = yoff;
111     if (num >= grCursorGlyphs->gr_num) return FALSE;
112     GrDrawGlyph(grCursorGlyphs->gr_glyph[num], &p);
113     return TRUE;
114 }
115 
116 /*
117  * ----------------------------------------------------------------------------
118  *
119  * GrGetStyleFromName --
120  *
121  * Return an integer style number given a "long name".
122  *
123  * Results:
124  *	Integer style number, or -1 if no style matches the name.
125  *
126  * Side effects:
127  *	None.
128  *
129  * ----------------------------------------------------------------------------
130  */
131 
132 int
GrGetStyleFromName(stylename)133 GrGetStyleFromName(stylename)
134     char *stylename;
135 {
136     int style;
137     int maxstyles = TECHBEGINSTYLES + (DBWNumStyles * 2);
138 
139     for (style = 0; style < maxstyles; style++)
140         if (GrStyleTable[style].longname != NULL)
141             if (!strcmp(stylename, GrStyleTable[style].longname))
142                 break;
143 
144     return (style == maxstyles) ? -1 : style;
145 }
146 
147 /*
148  * ----------------------------------------------------------------------------
149  *
150  * GrResetStyles --
151  *
152  * Free memory associated with the display styles in preparation for
153  * re-reading the styles file.
154  *
155  * Results:
156  *	None.
157  *
158  * Side effects:
159  *	Allocated memory free'd.
160  *
161  * ----------------------------------------------------------------------------
162  */
163 
164 void
GrResetStyles()165 GrResetStyles()
166 {
167     int i;
168 
169     if (DBWNumStyles == 0) return;	/* Nothing has been allocated yet */
170 
171     for (i = 0; i < TECHBEGINSTYLES + (DBWNumStyles * 2); i++)
172 	if (GrStyleTable[i].longname != NULL)
173 	    freeMagic(GrStyleTable[i].longname);
174 
175     freeMagic((char *)GrStyleTable);
176     GrStyleTable = NULL;
177     DBWNumStyles = 0;
178 }
179 
180 
181 /*
182  * ----------------------------------------------------------------------------
183  * styleBuildDisplayStyle:
184  *
185  *	Take one line of the display_styles section and process it.
186  *
187  * Results:
188  *	True if things worked, false otherwise.
189  *
190  * Side effects:
191  *	none
192  * ----------------------------------------------------------------------------
193  */
194 
195 bool
styleBuildDisplayStyle(line,version)196 styleBuildDisplayStyle(line, version)
197     char *line;
198     int version;
199 {
200     bool res;
201     int argsread;
202     int ord = 1, mask, color, outline, nfill, stipple;
203     char shortName, longName[52];
204     char fill[42], ordstr[12], colorName[30];
205     dstylelink *newstyle, *sstyle;
206 
207     char v6scanline[] = "%10s %o %29s %o %40s %d %c %50s";
208     char v7scanline[] = "%10s %i %29s %i %40s %d %c %50s";
209 
210     char *scanline = (version > 6) ? v7scanline : v6scanline;
211 
212     res = TRUE;
213 
214     if ((argsread = sscanf(line, scanline,
215 		ordstr, &mask, colorName, &outline, fill, &stipple,
216 		&shortName, &longName)) < 7)
217     {
218 	res = FALSE;
219     }
220     else
221     {
222 	newstyle = (dstylelink *)mallocMagic(sizeof(dstylelink));
223 	newstyle->next = dstylehead;
224 	dstylehead = newstyle;		/* note that dstylehead has styles
225 					 * in reverse order.
226 					 */
227 
228 	/* Allow colors to be specified by index or by name */
229 	if (sscanf(colorName, ((version > 6) ? "%i" : "%o"), &color) == 0)
230 	    color = GrNameToColor(colorName);
231 
232 	newstyle->style.mask = (mask & grBitPlaneMask);
233 	newstyle->style.color = (color & grBitPlaneMask);
234 	newstyle->style.outline = outline;
235 	if (StrIsInt(ordstr))
236 	{
237 	    newstyle->style.idx = atoi(ordstr);
238 	    if (newstyle->style.idx > ord)
239 		ord = newstyle->style.idx + 1;
240 	}
241 	else
242 	    newstyle->style.idx = ord++;
243 	nfill = LookupFull(fill, fillStyles);
244 	if (nfill < 0)
245 	    res = FALSE;
246 	newstyle->style.fill = nfill;
247 	newstyle->style.stipple = stipple;
248 
249 	/* Add short style name reverse lookup table entry */
250 	newstyle->shortname = shortName & 0x7f;
251 
252 	if (argsread == 8)
253 	    newstyle->style.longname = StrDup(NULL, longName);
254 	else
255 	    newstyle->style.longname = NULL;
256     }
257     return(res);
258 }
259 
260 
261 /*
262  * ----------------------------------------------------------------------------
263  * styleBuildStippleStyle:
264  *
265  *	Take one line of the stipples section and process it.
266  *
267  * Results:
268  *	True if things worked, false otherwise.
269  *
270  * Side effects:
271  *	none
272  * ----------------------------------------------------------------------------
273  */
274 
275 bool
styleBuildStipplesStyle(line,version)276 styleBuildStipplesStyle(line, version)
277     char *line;
278     int version;
279 {
280     bool res;
281     int ord;
282     int row[8];
283 
284     char v6scanline[] = "%d %o %o %o %o %o %o %o %o";
285     char v7scanline[] = "%d %x %x %x %x %x %x %x %x";
286 
287     char *scanline = (version > 6) ? v7scanline : v6scanline;
288 
289     res = TRUE;
290 
291     if (sscanf(line, scanline,
292 	    &ord, &(row[0]), &(row[1]), &(row[2]), &(row[3]),
293 	    &(row[4]), &(row[5]), &(row[6]), &(row[7]) ) != 9)
294     {
295 	res = FALSE;
296     }
297     else
298     {
299 	if (ord < 0)
300 	    res = FALSE;
301 	else
302 	{
303 	    int i, j, ns, **sttable;
304 
305 	    ns = MAX(grNumStipples, ord + 1);
306 	    if (ns > grNumStipples)
307 	    {
308 		/* Grab in blocks of 8 to avoid over-use of malloc. . . */
309 		if (ns < (grNumStipples + 8)) ns = grNumStipples + 8;
310 
311 		sttable = (int **)mallocMagic(ns * sizeof(int *));
312 	  	for (i = 0; i < grNumStipples; i++)
313 		    sttable[i] = GrStippleTable[i];
314 		for (; i < ns; i++)
315 		{
316 		    sttable[i] = (int *)mallocMagic(8 * sizeof(int));
317 		    for (j = 0; j < 8; j++)
318 			sttable[i][j] = 0;
319 		}
320 		if (GrStippleTable) freeMagic((char *)GrStippleTable);
321 		GrStippleTable = sttable;
322 		grNumStipples = ns;
323 	    }
324 	    for (i = 0; i < 8; i++)
325 		GrStippleTable[ord][i] = row[i];
326 	}
327     }
328     return(res);
329 }
330 
331 
332 /*
333  * ----------------------------------------------------------------------------
334  * GrLoadCursors --
335  *
336  *	Loads the graphics cursors from a given file.  There must not be
337  *	any window locks set, as this routine may need to write to the
338  *	display.
339  *
340  * Results:
341  *	True if things worked, false otherwise.
342  *
343  * Side effects:
344  *	Cursor patterns are loaded, which may involve writing to the
345  *	display.  The file from which the cursors are read is determined
346  *	by combining grCursorType (a driver-dependent string) with a
347  *	".glyphs" extension.
348  * ----------------------------------------------------------------------------
349  */
350 
351 bool
GrLoadCursors(path,libPath)352 GrLoadCursors(path, libPath)
353 char *path;
354 char *libPath;
355 {
356     if (grCursorGlyphs != (GrGlyphs *) NULL)
357     {
358 	GrFreeGlyphs(grCursorGlyphs);
359 	grCursorGlyphs = (GrGlyphs *) NULL;
360     }
361 
362     if (!GrReadGlyphs(grCursorType, path, libPath, &grCursorGlyphs))
363     {
364 	return FALSE;
365     }
366 
367     if (grDefineCursorPtr == NULL)
368 	TxError("Display does not have a programmable cursor.\n");
369     else
370 	(*grDefineCursorPtr)(grCursorGlyphs);
371 
372     return TRUE;
373 }
374 
375 
376 /*
377  * ----------------------------------------------------------------------------
378  * GrLoadStyles:
379  *
380  *	Reads in a display style file.  This has the effect of setting the
381  *	box styles and stipple patterns.
382  *
383  * Results:
384  *	-1 if the file contained a format error.
385  *	-2 if the file was not found.
386  *	0 if everything went OK.
387  *
388  * Side effects:
389  *	global variables are changed.
390  * ----------------------------------------------------------------------------
391  */
392 
393 int
GrLoadStyles(techType,path,libPath)394 GrLoadStyles(techType, path, libPath)
395 char *techType;			/* Type of styles wanted by the technology
396 				 * file (usually "std").  We tack two things
397 				 * onto this name:  the type of styles
398 				 * wanted by the display, and a version
399 				 * suffix.  This three-part name is used
400 				 * to look up the actual display styles
401 				 * file.
402 				 */
403 char *path;
404 char *libPath;
405 {
406     FILE *inp;
407     int res = 0;
408     int i, scount, processed = DISP_VERSION;
409     char fullName[256];
410     dstylelink *sstyle;
411     int MaxTechStyles = 0, MaxTileStyles = 0;
412 
413     /* The dstyle file format version number was buried in the filename */
414     /* prior to version 6.  Therefore versions which do not have a	*/
415     /* "version" keyword in the file should default to version 5.	*/
416     int version = 5;
417 
418     /* Reset number of styles to zero */
419     GrResetStyles();
420 
421     for (i = 0; i < 128; i++) GrStyleNames[i] = 0;
422 
423     (void) sprintf(fullName, "%.100s.%.100s.dstyle", techType, grDStyleType);
424 
425     inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL);
426     if (inp == NULL)
427     {
428 	/* Try old format ".dstyle5"? */
429         (void) sprintf(fullName, "%.100s.%.100s.dstyle5", techType, grDStyleType);
430 	inp = PaOpen(fullName, "r", (char *) NULL, path, libPath, (char **) NULL);
431 	if (inp == NULL)
432 	{
433 	    TxError("Couldn't open display styles file \"%s\"\n", fullName);
434             return(-2);
435 	}
436     }
437     else
438     {
439 	char line[STRLEN], sectionName[STRLEN];
440 	char *sres;
441 	bool newSection = FALSE;
442         int section;
443 
444 	while (TRUE)
445 	{
446 	    sres = fgets(line, STRLEN, inp);
447 	    if (sres == NULL) break;
448 	    if (StrIsWhite(line, FALSE))
449 		newSection = TRUE;
450 	    else if (line[0] == '#')
451 	    {
452 		/* comment line */
453 	    }
454 	    else if (newSection)
455 	    {
456 		if (sscanf(line, "%s", sectionName) != 1)
457 		{
458 		    TxError("File contained format error: "
459 			    "unable to read section name.\n");
460 		    res = -1;
461 		}
462 		if (strcmp(sectionName, "version") == 0)
463 		{
464 		    if (sscanf(line, "%*s %d", &version) != 1)
465 		    {
466 		        TxError("DStyle format version could not be "
467 				"read: assuming version 6\n");
468 			version = 6;
469 		    }
470 		    section = DISP_VERSION;
471 		}
472 		else if (strcmp(sectionName, "display_styles") == 0)
473 		{
474 		    int locbitplanes;
475 
476 		    if ((processed & (LAYOUT_STYLES | PALE_STYLES)) != 0)
477 		    {
478 			TxError("DStyle sections out of order: display_styles must "
479 				"come before layout_styles and pale_styles\n");
480 			res = -1;
481 		    }
482 		    section = DISP_STYLES;
483 		    scount = 0;
484 		}
485 		else if (strcmp(sectionName, "layout_styles") == 0)
486 		{
487 		    if ((processed & PALE_STYLES) != 0)
488 		    {
489 			TxError("DStyle sections out of order: layout_styles must "
490 				"come before pale_styles\n");
491 			MainExit(1);
492 		    }
493 		    section = LAYOUT_STYLES;
494 		    if (scount < TECHBEGINSTYLES)
495 		    {
496 			TxError("Error: Display style file defines only %d of "
497 				"%d required internal styles.\n", scount,
498 				TECHBEGINSTYLES);
499 		    }
500 		    else if (scount > TECHBEGINSTYLES)
501 		    {
502 			TxError("Error: Display style file defines too many (%d) "
503 				"internal styles; should be %d.\n", scount,
504 				TECHBEGINSTYLES);
505 		    }
506 		    scount = 0;
507 		}
508 		else if (strcmp(sectionName, "pale_styles") == 0)
509 		{
510 		    section = PALE_STYLES;
511 		    MaxTechStyles = scount + TECHBEGINSTYLES;
512 		    scount = 0;
513 		}
514 		else if (strcmp(sectionName, "stipples") == 0)
515 		{
516 		    section = STIPPLES;
517 		    if (grNumStipples > 0)
518 		    {
519 			while (grNumStipples > 0)
520 			    freeMagic((char *)GrStippleTable[--grNumStipples]);
521 			freeMagic((char *)GrStippleTable);
522 			GrStippleTable = NULL;
523 		    }
524 		}
525 		else
526 		{
527 		    if (StrIsInt(sectionName))
528 		    {
529 			TxError("Unexpected empty line in .dstyle file.\n");
530 			newSection = FALSE;
531 			goto recovery;
532 		    }
533 		    TxError("Bad section name \"%s\" in .dstyle file.\n",
534 			sectionName);
535 		    section = IGNORE;
536 		}
537 		newSection = FALSE;
538 	        processed |= section;
539 	    }
540 	    else
541 	    {
542 		int newres = TRUE;
543 
544 recovery:
545 		switch (section)
546 		{
547 		    case LAYOUT_STYLES:
548 		    case PALE_STYLES:
549 		    case DISP_STYLES:
550 			newres = styleBuildDisplayStyle(line, version);
551 			scount++;
552 			break;
553 		    case STIPPLES:
554 			newres = styleBuildStipplesStyle(line, version);
555 			break;
556 		    case DISP_VERSION:
557 		    case IGNORE:
558 			break;
559 		    default:
560 			TxError("Internal error in GrStyle\n");
561 			break;
562 		}
563 		if (!newres)
564 		{
565 		    TxError("Style line contained format error: %s", line);
566 		    res = -1;
567 		}
568 	    }
569 	}
570     }
571     if (fclose(inp) == EOF)
572 	TxError("Could not close styles file.\n");
573 
574     if ((processed | STIPPLES) != (LAYOUT_STYLES | DISP_STYLES
575 		| PALE_STYLES | STIPPLES | DISP_VERSION))
576     {
577 	TxError("Not all required style sections were read.  Missing"
578 		" sections are:");
579 	if (!(processed & DISP_STYLES))
580 	    TxError(" display_styles");
581 	if (!(processed & LAYOUT_STYLES))
582 	    TxError(" layout_styles");
583 	if (!(processed & PALE_STYLES))
584 	    TxError(" pale_styles");
585 	if (!(processed & DISP_VERSION))
586 	    TxError(" version");
587 	TxError("\n");
588 	res = -1;
589     }
590     else
591     {
592 	if (grSetSPatternPtr)
593 	    (*grSetSPatternPtr)(GrStippleTable, grNumStipples);
594 
595 	if ((MaxTechStyles - TECHBEGINSTYLES) != scount)
596 	{
597 	    TxError("Error:  Number of pale styles (%d) is different from "
598 			"the number of layout styles (%d)\n",
599 			scount, MaxTechStyles - TECHBEGINSTYLES);
600 	    res = -1;
601 	}
602 	else
603 	{
604 	    DBWNumStyles = scount;
605 	    MaxTileStyles = MaxTechStyles + scount;
606 
607 	    GrStyleTable = (GR_STYLE_LINE *)mallocMagic(MaxTileStyles *
608 		sizeof(GR_STYLE_LINE));
609 
610 	    /* Fill in table backwards, since linked list is a stack */
611 	    sstyle = dstylehead;
612 	    for (i = MaxTileStyles - 1; i >= 0; i--)
613 	    {
614 		if (sstyle == NULL)
615 		{
616 		    GrStyleTable[i].longname = NULL;
617 		    break;
618 		}
619 		else
620 		{
621 		    GrStyleTable[i] = sstyle->style;
622 		    /* Add short style name reverse lookup table entry */
623 		    GrStyleNames[(int)(sstyle->shortname)] = i;
624 		    freeMagic(sstyle);
625 		    sstyle = sstyle->next;
626 		}
627 	    }
628 	    dstylehead = NULL;
629 	}
630     }
631     if (res != 0) GrResetStyles();
632     return(res);
633 }
634