Initial revision
[ssr] / StraySrc / Libraries / Steel / c / template
1 /*
2 * template.c
3 *
4 * Loading and manipulation of window templates
5 *
6 * © 1994-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Steel library.
12 *
13 * Steel is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * Steel is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Steel. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "os.h"
33 #include "wimp.h"
34 #include "utils.h"
35 #include "template.h"
36 #include "dll.h"
37 #include "mem.h"
38 #include "font.h"
39 #include "msgs.h"
40 #include "werr.h"
41 #include "res.h"
42 #include "resspr.h"
43
44 /*----- Note to the reader ------------------------------------------------*
45 *
46 * This code makes no use of Wimp_LoadTemplate at all. It's modified from
47 * the Glass template loading code, which as we all know is no slouch.
48 */
49
50 /*----- Variables ---------------------------------------------------------*/
51
52 static template *template__all;
53 static char template__fonts[256];
54 static BOOL template__usingFonts;
55
56 /*----- Main code ---------------------------------------------------------*/
57
58 #ifndef _dll_NODLL
59 extern void _dllEntry(template__exit)(void);
60 #endif
61
62 /*
63 * int template__cmp(char *a,char *b)
64 *
65 * Use
66 * Compares two strings of length 12 or less.
67 */
68
69 static int template__cmp(char *a,char *b)
70 {
71 int i;
72 for (i=0;i<12;i++)
73 {
74 if (*a<32 && *b<32)
75 return (0);
76 if (*a!=*b)
77 return (*a-*b);
78 a++;
79 b++;
80 }
81 return (0);
82 }
83
84 /*
85 * template *template_copy(template *from)
86 *
87 * Use
88 * Copies a template field-for-field and fixes up new indirected data for
89 * it.
90 */
91
92 template *template_copy(template *from)
93 {
94 template *t;
95 wimp_icon *ic;
96 int i;
97 int size=sizeof(template)+from->window.nicons*sizeof(wimp_icon);
98
99 /* --- Allocate a new template block and copy --- */
100
101 t=mem_alloc(size);
102 if (!t)
103 return (0);
104 memcpy(t,from,size);
105
106 /* --- Allocate a new indirected space block and copy that too --- */
107
108 if (!from->workspace)
109 return(t);
110
111 t->workspace=mem_alloc(t->workspacesize);
112 if (!t->workspace)
113 {
114 mem_free(t);
115 return (0);
116 }
117 memcpy(t->workspace,from->workspace,t->workspacesize);
118
119 /* --- Fix up all the indirected pointers --- */
120
121 if (t->window.titleflags & wimp_INDIRECT)
122 {
123 t->window.title.indirecttext.buffer+=t->workspace-from->workspace;
124 if (t->window.titleflags & wimp_ITEXT &&
125 t->window.title.indirecttext.validstring!=(char *)-1)
126 t->window.title.indirecttext.validstring+=t->workspace-from->workspace;
127 }
128
129 /* --- And for the icons --- */
130
131 ic=(wimp_icon *)(t+1);
132 for (i=0;i<t->window.nicons;i++)
133 {
134 if (ic->flags & wimp_INDIRECT)
135 {
136 ic->data.indirecttext.buffer+=t->workspace-from->workspace;
137 if (ic->flags & wimp_ITEXT &&
138 ic->data.indirecttext.validstring!=(char *)-1)
139 ic->data.indirecttext.validstring+=t->workspace-from->workspace;
140 }
141 ic++;
142 }
143
144 return (t);
145 }
146
147 /*
148 * void template__exit(void)
149 *
150 * Use
151 * Closes down all the fonts loaded with templates
152 */
153
154 _dll_static void template__exit(void)
155 {
156 int i,j;
157 for (i=0;i<256;i++)
158 {
159 for (j=0;j<template__fonts[i];j++)
160 font_lose(i);
161 }
162 }
163
164 /*
165 * BOOL template_readfile(char *name)
166 *
167 * Use
168 * Loads the template file named into memory, and sorts out all its
169 * indirected data.
170 *
171 * Template entries with strange identifiers are ignored. Other entry
172 * types may be supported later.
173 *
174 * Parameters
175 * char *name == the name of the template file to load (a resource file)
176 *
177 * Returns
178 * FALSE if the file contained no sprite icons. No, I don't understand
179 * the use of this either. It's not my problem though. I just write the
180 * code.
181 */
182
183 /* --- Macros from Glass's gStruct.h to help read the structure --- */
184
185 #define intptr(flex,offset) \
186 ((int *)(((char *)(flex))+(offset)))
187 #define charptr(flex,offset) \
188 (((char *)(flex))+(offset))
189 #define _ptr(type,flex,offset) \
190 ((type *)(((char *)(flex))+(offset)))
191
192 BOOL template_readfile(char *file)
193 {
194 /* --- Variables for loading the file --- */
195
196 char *filebuf;
197 os_filestr f;
198
199 /* --- Variables for mangling the file in memory --- */
200
201 int fontData; /* Offset of font ata from start of file */
202 template *w; /* For each window we come across */
203 int datasize; /* Size of indirected data for the window */
204 char *p=0; /* Offset in indirected data for next item*/
205 char *q; /* Pointer to an indirected string */
206 int index; /* Current index entry we're looking at */
207 char name[13]; /* For the name of the template */
208 int objoff; /* Offset of window we're looking at */
209 wimp_icon *iconptr; /* Offset of icon we're looking at */
210 wimp_iconflags icf; /* Icon flags for something or other */
211 int objtype; /* Type of current template entry */
212 int numicons; /* Number of icons in a window */
213 int i; /* A loop counter */
214 int pass; /* We take two passes at each window */
215
216 /* --- Font handling --- */
217
218 int fheight; /* Height of a font required */
219 int fwidth; /* Width of a font required */
220 int fhandle; /* Font handle */
221 int fptr; /* Offset of font name */
222 BOOL fquiet=FALSE; /* Shut up about font failures. */
223
224 /* --- Load the file into memory --- */
225
226 f.action=17;
227 f.name=file;
228 if (utils_complain(os_file(&f),
229 msgs_lookup("templateELF:Error loading template file: '%s'")))
230 {
231 exit(1);
232 }
233
234 filebuf=mem_alloc(f.start);
235 if (!f.start)
236 {
237 werr(FALSE,msgs_lookup("templateNEM:Not enough memory "
238 "to load template file."));
239 exit(1);
240 }
241
242 f.action=16;
243 f.loadaddr=(int)filebuf;
244 f.execaddr=0;
245 if (utils_complain(os_file(&f),
246 msgs_lookup("templateELF:Error loading template file: '%s'")))
247 {
248 exit(1);
249 }
250
251 /* --- Now start parsing up the file structure --- */
252
253 fontData=*intptr(filebuf,0);
254
255 /* --- Loop through each index entry in turn --- */
256
257 for (index=16;*intptr(filebuf,index);index+=24)
258 {
259 /* --- Find this entry's location in the file --- */
260
261 objoff=*intptr(filebuf,index);
262 objtype=*intptr(filebuf,index+8);
263
264 /* --- Mangle it according to its type --- */
265
266 switch (objtype)
267 {
268 case 1:
269
270 /* --- Find the name of the window and its number of icons --- */
271
272 memcpy(name,charptr(filebuf,index+12),12);
273 name[12]=0;
274 utils_ctermToNterm(name);
275 memcpy(&numicons,intptr(filebuf,objoff+84),sizeof(int));
276
277 /* --- Allocate a template block for it --- */
278
279 datasize=sizeof(template)+numicons*sizeof(wimp_icon);
280 w=mem_alloc(datasize);
281 if (!w)
282 {
283 werr(FALSE,msgs_lookup("templateNEM:Not enough memory "
284 "to load template file."));
285 exit(1);
286 }
287
288 /* --- Copy the template data into this block --- */
289
290 memcpy(&w->window,
291 _ptr(void,filebuf,objoff),
292 sizeof(wimp_wind)+numicons*sizeof(wimp_icon));
293
294 /* --- Set up the window's sprite area --- */
295
296 w->window.spritearea=resspr_area();
297
298 /* --- Now perform the two passes on the window data --- */
299
300 datasize=0;
301 for (pass=1;pass<=2;pass++)
302 {
303 icf=w->window.titleflags;
304
305 /* --- Handle title indirected data --- */
306
307 if (icf & wimp_INDIRECT)
308 {
309 if (pass==1)
310 {
311 /* --- Pass 1 just counts the size we need --- */
312
313 q=(int)w->window.title.indirecttext.buffer+filebuf+objoff;
314 utils_ctermToNterm(q);
315 datasize+=w->window.title.indirecttext.bufflen;
316 if (icf & wimp_ITEXT &&
317 w->window.title.indirecttext.validstring!=(char *)-1)
318 {
319 q=(int)w->window.title.indirecttext.validstring+
320 filebuf+
321 objoff;
322 utils_ctermToNterm(q);
323 datasize+=strlen(q)+1;
324 }
325 }
326 else
327 {
328 q=(int)w->window.title.indirecttext.buffer+filebuf+objoff;
329 memcpy(p,q,w->window.title.indirecttext.bufflen);
330 w->window.title.indirecttext.buffer=p;
331 p+=w->window.title.indirecttext.bufflen;
332 if (icf & wimp_ITEXT &&
333 w->window.title.indirecttext.validstring!=(char *)-1)
334 {
335 q=(int)w->window.title.indirecttext.validstring+
336 filebuf+
337 objoff;
338 strcpy(p,q);
339 w->window.title.indirecttext.validstring=p;
340 p+=strlen(q)+1;
341 }
342 }
343 }
344
345 /* --- Cope with antialiasing on the second pass --- */
346
347 if ((icf & wimp_IFONT) && pass==2)
348 {
349 /* --- Get the font handle --- */
350
351 fhandle=(icf & 0xff000000) >> 24;
352
353 /* --- Find information about the font --- */
354
355 fptr=fontData+(fhandle-1)*48;
356 memcpy(&fwidth,intptr(filebuf,fptr)+0,sizeof(int));
357 memcpy(&fheight,intptr(filebuf,fptr)+1,sizeof(int));
358 utils_ctermToNterm(charptr(filebuf,fptr+8));
359
360 /* --- Get a real font like this --- */
361
362 if (font_find(charptr(filebuf,fptr+8),
363 fwidth,
364 fheight,
365 0,0,
366 &fhandle))
367 {
368 if (!fquiet)
369 {
370 werr(FALSE,msgs_lookup("templateCFF:Some fonts used in this "
371 "template file could not be found. "
372 "Icons with such fonts will not be "
373 "anti-aliased."));
374 fquiet=TRUE;
375 }
376 icf&=~wimp_IFONT;
377 }
378 else
379 {
380 icf=(icf & 0x00ffffff) | (fhandle << 24);
381 template__fonts[fhandle]++;
382 if (!template__usingFonts)
383 {
384 atexit(_dllEntry(template__exit));
385 template__usingFonts=TRUE;
386 }
387 }
388 w->window.titleflags=icf;
389 }
390
391 /* --- Now handle each icon in turn like this --- */
392
393 iconptr=(wimp_icon *)(w+1);
394 for (i=0;i<numicons;i++)
395 {
396 icf=iconptr->flags;
397
398 /* --- Handle title indirected data --- */
399
400 if (icf & wimp_INDIRECT)
401 {
402 if (pass==1)
403 {
404 /* --- Pass 1 just counts the size we need --- */
405
406 q=(int)iconptr->data.indirecttext.buffer+filebuf+objoff;
407 utils_ctermToNterm(q);
408 datasize+=iconptr->data.indirecttext.bufflen;
409 if (icf & wimp_ITEXT &&
410 iconptr->data.indirecttext.validstring!=(char *)-1)
411 {
412 q=(int)iconptr->data.indirecttext.validstring+
413 filebuf+
414 objoff;
415 utils_ctermToNterm(q);
416 datasize+=strlen(q)+1;
417 }
418 }
419 else
420 {
421 q=(int)iconptr->data.indirecttext.buffer+filebuf+objoff;
422 memcpy(p,q,iconptr->data.indirecttext.bufflen);
423 iconptr->data.indirecttext.buffer=p;
424 p+=iconptr->data.indirecttext.bufflen;
425 if (icf & wimp_ITEXT &&
426 iconptr->data.indirecttext.validstring!=(char *)-1)
427 {
428 q=(int)iconptr->data.indirecttext.validstring+
429 filebuf+
430 objoff;
431 strcpy(p,q);
432 iconptr->data.indirecttext.validstring=p;
433 p+=strlen(q)+1;
434 }
435 }
436 }
437
438 /* --- Cope with antialiasing on the second pass --- */
439
440 if ((icf & wimp_IFONT) && pass==2)
441 {
442 /* --- Get the font handle --- */
443
444 fhandle=(icf & 0xff000000) >> 24;
445
446 /* --- Find information about the font --- */
447
448 fptr=fontData+(fhandle-1)*48;
449 memcpy(&fwidth,intptr(filebuf,fptr)+0,sizeof(int));
450 memcpy(&fheight,intptr(filebuf,fptr)+1,sizeof(int));
451 utils_ctermToNterm(charptr(filebuf,fptr+8));
452
453 /* --- Get a real font like this --- */
454
455 if (font_find(charptr(filebuf,fptr+8),
456 fwidth,
457 fheight,
458 0,0,
459 &fhandle))
460 {
461 if (!fquiet)
462 {
463 werr(FALSE,msgs_lookup("templateCFF:Some fonts used in "
464 "this template file could not be "
465 "found. Icons with such fonts "
466 "will not be anti-aliased."));
467 fquiet=TRUE;
468 }
469 icf&=~wimp_IFONT;
470 }
471 else
472 {
473 icf=(icf & 0x00ffffff) | (fhandle << 24);
474 template__fonts[fhandle]++;
475 if (!template__usingFonts)
476 {
477 atexit(_dllEntry(template__exit));
478 template__usingFonts=TRUE;
479 }
480 }
481 iconptr->flags=icf;
482 }
483 iconptr++;
484 }
485
486 /* --- Finish off the pass properly now --- */
487
488 if (pass==1)
489 {
490 /* --- Allocate the right amount of indirected space --- */
491
492 w->workspacesize=datasize;
493 if (datasize)
494 {
495 w->workspace=mem_alloc(datasize);
496 if (!w->workspace)
497 {
498 werr(FALSE,msgs_lookup("templateNEM:Not enough memory "
499 "to load template file."));
500 exit(1);
501 }
502 }
503 else
504 w->workspace=0;
505 p=w->workspace;
506 }
507 else
508 {
509 /* --- Link the filled in structure into the list --- */
510
511 w->next=template__all;
512 template__all=w;
513
514 /* --- Fill in the name of the template --- */
515
516 memcpy(w->name,name,12);
517 }
518 }
519 break;
520 }
521 }
522
523 /* --- Finished -- return to the user --- */
524
525 mem_free(filebuf);
526 return (TRUE); /* It can't do any harm, now, can it? */
527 }
528
529 /*
530 * void template_init(void)
531 *
532 * Use
533 * Loads the application's `Templates' file.
534 */
535
536 void template_init(void)
537 {
538 template_readfile(res_name("Templates"));
539 }
540
541 /*
542 * void template_use_fancyfonts(void)
543 *
544 * Use
545 * Does absolutely nothing at all. Fancy font support happens anyway.
546 */
547
548 void template_use_fancyfonts(void)
549 {
550 /* Do absolutely nothing at all :-) */
551 }
552
553 /*
554 * BOOL template_exists(char *name)
555 *
556 * Use
557 * Returns TRUE if the named template is known at the moment, or FALSE
558 * otherwise
559 */
560
561 BOOL template_exists(char *name)
562 {
563 template *t=template__all;
564 while (t)
565 {
566 if (!template__cmp(name,t->name))
567 return (TRUE);
568 t=t->next;
569 }
570 return (FALSE);
571 }
572
573 /*
574 * template *template_find(char *name)
575 *
576 * Use
577 * Locates a named template and returns a pointer to it
578 */
579
580 template *template_find(char *name)
581 {
582 template *t=template__all;
583 while (t)
584 {
585 if (!template__cmp(name,t->name))
586 return (t);
587 t=t->next;
588 }
589 werr(TRUE,msgs_lookup("templateNF:Template '%s' not found"),name);
590 return (0); /* FWIW */
591 }
592
593 /*
594 * wimp_wind *template_syshandle(char *name)
595 *
596 * Use
597 * Not very much, if the truth be known. It returns a pointer to a named
598 * window definition.
599 */
600
601 wimp_wind *template_syshandle(char *name)
602 {
603 return (&template_find(name)->window);
604 }
605
606 /*
607 * BOOL template_loaded(void)
608 *
609 * Use
610 * Returns TRUE if we have templates on board.
611 */
612
613 BOOL template_loaded(void)
614 {
615 return (template__all ? TRUE : FALSE);
616 }