aboutsummaryrefslogtreecommitdiffstats
path: root/z52.c
blob: ac9cf3f58ed0be922325fdc3528353f657ffe93d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*@z52.c:Texture Service:TextureChange, TextureCommand@***********************/
/*                                                                           */
/*  THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.41)                       */
/*  COPYRIGHT (C) 1991, 2023 Jeffrey H. Kingston                             */
/*                                                                           */
/*  Jeffrey H. Kingston (jeff@it.usyd.edu.au)                                */
/*  School of Information Technologies                                       */
/*  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 3, 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:         z52.c                                                      */
/*  MODULE:       Texture Service                                            */
/*  EXTERNS:      TextureChange(), TextureCommand()                          */
/*                                                                           */
/*****************************************************************************/
#include "externs.h"
#include "child.h"
#define INIT_TEXTURE_NUM	100


/*****************************************************************************/
/*                                                                           */
/*  TEXTURE_TABLE                                                            */
/*                                                                           */
/*  A symbol table permitting access to texture records by number or name.   */
/*  The table will automatically enlarge to accept any number of entries,    */
/*  but there is an arbitrary limit of 65535 textures imposed so that texture*/
/*  numbers can be stored in 16 bit fields.                                  */
/*                                                                           */
/*     ptab_new(newsize)                 New empty table, newsize capacity   */
/*     ptab_insert(x, &S)                Insert new texture object x into S  */
/*     ptab_retrieve(str, S)             Retrieve texture object of name str */
/*     ptab_num(S, num)                  Retrieve texture object, number num */
/*     ptab_debug(S, fp)                 Debug print of table S to file fp   */
/*                                                                           */
/*****************************************************************************/

typedef struct
{ int pattab_size;				/* size of table             */
  int pattab_count;				/* number of textures held   */
  struct pattab_rec
  {	OBJECT	by_number;			/* texture record by number  */
	OBJECT	by_name_hash;			/* texture record by name    */
  } pattab[1];
} *TEXTURE_TABLE;

#define	ptab_size(S)	(S)->pattab_size
#define	ptab_count(S)	(S)->pattab_count
#define	ptab_num(S, i)	(S)->pattab[i].by_number
#define	ptab_name(S, i)	(S)->pattab[i].by_name_hash

#define hash(pos, str, S)						\
{ FULL_CHAR *p = str;							\
  pos = *p++;								\
  while( *p ) pos += *p++;						\
  pos = pos % ptab_size(S);						\
}

static TEXTURE_TABLE ptab_new(int newsize)
{ TEXTURE_TABLE S;  int i;
  ifdebug(DMA, D, DebugRegisterUsage(MEM_TEXTURE_TAB, 1,
    2*sizeof(int) + newsize * sizeof(struct pattab_rec)));
  S = (TEXTURE_TABLE) malloc(2*sizeof(int) + newsize * sizeof(struct pattab_rec));
  if( S == (TEXTURE_TABLE) NULL )
    Error(42, 1, "ran out of memory when enlarging texture table",
      FATAL, no_fpos);
  ptab_size(S) = newsize;
  ptab_count(S) = 0;
  for( i = 0;  i < newsize;  i++ )
  { ptab_num(S, i) = ptab_name(S, i) = nilobj;
  }
  return S;
} /* end ptab_new */

static void ptab_insert(OBJECT x, TEXTURE_TABLE *S);

static TEXTURE_TABLE ptab_rehash(TEXTURE_TABLE S, int newsize)
{ TEXTURE_TABLE NewS;  int i;
  NewS = ptab_new(newsize);
  for( i = 1;  i <= ptab_count(S);  i++ )
     ptab_insert(ptab_num(S, i), &NewS);
  for( i = 0;  i < ptab_size(S);  i++ )
  { if( ptab_name(S, i) != nilobj )  DisposeObject(ptab_name(S, i));
  }
  ifdebug(DMA, D, DebugRegisterUsage(MEM_TEXTURE_TAB, -1,
    -(2*sizeof(int) + ptab_size(S) * sizeof(struct pattab_rec))));
  free(S);
  return NewS;
} /* end ptab_rehash */

static void ptab_insert(OBJECT x, TEXTURE_TABLE *S)
{ int pos, num;					
  if( ptab_count(*S) == ptab_size(*S) - 1 )	/* one less since 0 unused */
    *S = ptab_rehash(*S, 2*ptab_size(*S));
  num = ++ptab_count(*S);
  if( num > MAX_TEXTURE )
    Error(42, 2, "too many textures (maximum is %d)",
      FATAL, &fpos(x), MAX_TEXTURE);
  hash(pos, string(x), *S);
  if( ptab_name(*S, pos) == nilobj )  New(ptab_name(*S, pos), ACAT);
  Link(ptab_name(*S, pos), x);
  word_texture(x) = num;
  ptab_num(*S, num) = x;
} /* end ptab_insert */

