[comp.sys.amiga] gadio.c - 7 of 21

crunch@well.UUCP (John Draper) (12/03/86)

/*=============================================================================
  gadio.c - Functions to save/retrieve a gadget to/from disk.
  Brent Southard, 7/10/86
  CIS   76657,415
  Well  brent
 
  -Change History-
  7/6/86  rbs  Changed dumpGad() and grabGad() to only write/read one Gadget
               at a time, rather than a list.  The NextGadget field will now
               be ignored at 'dump' time, and NULLed at 'grab' time.
===============================================================O=============*/
 
/*  The usual header files to be inserted later  */
#include <intuition/intuition.h>
#include <libraries/dosextens.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/display.h>
#include <exec/memory.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <devices/narrator.h>
#include <devices/audio.h>
#include <libraries/translator.h>
#include "gad.h"
 
/*================== external functions ===================*/
 
extern int  strlen();
extern char *strcpy();
extern APTR AllocRemember();
 
/*================== external variables ==================*/
 
extern char gadimage[MAX_PROPINFOS][NAM_SIZ];
extern char selectimage[MAX_PROPINFOS][NAM_SIZ];
 
/*====================== globals ==========================*/
 
#define CLRMEM      MEMF_CHIP | MEMF_CLEAR
#define VERY_BIG    512
 
static UBYTE        scratch[VERY_BIG];
extern struct Remember  *rememberBase;
extern char def_font[]; /* name of the default font used in intuitexts */
/*==================== sub-functions ======================*/
 
void freeGadMem()  /* free allocated gadget memory (use carefully!) */
/*  Call this function before ending main().  This may not be an elegant way
    to free up space, but it works... */
{
    FreeRemember(rememberBase, TRUE);
    rememberBase = NULL;
}
 
void putString(str, fd)  /* write a null-terminated string to a file */
UBYTE   *str;
long     fd;
{
    /* Write the text, including the null byte. */
    Write(fd, str, (long)(strlen(str)+1));
}
 
UBYTE *getString(fd,stringsize)  /* read a null-terminated string from a file */
long     fd;
long     stringsize;
{
    UBYTE   *str;
    int     i = 0;
 
    /* Read the text, including the null byte, into scratch area. */
    do { Read(fd, &scratch[i], 1L); }
        while (scratch[i++] != '\0');
 
    /* Allocate memory for string and move it there. */
    /* ### changed to allocate only enough for the   */
    /* string if the stringsize parm is zero, and    */
    /* whatever specified if string size is not zero */
    /* This prevents crashes where the user inserts  */
    /* to a string gadget after reading it.    RRL   */
    if (stringsize == 0L)
        str = (UBYTE *)
          AllocRemember(rememberBase, (LONG)(strlen(scratch)+1), CLRMEM);
    else  str = (UBYTE *)
          AllocRemember(rememberBase, stringsize, CLRMEM);
 
    strcpy(str, scratch);
 
    return(str);
}
 
/* write (list of) image structure(s) to a file */
void putImages(anImage, fd, ind)
struct Image    *anImage;
long            fd;
int             ind;
{
    short   wordWidth, size;
 
   while (anImage != NULL) {
        /* Write name of Image to file */
        /* ### only if it's not an autoknob image for a prop gad. RRL */
        if (ind >= 0) {
           Write(fd, gadimage[ind], (long)NAM_SIZ);
           Write(fd, selectimage[ind], (long)NAM_SIZ);
        }
 
        /*  Write image structure itself. */
 
        Write(fd, anImage, (long)sizeof(struct Image));
        /* Thare should be some data to write (we would hope!) */
        if (anImage->ImageData != NULL) {
            wordWidth = anImage->Width / 16;
            if (anImage->Width % 16 != 0)
                wordWidth++;
            /* size is wordWidth (x 2 bytes/word) x Height x Depth */
            size = wordWidth * 2 * anImage->Height * anImage->Depth;
 
            Write(fd, anImage->ImageData, (long)size);
        }
 
        /* Another image? */
        anImage = anImage->NextImage;
    }
}
 
