/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Title:  template.c
 * Purpose:  Template file management
 * History:  8-Mar-89 IDJ created
 *           22-May-89  IDJ added mosticons and mostspace to allow any
 *                          size of template to be loaded.
 *           1-June-89  IDJ Kludge added to allow more workspace
 *                          for indirected icons (dunno why this is needed)
 *           5-Feb-90  IDJ added template_use_fancyfonts()
 *           8-May-91  ECN #ifndefed out unused ROM functions
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string.h>

#include "swis.h"
#include "os.h"
#include "wimp.h"
#include "wimpt.h"
#include "res.h"
#include "sprite.h"
#include "resspr.h"
#include "werr.h"
#include "template.h"
#include "trace.h"
#include "msgs.h"
#include "font.h"
#include "h.verintern.messages"

/*
 * Templates held in private linked list
 */

static  template *template__list = 0;
static  wimp_font_array *template__fontcounts = 0;


static BOOL template__nameeq(char *s, char *t)
{
    int i;

    for (i = 0; i < 12; i++) {
        if (*s < ' ' && *t < ' ') return 1;
        if (*s < ' ' || *t < ' ') return 0;
        if (*s++ != *t++) return 0;
    }
    return 1;
}

static void *template_alloc(int n)
{
    void *p;

    p = malloc(n);
    if (!p) werr(1, msgs_lookup(MSGS_template2));
    return p;
}

template *template_find(char *name)
{
  template *t = template__list;
  while (t != 0 && template__nameeq(name, t->name) == 0) t=t->next;
  if (t == 0) werr(1, msgs_lookup(MSGS_template1), name);
  return(t);
}

template *template_copy(template *from)
{
  template *to;
  int j;
  int windowsize, size;
  int reloc;

  windowsize = sizeof(template) + from->window.nicons * sizeof(wimp_icon);
  size = windowsize + from->workspacesize;

  /* --- copy the template --- */
  to = malloc(size);
  if (to == 0) return 0;

  memcpy(to, from, windowsize);

  if (to->workspacesize) {
    to->workspace = (char *)to + windowsize;
    memcpy(to->workspace, from->workspace, to->workspacesize);
    reloc = (int)to->workspace - (int)from->workspace;

    /* - fix up indirect icon pointers - */
    for (j=0; j<to->window.nicons; j++)
    {
      wimp_icon *i = ((wimp_icon *)(&to->window + 1)) + j;
      if ((i->flags & wimp_INDIRECT) != 0)
      {
        i->data.indirecttext.buffer += reloc;
        if ((i->flags & wimp_ITEXT) != 0 &&
            ((int) i->data.indirecttext.validstring) > 0)
          i->data.indirecttext.validstring += reloc;
      }
    }

    /* --- fix up relocated title pointer --- */
    if ((to->window.titleflags & wimp_INDIRECT) != 0)
      to->window.title.indirecttext.buffer += reloc;

  }

  to->next = 0;
  return to;
}

BOOL (template_readfile)(char *filename)
{
  template *to;          /* for insertion into linked list */
  int sprites = 0;       /* are sprites used? */
  int j;
  int index;
  char name[12];
  int windowsize, datasize;

  _swi(Wimp_OpenTemplate, _IN(1), filename);
  index = 0;
  while (1)
  {
    *((int *)name) = '*';
    if (!_swi(Wimp_LoadTemplate,
              _IN(1)|_IN(5)|_IN(6)|_OUT(1)|_OUT(2)|_RETURN(6),
              -1, name, index, &windowsize, &datasize))
        break;
    windowsize = (windowsize + 3) & ~3;
    to = template_alloc(offsetof(template, window) + windowsize + datasize);
    to->next = template__list;
    template__list = to;
    to->workspace = (char *)&to->window + windowsize;
    to->workspacesize = datasize;
    *((int *)to->name) = '*';
    index = _swi(Wimp_LoadTemplate,
                 _IN(1)|_IN(2)|_IN(3)|_IN(4)|_IN(5)|_IN(6)|_RETURN(6),
                 &to->window, to->workspace, to->workspace + datasize,
                 template__fontcounts ? template__fontcounts : (void *)-1,
                 to->name, index);

    /* --- look for sprites --- */
    if (!sprites) {
        for (j=0; j < to->window.nicons; j++)
        {
            /* - icons come after buffer->window in memory - */
            wimp_icon *i = ((wimp_icon *)(&to->window + 1)) + j;
            if ((i->flags & wimp_ISPRITE) != 0)
            {
                 sprites = 1;
                 break;
            }
        }
    }

    /* --- bind sprite area appropriately --- */
    to->window.spritearea = resspr_area();

  }

  /* --- close the template file and free up temporary space --- */
  _swi(Wimp_CloseTemplate, 0);
  return sprites;
}


BOOL template_loaded(void)
{
   return ((BOOL)template__list);
}

#ifndef UROM
static void template__loseallfonts(void)
{
   int num, used;

   if (template__fontcounts != 0)
   {
      for (num = 0; num < 256; num++)
          for (used = 0; used < template__fontcounts->f[num]; used++)
              wimpt_noerr(font_lose(num));
   }
}
#endif

#ifndef UROM
void template_use_fancyfonts(void)
{
   if (template__fontcounts == 0) {
      template__fontcounts = template_alloc(sizeof(wimp_font_array));
      memset(template__fontcounts, 0, 256);
      atexit(template__loseallfonts);
   }
}
#endif

void template_init(void)
{
  char s[40];

  if (res_findname("Templates", s))
    (template_readfile)(s);

  return;

}


wimp_wind *template_syshandle(char *name)
{
  template *tem;

  /* find template in linked list */
  if ((tem = template_find(name)) == 0)
    return ((wimp_wind *)0);

  /* return pointer to underlying window structure */
  return (&(tem -> window));
}