/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Template.LoadFile.c
    Author:  Copyright  1992 Jason Williams
             Thanks to John Winters for supplying the code that I hacked
             changed, hacked, rewrote, and then wrote again from scratch!
    Version: 1.12 (02 Mar 1994)
    Purpose: Loading, cacheing, and retrieval of window templates
             Now correctly loads templates with outline fonts in them
*/


#include "TempDefs.h"


/* Not intended for user consumption */
Desk_linklist_header Desk_template_list         = {NULL, NULL};
Desk_font_array      *Desk_template_fontarray   = (Desk_font_array *) -1;

/* 
Provide function veneers for the above globals - they are refered to by the
Desk_Window_ModeChange() function.
*/
#ifdef _DLL
extern Desk_linklist_header  *Desk_Template__Ref_list( void)      { return &Desk_template_list;      }
extern Desk_font_array      **Desk_Template__Ref_fontarray( void) { return &Desk_template_fontarray; }
#endif



static void ReadHeader(char *filename)
/* Find out how many templates, names, and sizes */
{
  FILE *filehandle;
  int  buffer[10];  /* 40 byte file buffer */
  int  i, numtemplates;
  char *s;
  Desk_template_record *temprec;

  filehandle = fopen(filename, "rb");
  if (filehandle == NULL)
    Desk_Error_ReportFatalInternal(ERR7, ERRMESS7);

  if (fread(buffer, Desk_HEADER_SIZE, 1, filehandle) != 1)
  {
    fclose(filehandle);
    Desk_Error_ReportFatalInternal(ERR4, ERRMESS4);
  }

  numtemplates = 0;
  while(Desk_bool_TRUE)
  {
    if (fread(&buffer[0], Desk_INDEX_SIZE, 1, filehandle) != 1)
    {
      fclose(filehandle);
      Desk_Error_ReportFatalInternal(ERR5, ERRMESS5);
    }

    if (buffer[0] == 0) /* template list terminator */
      break;

    numtemplates++;
    temprec = (Desk_template_record *) Desk_DeskMem_XMalloc(sizeof(Desk_template_record));

    i = 0;
    s = (char *) &buffer[3];
    buffer[6] = 0;  /* Ensure terminators after 12-bytes of name */
    while (Desk_bool_TRUE)
    {      
      if (s[i] < 32)
      {
        temprec->identifier[i] = '\0';
        break;
      }
      temprec->identifier[i] = s[i];

      i++;
    }

    temprec->dataoffset   = buffer[0];
    temprec->templatesize = buffer[1];     /* size needed to load template */
    temprec->windowdef    = NULL;
    temprec->indirectdata = NULL;
    Desk_LinkList_Init(&(temprec->header));
    Desk_LinkList_AddToTail(&Desk_template_list, &(temprec->header));
  }

  fclose(filehandle);
}



extern void Desk_Template_LoadFile(const char *leafname)
{
  Desk_template_record *tptr;
  char            filename[60];
  char            tempname[20];
  Desk_template_block  tblock;
  char            tempdata[5192];        /* temp. buffer for indirected data */

  strcpy(filename, Desk_resource_pathname);
  strcat(filename, leafname);

  /* Remember the end of the template list - this will be NULL for the
   * first call to Desk_Template_LoadFile, and non-NULL for subsequent calls.
   */
  tptr = (Desk_template_record *) Desk_template_list.previous;

  ReadHeader(filename);     /* Find out how many templates, names, and sizes */
  Desk_Wimp_eOpenTemplate(filename);

  /* If tptr is NULL, then this is the first time we have loaded any templates,
   * so get the head of the list to find the first blank record supplied by
   * ReadHeader().  If tptr is not NULL, then we are appending templates, so
   * get the next record after tptr, as this will be the first blank record
   * just added by ReadHeader().
   */
  if (tptr == NULL)
    tptr = (Desk_template_record *) Desk_template_list.next;
  else
    tptr = (Desk_template_record *) tptr->header.next;
  
  while (tptr != NULL)
  {
    tptr->windowdef = (Desk_window_block *) Desk_DeskMem_XMalloc(tptr->templatesize);
    if (tptr->windowdef == NULL)
    {
      Desk_Wimp_eCloseTemplate();
      Desk_Error_ReportFatalInternal(ERR3, ERRMESS3);
    }

/*  Now, read template once to determine the indirected data size needed.
 *  I tried many different methods to do this, but thrashing in all the icons
 *  and counting their indirect text buffer sizes, and then thrashing in
 *  all of the validation strings and counting their lengths was slow, nasty,
 *  and didn't seem very reliable.
 *  This way also produces a much smaller code lump to include in DeskLib
 *  It works very nicely, so long as your indirected data doesn't expand
 *  to more than 5kB (unlikely unless you are being very antisocial towards
 *  Mr. Wimp)
 */
    tblock.buffer   = tptr->windowdef;
    tblock.workfree = tempdata;
    tblock.workend  = tblock.workfree + 5188;

    /* The following line has been changed. If the font array was not passed
     * in here as well, the fonts were not handled at all...
     */
    tblock.font     = Desk_template_fontarray;   /* was  (Desk_font_array *) -1 */
    strcpy(tempname, tptr->identifier);
    tblock.name     = tempname;
    tblock.index    = 0;
    Desk_Wimp_eLoadTemplate(&tblock);

    tptr->indirectsize = (tblock.workfree - tempdata) + 4;
    tptr->indirectdata = (char *) Desk_DeskMem_XMalloc(tptr->indirectsize);
    if (tptr->indirectdata == NULL)
    {
      Desk_Wimp_eCloseTemplate();
      Desk_Error_ReportFatalInternal(ERR3, ERRMESS3);
    }

/*  Now, do a Desk_Template_Load to actually load in the template. Should be nice
 *  and quick, as the previous load should have cached the data in a buffer
 *  so more disc reading is unlikely. (Though don't quote me on that! ;-)
 */
    tblock.buffer   = tptr->windowdef;
    tblock.workfree = tptr->indirectdata;
    tblock.workend  = tblock.workfree + tptr->indirectsize;
    tblock.font     = Desk_template_fontarray;
    strcpy(tempname, tptr->identifier);
    tblock.name     = tempname;
    tblock.index    = 0;
    Desk_Wimp_eLoadTemplate(&tblock);

    tptr = (Desk_template_record *) tptr->header.next;
  }

  Desk_Wimp_eCloseTemplate();
}