struct Image *getImages(fd, ind)  /* read image structure(s) from a file */
long  fd;
int   ind;
{
    struct Image    *anImage, *first;
    BOOL            done = FALSE;
    short           wordWidth;
    LONG            size;
 
    first = anImage = (struct Image *)
        AllocRemember(rememberBase, (long)sizeof(struct Image), CLRMEM);
 
    do {
        /* Get name of select and render images */
        /* ### only if it is not an autoknob RRL*/
        if (ind >= 0) {
           Read(fd, gadimage[ind], (long)NAM_SIZ);
           Read(fd, selectimage[ind], (long)NAM_SIZ);
        }
 
        /* Read image structure itself. */
        Read(fd, anImage, (long)sizeof(struct Image));
 
        /* There should be some data to read (we would hope!) */
        if (anImage->ImageData != NULL) {
            wordWidth = anImage->Width / 16;
            if (anImage->Width % 16 != 0)
                wordWidth++;
            /* size is wordWidth (x 2 bytes/word) x Height x Depth */
            size = wordWidth * 2 * anImage->Height * anImage->Depth;
            anImage->ImageData = (USHORT *)
                AllocRemember(rememberBase, size, CLRMEM);
            Read(fd, anImage->ImageData, size);
        }
 
        /* Another image? */
        if (anImage->NextImage != NULL) {
            anImage->NextImage = (struct Image *)
                AllocRemember(rememberBase, (long)sizeof(struct Image), CLRMEM);
            anImage = anImage->NextImage;
        }
        else
            done = TRUE;
    } while (! done);
 
    return(first);
}
 
void putBorders(aBorder, fd)  /* write (list of) border structure(s) to file */
struct Border   *aBorder;
long            fd;
{
    int i;   /* ### */
 
    while (aBorder != NULL) {
        /* Write border structure itself. */
 
        Write(fd, aBorder, (long)sizeof(struct Border));
 
        /* There should be some data to write (we would hope!) */
        if (aBorder->Count > 0 && aBorder->XY != NULL) {
            Write(fd, aBorder->XY, (long)(aBorder->Count*4));
        }
 
        /* Another border? */
        aBorder = aBorder->NextBorder;
    }
}
 
struct Border *getBorders(fd)  /* read border structure(s) from file */
long  fd;
{
    struct Border   *aBorder, *first;
    BOOL            done = FALSE;
 
    first = aBorder = (struct Border *)
        AllocRemember(rememberBase, (long)sizeof(struct Border), CLRMEM);
 
    do {
        /* Read border structure itself. */
        Read(fd, aBorder, (long)sizeof(struct Border));
 
        /* There should be some data to read (we would hope!) */
        if (aBorder->Count > 0 && aBorder->XY != NULL) {
           /* RRL added this - nice to have a place to put the pairs! */
           aBorder->XY = (SHORT *)
            AllocRemember(rememberBase, (long)(aBorder->Count*4), CLRMEM);
 
            Read(fd, aBorder->XY, (long)(aBorder->Count*4));
         }
        /* Another border? */
        if (aBorder->NextBorder != NULL) {
            aBorder->NextBorder = (struct Border *)
                AllocRemember(rememberBase, (long)sizeof(struct Border), CLRMEM)
;
            aBorder = aBorder->NextBorder;
        }
        else
            done = TRUE;
    } while (! done);
 
    return(first);
}
 
void putPropInfo(aPropInfo, fd)  /* write proportional gadget info */
struct PropInfo *aPropInfo;
long            fd;
/* Note that only the first 5 fields really need to be saved. */
{
    /* No pointers involved here, so we just write the structure */
    Write(fd, aPropInfo, (long)sizeof(struct PropInfo));
}
 
struct PropInfo *getPropInfo(fd)  /* read proportional gadget info */
long  fd;
/* Note that only the first 5 fields really need to be read.  Intuition
   initializes the others. */
{
    struct PropInfo *aPropInfo;
 
    /* No pointers involved here, so we just read the structure */
    aPropInfo = (struct PropInfo *)
        AllocRemember(rememberBase, (long)sizeof(struct PropInfo), CLRMEM);
    Read(fd, aPropInfo, (long)sizeof(struct PropInfo));
    return(aPropInfo);
}
 
void putIText(anIText, fd)  /* write (list of) IntuiText structure(s) to file */
struct IntuiText    *anIText;
long                fd;
{
   while (anIText != NULL) {
        /* Start by writing structure into file. */
        Write(fd, (char *)anIText, (long)sizeof(struct IntuiText));
 
        /* If non-system font, save font attributes next */
        if (anIText->ITextFont != NULL) /* gonna have to store a structure */
            Write(fd, (APTR) anIText->ITextFont, (long)sizeof(struct TextAttr));
 
        /* Write the text now.  Read function will read up to zero-byte to
           get the whole string. */
        putString(anIText->IText, fd);
 
        /* Do it again, if there's more text following... */
        anIText = anIText->NextText;
    }
}
 