static OBJECT ptab_retrieve(FULL_CHAR *str, TEXTURE_TABLE S)
{ OBJECT x, link, y;  int pos;
  hash(pos, str, S);
  x = ptab_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 ptab_retrieve */

#if DEBUG_ON
static void ptab_debug(TEXTURE_TABLE S, FILE *fp)
{ int i;  OBJECT x, link, y;
  fprintf(fp, "  table size: %d;  current number of textures: %d%s",
    ptab_size(S), ptab_count(S), STR_NEWLINE);
  for( i = 0;  i < ptab_size(S);  i++ )
  { x = ptab_num(S, i);
    fprintf(fp, "  ptab_num(S, %d) = %s%s", i,
      x == nilobj ? AsciiToFull("<nilobj>") :
      is_word(type(x)) ? string(x) : AsciiToFull("not WORD!"), STR_NEWLINE);
  }
  fprintf(fp, "%s", STR_NEWLINE);
  for( i = 0;  i < ptab_size(S);  i++ )
  { x = ptab_name(S, i);
    fprintf(fp, "ptab_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, "%s", STR_NEWLINE);
  }
} /* end ptab_debug */
#endif


static TEXTURE_TABLE pat_tab;

/*****************************************************************************/
/*                                                                           */
/*  UseTexture                                                               */
/*                                                                           */
/*  When set to FALSE (by z01.c), means to ignore texture changing commands. */
/*                                                                           */
/*****************************************************************************/

BOOLEAN UseTexture = TRUE;


/*****************************************************************************/
/*                                                                           */
/*  TextureInit()                                                            */
/*                                                                           */
/*  Initialize this module.                                                  */
/*                                                                           */
/*****************************************************************************/

void TextureInit(void)
{ OBJECT cname;

  /* initial texture table is empty */
  pat_tab = ptab_new(INIT_TEXTURE_NUM);

  /* insert "LoutTextureSolid" as texture number 1 */
  cname = MakeWord(WORD, AsciiToFull("LoutTextureSolid"), no_fpos);
  ptab_insert(cname, &pat_tab);
} /* end TextureInit */


/*****************************************************************************/
/*                                                                           */
/*  TextureChange(style, x)                                                  */
/*                                                                           */
/*  Change the current style to contain the texture of texture command x.    */
/*                                                                           */
/*****************************************************************************/

void TextureChange(STYLE *style, OBJECT x)
{ OBJECT cname;
  debug2(DTX, D, "TextureChange(%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_TEXTURE);
    debug0(DTX, D, "TextureChange returning (texture unchanged)");
    return;
  }

  /* if not using textures, do nothing */
  if( !UseTexture )
  { debug0(DTX, D, "TextureChange returning (not UseTexture)");
    return;
  }

  /* if argument is nochange, do nothing */
  if( StringEqual(string(x), STR_TEXTURE_NOCHANGE) ||
      StringEqual(string(x), STR_EMPTY) )
  { debug0(DTX, D, "TextureChange returning (texture nochange)");
    return;
  }

  /* retrieve texture command if present, else insert it */
  { cname = ptab_retrieve(string(x), pat_tab);
    if( cname == nilobj )
    { cname = MakeWord(type(x), string(x), &fpos(x));
      ptab_insert(cname, &pat_tab);
      texture(*style) = word_texture(cname);
    }
    else texture(*style) = word_texture(cname);
  }

  debug2(DTX, D, "TextureChange returning %d (texture = %s)",
   texture(*style), string(cname));
  ifdebug(DTX, DD, ptab_debug(pat_tab, stderr));
} /* TextureChange */


/*@::TextureCommand()@********************************************************/
/*                                                                           */
/*  FULL_CHAR *TextureCommand(pnum)                                          */
/*                                                                           */
/*  Return the PostScript command for producing texture pnum.                */
/*                                                                           */
/*****************************************************************************/

FULL_CHAR *TextureCommand(TEXTURE_NUM pnum)
{ FULL_CHAR *res;
  debug1(DTX, D, "TextureCommand(%d)", pnum);
  assert( pnum > 0 && pnum <= ptab_count(pat_tab), "TextureCommand: number" );

  res = string(ptab_num(pat_tab, pnum));

  debug1(DTX, D, "TextureCommand returning %s", res);
  return res;
} /* end TextureCommand */