3 /* Standard module for reading/writing simple IFF files */
7 #include <exec/types.h>
9 #include <dos/dosextens.h>
10 #include <libraries/iffparse.h>
11 #include <proto/exec.h>
12 #include <proto/dos.h>
13 #include <proto/iffparse.h>
14 #include <prefs/prefhdr.h>
15 #include "prefs/popupmenu.h"
17 /* This function opens an IFF file and prepares it for reading or writing. */
18 /* If the file is opened for writing, it is initialized as a FORM of the */
19 /* specified 'type'. If an error occurs, it is returned in 'error'. */
21 struct IFFHandle
*OpenIFFFile(STRPTR name
, LONG type
, ULONG mode
, LONG
*error
, struct Library
*IFFParseBase
)
23 struct IFFHandle
*iffh
;
25 LONG dosmode
= (mode
== IFFF_WRITE
)? MODE_NEWFILE
: MODE_OLDFILE
;
29 if ((file
= Open(name
,dosmode
)))
31 *error
= IFFERR_NOMEM
;
33 if ((iffh
= AllocIFF()))
35 iffh
->iff_Stream
= (ULONG
)file
;
38 *error
= OpenIFF(iffh
,mode
);
42 if (mode
== IFFF_WRITE
)
44 *error
= PushChunk(iffh
,type
,ID_FORM
,IFFSIZE_UNKNOWN
);
45 if (*error
) PopChunk(iffh
);
48 if (*error
== 0L) return (iffh
);
61 /* This function closes a previously opened IFF file. */
63 void CloseIFFFile(struct IFFHandle
*iffh
, struct Library
*IFFParseBase
)
67 if (iffh
->iff_Flags
& IFFF_WRITE
)
73 Close((BPTR
)(iffh
->iff_Stream
));
78 /* This function resets the reading/writing position of an IFF file */
79 /* so that the next I/O operation restarts from the beginning. */
81 LONG
ResetIFFFile(struct IFFHandle
*iffh
, struct Library
*IFFParseBase
)
89 file
= (BPTR
)(iffh
->iff_Stream
);
90 flags
= iffh
->iff_Flags
;
92 Seek(file
,0,OFFSET_BEGINNING
);
93 error
= OpenIFF(iffh
,flags
& IFFF_RWBITS
);
99 /* This function can be used to read a chunk of the specified ID, or just */
100 /* the next chunk if 'id' is zero. You can read a series of chunks having */
101 /* the same ID just by calling ReadChunk() multiple times, as it remembers */
102 /* its current position. By doing this with an 'id' of zero, you can even */
103 /* read all the chunks in the IFF file. If you need to read chunks having */
104 /* different IDs, you should call ResetIFFFile() before each new search, */
105 /* to make sure the scan always starts from the beginning. If the wanted */
106 /* chunk is found, no more than 'size' bytes are copied from it to the */
107 /* buffer pointed to by 'data'; if either 'data' or 'size' is zero, no */
108 /* copy occurs. You can always retrieve the chunk bytes from the returned */
109 /* ContextNode structure; a NULL return value means that no more chunks of */
110 /* the specified ID were found (or the end of file was reached). */
112 struct ContextNode
*ReadChunk(struct IFFHandle
*iffh
, LONG id
, APTR data
, ULONG size
, struct Library
*IFFParseBase
)
115 struct ContextNode
*cn
= NULL
;
117 if (iffh
&& ((iffh
->iff_Flags
& IFFF_RWBITS
) == IFFF_READ
))
121 error
= ParseIFF(iffh
,IFFPARSE_RAWSTEP
);
123 if (error
== IFFERR_EOC
)
133 cn
= CurrentChunk(iffh
);
135 if (!id
|| (cn
->cn_ID
== id
))
137 if (data
&& size
&& (cn
->cn_ID
!= ID_FORM
) && (cn
->cn_ID
!= ID_PROP
))
139 error
= ReadChunkBytes(iffh
,data
,size
);
142 if (error
< 0L) cn
= NULL
;
155 void PM_LoadPrefsFile(STRPTR filename
, ULONG flags
, struct PopupMenuPrefs
*prefs
, struct PopupMenuPrefs
*defprefs
)
157 struct IFFHandle
*iffh
= NULL
;
158 struct ContextNode
*cn
;
159 struct Library
*IFFParseBase
;
164 if((IFFParseBase
= OpenLibrary("iffparse.library", 0))) {
165 if ((iffh
= OpenIFFFile(filename
,ID_PREF
,IFFF_READ
,&error
, IFFParseBase
))) {
166 if ((cn
= ReadChunk(iffh
,ID_PMNU
,prefs
,sizeof(struct PopupMenuPrefs
),IFFParseBase
))) {
172 if (read
!= sizeof(struct PopupMenuPrefs
)) {
176 CloseIFFFile(iffh
, IFFParseBase
);
179 CloseLibrary(IFFParseBase
);
183 if (!iffh
|| (error
!= 0L)) {
184 CopyMem(defprefs
, prefs
, sizeof(struct PopupMenuPrefs
));