struct IntuiText *getIText(fd)  /* opposite of putIText(). */
long  fd;
{
    struct IntuiText    *anIText, *first, *new;
    BOOL                done = FALSE;
 
    /* Allocate memory for first structure. */
    first = anIText = (struct IntuiText *)
        AllocRemember(rememberBase, (long)sizeof(struct IntuiText), CLRMEM);
 
    do {
        /* Read structure from file. */
        Read(fd, anIText, (long)sizeof(struct IntuiText));
 
        /* If non-system font used, get proper font structure. */
        if (anIText->ITextFont != NULL) {
            anIText->ITextFont = (struct TextAttr *)
                AllocRemember(rememberBase,
                  (long)sizeof(struct TextAttr),CLRMEM);
            Read(fd, anIText->ITextFont, (long)sizeof(struct TextAttr));
            /* added by RRL - ITextFont is another pointer */
            anIText->ITextFont->ta_Name = (STRPTR)def_font;
        }
        /* Read the text now.  Read up to (and including) zero-byte. */
        anIText->IText = getString(fd,0L);
        /* Do it again, if there's more text following... */
        if (anIText->NextText != NULL) {
           anIText->NextText = (struct IntuiText *)
              AllocRemember(rememberBase,
                (long)sizeof(struct IntuiText),CLRMEM);
           anIText = anIText->NextText; /* this was missing - RRL */
        }
        else
            done = TRUE;
    } while (! done);
 
    return(first);
}
 
void putStringInfo(aStringInfo, fd)  /* this is the toughie!!! */
struct StringInfo   *aStringInfo;
long                fd;
/* Note that only the first 5 fields really need to be saved. */
{
    /* First, write the entire stucture (this is really overkill). */
    Write(fd, aStringInfo, (long)sizeof(struct StringInfo));
 
    /* Now, if the Buffer or UndoBuffer are non-NULL, write 'em. */
    if (aStringInfo->Buffer != NULL)
        putString(aStringInfo->Buffer, fd);
    if (aStringInfo->UndoBuffer != NULL)
        putString(aStringInfo->UndoBuffer, fd);
}
 
struct StringInfo *getStringInfo(fd)  /* likewise! */
long  fd;
/* Note that only the first 5 fields really need to be saved.  Intuition
   initializes the rest (presumably at AddGadget() time) */
{
    struct StringInfo   *aStringInfo;
 
    /* Allocate some storage. */
    aStringInfo = (struct StringInfo *)
        AllocRemember(rememberBase, (long)sizeof(struct StringInfo), CLRMEM);
 
    /* Read the entire stucture. */
    Read(fd, aStringInfo, (long)sizeof(struct StringInfo));
 
    /* Now, if the Buffer or UndoBuffer are non-NULL, read 'em. */
    if (aStringInfo->Buffer != NULL)
        aStringInfo->Buffer = getString(fd,BUFSIZE);
    if (aStringInfo->UndoBuffer != NULL)
        aStringInfo->UndoBuffer = getString(fd,BUFSIZE);
 
    return(aStringInfo);
}
 
/*==================== the functions ======================*/
 
void dumpGad(aGad, fd, ind)  /* save a gadget in binary form to a file */
struct Gadget   *aGad;
long            fd;
int            ind;
 
