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); }