aboutsummaryrefslogtreecommitdiffstats
path: root/z42.c
diff options
context:
space:
mode:
authorJeffrey H. Kingston <jeff@it.usyd.edu.au>2010-09-14 19:21:41 +0000
committerJeffrey H. Kingston <jeff@it.usyd.edu.au>2010-09-14 19:21:41 +0000
commit71bdb35d52747e6d7d9f55df4524d57c2966be94 (patch)
tree480ee5eefccc40d5f3331cc52d66f722fd19bfb9 /z42.c
parentb41263ea7578fa9742486135c762803b52794105 (diff)
downloadlout-71bdb35d52747e6d7d9f55df4524d57c2966be94.tar.gz
Lout 3.17.
git-svn-id: http://svn.savannah.nongnu.org/svn/lout/trunk@2 9365b830-b601-4143-9ba8-b4a8e2c3339c
Diffstat (limited to 'z42.c')
-rw-r--r--z42.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/z42.c b/z42.c
new file mode 100644
index 0000000..66a3c80
--- /dev/null
+++ b/z42.c
@@ -0,0 +1,243 @@
+/*@z42.c:Colour Service:ColourChange, ColourCommand@**************************/
+/* */
+/* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.17) */
+/* COPYRIGHT (C) 1991, 1999 Jeffrey H. Kingston */
+/* */
+/* Jeffrey H. Kingston (jeff@cs.usyd.edu.au) */
+/* Basser Department of Computer Science */
+/* The University of Sydney 2006 */
+/* AUSTRALIA */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either Version 2, or (at your option) */
+/* any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */
+/* */
+/* FILE: z42.c */
+/* MODULE: Colour Service */
+/* EXTERNS: ColourChange(), ColourCommand() */
+/* */
+/*****************************************************************************/
+#include "externs.h"
+#define INIT_COLOUR_NUM 100
+
+
+/*****************************************************************************/
+/* */
+/* COLOUR_TABLE */
+/* */
+/* A symbol table permitting access to colour records by number or name. */
+/* The table will automatically enlarge to accept any number of entries, */
+/* but there is an arbitrary limit of 65535 colours imposed so that colour */
+/* numbers can be stored in 16 bit fields. */
+/* */
+/* ctab_new(newsize) New empty table, newsize capacity */
+/* ctab_insert(x, &S) Insert new colour object x into S */
+/* ctab_retrieve(str, S) Retrieve colour object of name str */
+/* ctab_num(S, num) Retrieve colour object, number num */
+/* ctab_debug(S, fp) Debug print of table S to file fp */
+/* */
+/*****************************************************************************/
+
+typedef struct
+{ int coltab_size; /* size of table */
+ int coltab_count; /* number of colours held */
+ struct coltab_rec
+ { OBJECT by_number; /* colour record by number */
+ OBJECT by_name_hash; /* colour record by name */
+ } coltab[1];
+} *COLOUR_TABLE;
+
+#define ctab_size(S) (S)->coltab_size
+#define ctab_count(S) (S)->coltab_count
+#define ctab_num(S, i) (S)->coltab[i].by_number
+#define ctab_name(S, i) (S)->coltab[i].by_name_hash
+
+#define hash(pos, str, S) \
+{ FULL_CHAR *p = str; \
+ pos = *p++; \
+ while( *p ) pos += *p++; \
+ pos = pos % ctab_size(S); \
+}
+
+static COLOUR_TABLE ctab_new(int newsize)
+{ COLOUR_TABLE S; int i;
+ ifdebug(DMA, D, DebugRegisterUsage(MEM_COLOUR_TAB, 1,
+ 2*sizeof(int) + newsize * sizeof(struct coltab_rec)));
+ S = (COLOUR_TABLE) malloc(2*sizeof(int) + newsize * sizeof(struct coltab_rec));
+ if( S == (COLOUR_TABLE) NULL )
+ Error(42, 1, "ran out of memory when enlarging colour table",
+ FATAL, no_fpos);
+ ctab_size(S) = newsize;
+ ctab_count(S) = 0;
+ for( i = 0; i < newsize; i++ )
+ { ctab_num(S, i) = ctab_name(S, i) = nilobj;
+ }
+ return S;
+} /* end ctab_new */
+
+static void ctab_insert(OBJECT x, COLOUR_TABLE *S);
+
+static COLOUR_TABLE ctab_rehash(COLOUR_TABLE S, int newsize)
+{ COLOUR_TABLE NewS; int i;
+ NewS = ctab_new(newsize);
+ for( i = 1; i <= ctab_count(S); i++ )
+ ctab_insert(ctab_num(S, i), &NewS);
+ for( i = 0; i < ctab_size(S); i++ )
+ { if( ctab_name(S, i) != nilobj ) DisposeObject(ctab_name(S, i));
+ }
+ ifdebug(DMA, D, DebugRegisterUsage(MEM_COLOUR_TAB, -1,
+ -(2*sizeof(int) + ctab_size(S) * sizeof(struct coltab_rec))));
+ free(S);
+ return NewS;
+} /* end ctab_rehash */
+
+static void ctab_insert(OBJECT x, COLOUR_TABLE *S)
+{ int pos, num;
+ if( ctab_count(*S) == ctab_size(*S) - 1 ) /* one less since 0 unused */
+ *S = ctab_rehash(*S, 2*ctab_size(*S));
+ num = ++ctab_count(*S);
+ if( num > MAX_COLOUR )
+ Error(42, 2, "too many colours (maximum is %d)",
+ FATAL, &fpos(x), MAX_COLOUR);
+ hash(pos, string(x), *S);
+ if( ctab_name(*S, pos) == nilobj ) New(ctab_name(*S, pos), ACAT);
+ Link(ctab_name(*S, pos), x);
+ word_colour(x) = num;
+ ctab_num(*S, num) = x;
+} /* end ctab_insert */
+
+static OBJECT ctab_retrieve(FULL_CHAR *str, COLOUR_TABLE S)
+{ OBJECT x, link, y; int pos;
+ hash(pos, str, S);
+ x = ctab_name(S, pos);
+ if( x == nilobj ) return nilobj;
+ for( link = Down(x); link != x; link = NextDown(link) )
+ { Child(y, link);
+ if( StringEqual(str, string(y)) ) return y;
+ }
+ return nilobj;
+} /* end ctab_retrieve */
+
+#if DEBUG_ON
+static void ctab_debug(COLOUR_TABLE S, FILE *fp)
+{ int i; OBJECT x, link, y;
+ fprintf(fp, " table size: %d; current number of colours: %d\n",
+ ctab_size(S), ctab_count(S));
+ for( i = 0; i < ctab_size(S); i++ )
+ { x = ctab_num(S, i);
+ fprintf(fp, " ctab_num(S, %d) = %s\n", i,
+ x == nilobj ? AsciiToFull("<nilobj>") :
+ is_word(type(x)) ? string(x) : AsciiToFull("not WORD!"));
+ }
+ fprintf(fp, "\n");
+ for( i = 0; i < ctab_size(S); i++ )
+ { x = ctab_name(S, i);
+ fprintf(fp, "ctab_name(S, %d) =", i);
+ if( x == nilobj )
+ fprintf(fp, " <nilobj>");
+ else if( type(x) != ACAT )
+ fprintf(fp, " not ACAT!");
+ else for( link = Down(x); link != x; link = NextDown(link) )
+ { Child(y, link);
+ fprintf(fp, " %s",
+ is_word(type(y)) ? string(y) : AsciiToFull("not-WORD!"));
+ }
+ fprintf(fp, "\n");
+ }
+} /* end ctab_debug */
+#endif
+
+
+static COLOUR_TABLE col_tab;
+
+/*****************************************************************************/
+/* */
+/* ColourInit() */
+/* */
+/* Initialize this module. */
+/* */
+/*****************************************************************************/
+
+void ColourInit(void)
+{ col_tab = ctab_new(INIT_COLOUR_NUM);
+} /* end ColourInit */
+
+
+/*****************************************************************************/
+/* */
+/* ColourChange(style, x) */
+/* */
+/* Change the current style to contain the colour of colour command x. */
+/* */
+/*****************************************************************************/
+
+void ColourChange(STYLE *style, OBJECT x)
+{ OBJECT cname;
+ debug2(DCO, D, "ColourChange(%s, %s)", EchoStyle(style), EchoObject(x));
+
+ /* if argument is not a word, fail and exit */
+ if( !is_word(type(x)) )
+ { Error(42, 3, "%s ignored (illegal left parameter)", WARN, &fpos(x),
+ KW_COLOUR);
+ debug0(DCO, D, "ColourChange returning (colour unchanged)");
+ return;
+ }
+
+ /* if argument is empty, fail and exit */
+ if( StringEqual(string(x), STR_EMPTY) )
+ { if( BackEnd != PLAINTEXT )
+ Error(42, 4, "%s ignored (empty left parameter)", WARN, &fpos(x),
+ KW_COLOUR);
+ debug0(DCO, D, "ColourChange returning (colour unchanged)");
+ return;
+ }
+
+ /* if argument is nochange, do nothing */
+ if( StringEqual(string(x), STR_COLOUR_NOCHANGE) )
+ { debug0(DCO, D, "ColourChange returning (colour nochange)");
+ return;
+ }
+
+ /* retrieve colour command if present, else insert it */
+ { cname = ctab_retrieve(string(x), col_tab);
+ if( cname == nilobj )
+ { cname = MakeWord(type(x), string(x), &fpos(x));
+ ctab_insert(cname, &col_tab);
+ colour(*style) = word_colour(cname);
+ }
+ else colour(*style) = word_colour(cname);
+ }
+
+ debug1(DCO, D, "ColourChange returning (colour = %s)", string(cname));
+ ifdebug(DCO, DD, ctab_debug(col_tab, stderr));
+} /* ColourChange */
+
+
+/*@::ColourCommand()@*********************************************************/
+/* */
+/* FULL_CHAR *ColourCommand(cnum) */
+/* */
+/* Return the PostScript command for producing colour cnum. */
+/* */
+/*****************************************************************************/
+
+FULL_CHAR *ColourCommand(COLOUR_NUM cnum)
+{ FULL_CHAR *res;
+ debug1(DCO, D, "ColourCommand(%d)", cnum);
+ assert( cnum > 0 && cnum <= ctab_count(col_tab), "ColourCommand: number" );
+
+ res = string(ctab_num(col_tab, cnum));
+
+ debug1(DCO, D, "ColourCommand returning %s", res);
+ return res;
+} /* end ColourCommand */