/* This function dumps the contents of one gadget to a file.  It does not
   write the gadget name, or any other information not included in the gadget
   structure or sub-structures themselves;  that is the responsibility of the
   calling function.
*/
{
struct PropInfo *pi;
 
    /* First we write out the Gadget structure itself.
       Wait a sec', it's not that easy!  For instance, do we want to write
       the actual values of the pointers?  No!  This would be rather silly,
       since they're of no use in the future.  Instead, we'll use their
       fields to express boolean information in simpler terms.  No reason
       to mess with crazy values, when we can say what we mean, right?
       On the other hand, the pointers are boolean already (i.e. either
       zero (NULL, FALSE), or non-zero (addr, TRUE), so we really don't
       need to mess with them.  After all, it's up to the READING program
       to be sure to initialize all the pointers for us, clearing any
       garbage values for us.  Once again, simplicity wins...
     ### */
 
    Write(fd, aGad, (long)sizeof(struct Gadget));
 
    /* Now, do we have GadgetRender structures to worry about? */
    /* ### we also have to deal with Prop. Gadget AUTOKNOBs RRL*/
    if (aGad->GadgetRender != NULL) {                    /* Yes, we do! */
        if (aGad->Flags & GADGIMAGE) {                    /* Image(s) */
            /* write Image structures (IN ORDER) */
            putImages(aGad->GadgetRender, fd, ind);
        }
        else if (aGad->GadgetType == PROPGADGET) {   /* an autoknob? RRL */
            pi = (struct PropInfo *)aGad->SpecialInfo;
            if ((pi->Flags & AUTOKNOB) == AUTOKNOB)
            putImages(aGad->GadgetRender, fd, -1);
        }
        else {                                           /* Border(s) */
            /* write Border structures (IN ORDER) */
            putBorders(aGad->GadgetRender, fd);
        }
     }
 
    /* Okay, what about SelectRender structures? */
    if (aGad->SelectRender != NULL)                     /* Yup. */
        if (aGad->Flags & GADGHIMAGE)                   /* Image, Border */
            if (aGad->Flags & GADGIMAGE) {                /* Image(s) */
 
                putImages(aGad->SelectRender, fd, ind);
            }
            else {                                        /* Border(s) */
                putBorders(aGad->SelectRender, fd);
            }
 
    /* Finally, do we have SpecialInfo, too? */
    if (aGad->SpecialInfo != NULL) {
        if (aGad->GadgetType == PROPGADGET) {
            putPropInfo(aGad->SpecialInfo, fd);
        }
        else if (aGad->GadgetType == STRGADGET)
            putStringInfo(aGad->SpecialInfo, fd);
        /* else BOOLGADGET, so ignore. */
    }
 
    /* Any IntuiText out there? */
    if (aGad->GadgetText != NULL)           /* The writing's on the wall. */
        putIText(aGad->GadgetText, fd);     /* shove text in file, too. */
}
 
struct Gadget *grabGad(fd, ind)  /* get a gadget from a file */
long  fd;
int  ind;
{
    struct Gadget   *aGad;
 
    aGad = (struct Gadget *)
        AllocRemember(rememberBase, (long)sizeof(struct Gadget), CLRMEM);
 
    /* First we read the structure. */
    Read(fd, aGad, (long)sizeof(struct Gadget));
 
    /* Let's just NULL out the NextGadget field for good measure. */
    aGad->NextGadget = NULL;
 
    /* Now, do we have GadgetRender structures to read in? */
    if (aGad->GadgetRender != NULL) {                    /* Yes, we do! */
        if (aGad->Flags & GADGIMAGE) {                   /* Image(s) */
            /* read Image structures (IN ORDER) */
            aGad->GadgetRender = (APTR) getImages(fd, ind);
        }
        else if (aGad->GadgetType == PROPGADGET) {   /* an autoknob? RRL */
             aGad->GadgetRender = (APTR)getImages(fd, -1);
        }
        else {                                           /* Border(s) */
            /* read Border structures (IN ORDER) */
            aGad->GadgetRender = (APTR) getBorders(fd);
        }
     }
    /* Okay, what about SelectRender structures? */
    if (aGad->SelectRender != NULL)                     /* Yup. */
        if (aGad->Flags & GADGHIMAGE)                   /* Image, Border */
            if (aGad->Flags & GADGIMAGE)                /* Image(s) */
                aGad->SelectRender = (APTR) getImages(fd, ind);
            else                                        /* Border(s) */
                aGad->SelectRender = (APTR) getBorders(fd);
 
    /* Finally, do we have SpecialInfo, too? */
    if (aGad->SpecialInfo != NULL) {
        if (aGad->GadgetType == PROPGADGET)
            aGad->SpecialInfo = (APTR) getPropInfo(fd);
        else if (aGad->GadgetType == STRGADGET)
            aGad->SpecialInfo = (APTR) getStringInfo(fd);
        /* else BOOLGADGET, so ignore. */
    }
 
    /* Any IntuiText out there? */
    if (aGad->GadgetText != NULL)           /* The writing's on the wall. */
        aGad->GadgetText = getIText(fd);    /* get it */
 
    return(aGad);
}