1 {
2     This file is part of the Free Pascal run time library.
3     Copyright (c) 2016 by Free Pascal development team
4 
5     iffparse.library functions for Amiga OS 4.x
6 
7     See the file COPYING.FPC, included in this distribution,
8     for details about the copyright.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 
14  **********************************************************************}
15 {$PACKRECORDS 2}
16 
17 unit iffparse;
18 
19 interface
20 
21 uses
22   exec, clipboard, utility;
23 
24 
25 // Struct associated with an active IFF stream. "iff_Stream" is a value used by the client's read/write/seek functions -
26 // it will not be accessed by the library itself and can have any value (could even be a pointer or a BPTR).
27 // This structure can only be allocated by iffparse.library
28 type
29   PIFFHandle = ^TIFFHandle;
30   TIFFHandle = record
31     iff_Stream: LongWord;
32     iff_Flags: LongWord;
33     iff_Depth: LongInt;   //  Depth of context stack.
34   end;
35 
36 // Bit masks for "iff_Flags" field.
37 const
38   IFFF_READ     = 0;                      // read mode - default
39   IFFF_WRITE    = 1;                      // write mode
40   IFFF_RWBITS   = IFFF_READ + IFFF_WRITE; // read/write bits
41   IFFF_FSEEK    = 1 shl 1;                // forward seek only
42   IFFF_RSEEK    = 1 shl 2;                // random seek
43   IFFF_RESERVED = $FFFF0000;              // Don't touch these bits.
44 
45 // When the library calls your stream handler, you'll be passed a pointer to this structure as the "message packet".
46 type
47   PIFFStreamCmd = ^TIFFStreamCmd;
48   TIFFStreamCmd = record
49     sc_Command: LongInt;  //  Operation to be performed (IFFCMD_)
50     sc_Buf: APTR;         //  Pointer to data buffer
51     sc_NBytes: LongInt;   //  Number of bytes to be affected
52   end;
53 
54 // A node associated with a context on the iff_Stack.  Each node represents a chunk, the stack representing the current nesting of chunks in the
55 // open IFF file.  Each context node has associated local context items in the (private) LocalItems list.
56 // The ID, type, size and scan values describe the chunk associated with this node.
57 // This structure can only be allocated by iffparse.library
58   PContextNode = ^TContextNode;
59   TContextNode = record
60     cn_Node: TMinNode;
61     cn_ID: LongInt;
62     cn_Type: LongInt;
63     cn_Size: LongInt; //  Size of this chunk
64     cn_Scan: LongInt; //  # of bytes read/written so far
65   end;
66 
67 // Local context items live in the ContextNode's.  Each class is identified by its lci_Ident code and has a (private) purge vector for when the
68 // parent context node is popped. This structure can only be allocated by iffparse.library
69   PLocalContextItem = ^TLocalContextItem;
70   TLocalContextItem = record
71     lci_Node: TMinNode;
72     lci_ID: LongWord;
73     lci_Type: LongWord;
74     lci_Ident: LongWord;
75   end;
76 // StoredProperty: a local context item containing the data stored from a previously encountered property chunk.
77   PStoredProperty = ^TStoredProperty;
78   TStoredProperty = record
79     sp_Size: LongInt;
80     sp_Data: APTR;
81   end;
82 
83 // Collection Item: the actual node in the collection list at which client will look.
84 // The next pointers cross context boundaries so that the complete list is accessable.
85   PCollectionItem = ^TCollectionItem;
86   TCollectionItem = record
87     ci_Next: PCollectionItem;
88     ci_Size: LongInt;
89     ci_Data: APTR;
90   end;
91 // Structure returned by OpenClipboard().  You may do CMD_POSTs and such using this structure.
92 // However, once you call OpenIFF(), you may not do any more of your own I/O to the clipboard until you call CloseIFF().
93   PClipboardHandle = ^TClipBoardHandle;
94   TClipboardHandle = record
95     cbh_Req: TIOClipReq;
96     cbh_CBport: TMsgPort;
97     cbh_SatisfyPort: TMsgPort;
98   end;
99 
100 const
101 // IFF return codes.  Most functions return either zero for success or one of these codes.  The exceptions are the read/write functions which
102 // return positive values for number of bytes or records read or written, or a negative error code.
103 // Some of these codes are not errors per sae, but valid conditions such as EOF or EOC (End of Chunk).
104   IFFERR_EOF        = -1;  // Reached logical END of file
105   IFFERR_EOC        = -2;  // About to leave context
106   IFFERR_NOSCOPE    = -3;  // No valid scope for property
107   IFFERR_NOMEM      = -4;  // Internal memory alloc failed
108   IFFERR_READ       = -5;  // Stream read error
109   IFFERR_WRITE      = -6;  // Stream write error
110   IFFERR_SEEK       = -7;  // Stream seek error
111   IFFERR_MANGLED    = -8;  // Data in file is corrupt
112   IFFERR_SYNTAX     = -9;  // IFF syntax error
113   IFFERR_NOTIFF     = -10; //  Not an IFF file
114   IFFERR_NOHOOK     = -11; //  No call-back hook provided
115   IFF_RETURN2CLIENT = -12; //  Client handler normal return
116 
117 // Universal IFF identifiers.
118   ID_FORM = 1179603533; // 'FORM'
119   ID_LIST = 1279873876; // 'LIST'
120   ID_CAT  = 1128354848; // 'CAT '
121   ID_PROP = 1347571536; // 'PROP'
122   ID_NULL = 538976288;  // '    '
123   // Ident codes for universally recognized local context items.
124   IFFLCI_PROP         = 1886547824; // 'prop'
125   IFFLCI_COLLECTION   = 1668246636; // 'coll'
126   IFFLCI_ENTRYHANDLER = 1701734500; // 'enhd'
127   IFFLCI_EXITHANDLER  = 1702389860; // 'exhd'
128 
129 // Control modes for ParseIFF() function.
130   IFFPARSE_SCAN    = 0;
131   IFFPARSE_STEP    = 1;
132   IFFPARSE_RAWSTEP = 2;
133 
134 // Control modes for StoreLocalItem() function
IFFSLI_ROOTnull135   IFFSLI_ROOT = 1; //  Store in default context
136   IFFSLI_TOP  = 2; //  Store in current context
137   IFFSLI_PROP = 3; //  Store in topmost FORM OR LIST
138 
139 // Magic value for writing functions. If you pass this value in as a size to PushChunk() when writing a file, the parser will figure out the
140 // size of the chunk for you. If you know the size, is it better to provide as it makes things faster.
141   IFFSIZE_UNKNOWN =  -1;
142 
143 
144 // Possible call-back command values.
145   IFFCMD_INIT     = 0; // Prepare the stream for a session
146   IFFCMD_CLEANUP  = 1; // Terminate stream session
147   IFFCMD_READ     = 2; // Read bytes from stream
148   IFFCMD_WRITE    = 3; // Write bytes to stream
149   IFFCMD_SEEK     = 4; // Seek on stream
150   IFFCMD_ENTRY    = 5; // You just entered a new context
151   IFFCMD_EXIT     = 6; // You're about to leave a context
152   IFFCMD_PURGELCI = 7; // Purge a LocalContextItem
153 
154 const
155   IFFPARSENAME: PChar = 'iffparse.library';
156 
157 var
158   IFFParseBase: PLibrary = nil;
159   IIFFParse: PInterface = nil;
160 
161 function IFFParseObtain(): LongWord; syscall IIFFParse 60;
162 function IFFParseRelease(): LongWord; syscall IIFFParse 64;
163 procedure IFFParseExpunge(); syscall IIFFParse 68;
164 function IFFParseClone(): PInterface; syscall IIFFParse 72;
165 function AllocIFF: PIFFHandle; syscall IIFFParse 76;
166 function OpenIFF(Iff: PIFFHandle; RWMode: LongInt): LongInt; syscall IIFFParse 80;
167 function ParseIFF(Iff: PIFFHandle; Control: LongInt): LongInt; syscall IIFFParse 84;
168 procedure CloseIFF(Iff: PIFFHandle); syscall IIFFParse 88;
169 procedure FreeIFF(Iff: PIFFHandle); syscall IIFFParse 92;
170 function ReadChunkBytes(Iff: PIFFHandle; Buf: APTR; NumBytes: LongInt): LongInt; syscall IIFFParse 96;
171 function WriteChunkBytes(Iff: PIFFHandle; const Buf: APTR; NumBytes: LongInt): LongInt; syscall IIFFParse 100;
172 function ReadChunkRecords(Iff: PIFFHandle; Buf: APTR; BytesPerRecord: LongInt; NumRecords: LongInt): LongInt; syscall IIFFParse 104;
173 function WriteChunkRecords(Iff: PIFFHandle; const Buf: APTR; BytesPerRecord: LongInt; NumRecords: LongInt): LongInt; syscall IIFFParse 108;
174 function PushChunk(Iff: PIFFHandle; Type_, ID, Size: LongInt): LongInt; syscall IIFFParse 112;
175 function PopChunk(Iff: PIFFHandle): LongInt; syscall IIFFParse 116;
176 function EntryHandler(Iff: PIFFHandle; Type_, ID, Position: LongInt; Handler: PHook; Obj: APTR): LongInt; syscall IIFFParse 120;
177 function ExitHandler(Iff: PIFFHandle; Type_, ID, Position: LongInt; Handler: PHook; Obj: APTR): LongInt; syscall IIFFParse 124;
178 function PropChunk(Iff: PIFFHandle; Type_, ID: LongInt): LongInt; syscall IIFFParse 128;
179 function PropChunks(Iff: PIFFHandle; const PropArray: PLongInt; NumPairs: LongInt): LongInt; syscall IIFFParse 132;
180 function StopChunk(Iff: PIFFHandle; Type_, ID: LongInt): LongInt; syscall IIFFParse 136;
181 function StopChunks(Iff: PIFFHandle; const PropArray: PLongInt; NumPairs: LongInt): LongInt; syscall IIFFParse 140;
182 function CollectionChunk(Iff: PIFFHandle; Type_, ID: LongInt): LongInt; syscall IIFFParse 144;
183 function CollectionChunks(Iff: PIFFHandle; const PropArray: PLongInt; NumPairs: LongInt): LongInt; syscall IIFFParse 148;
184 function StopOnExit(Iff: PIFFHandle; Type_, ID: LongInt): LongInt; syscall IIFFParse 152;
185 function FindProp(const Iff: PIFFHandle; Type_, ID: LongInt): PStoredProperty; syscall IIFFParse 156;
186 function FindCollection(const Iff: PIFFHandle; Type_, ID: LongInt): PCollectionItem; syscall IIFFParse 160;
187 function FindPropContext(const Iff: PIFFHandle): PContextNode; syscall IIFFParse 164;
188 function CurrentChunk(const Iff: PIFFHandle): PContextNode; syscall IIFFParse 168;
189 function ParentChunk(const ContextNode: PContextNode): PContextNode; syscall IIFFParse 172;
190 function AllocLocalItem(Type_, ID, Ident, DataSize: LongInt): PLocalContextItem; syscall IIFFParse 176;
191 function LocalItemData(const LocalItem: PLocalContextItem): POINTER; syscall IIFFParse 180;
192 procedure SetLocalItemPurge(LocalItem: PLocalContextItem; const PurgeHook: PHook); syscall IIFFParse 184;
193 procedure FreeLocalItem(LocalItem: PLocalContextItem); syscall IIFFParse 188;
194 function FindLocalItem(const Iff: PIFFHandle; Type_, ID, Ident: LongInt): PLocalContextItem; syscall IIFFParse 192;
195 function StoreLocalItem(Iff: PIFFHandle; LocalItem: PLocalContextItem; Position: LongInt): LongInt; syscall IIFFParse 196;
196 procedure StoreItemInContext(Iff: PIFFHandle; LocalItem: PLocalContextItem; ContextNode: PContextNode); syscall IIFFParse 200;
197 procedure InitIFF(Iff: PIFFHandle; Flags: LongInt; const StreamHook: PHook); syscall IIFFParse 204;
198 procedure InitIFFasDOS(Iff: PIFFHandle); syscall IIFFParse 208;
199 procedure InitIFFasClip(Iff: PIFFHandle); syscall IIFFParse 212;
200 function OpenClipboard(UnitNumber: LongInt): PClipboardHandle; syscall IIFFParse 216;
201 procedure CloseClipboard(clipHandle: PClipboardHandle); syscall IIFFParse 220;
202 function GoodID(ID: LongInt): LongInt; syscall IIFFParse 224;
203 function GoodType(Type_: LongInt): LongInt; syscall IIFFParse 228;
204 function IDtoStr(ID: LongInt; Buf: STRPTR): STRPTR; syscall IIFFParse 232;
205 
206 function Make_ID(Str: string): LongWord;
207 
208 implementation
209 
210 function Make_ID(Str: string): LongWord;
211 begin
212   Make_ID := 0;
213   if Length(Str) >= 4 then
214     Make_ID := (LongWord(Ord(Str[1])) shl 24) or
215                (LongWord(Ord(Str[2])) shl 16) or
216                (LongWord(Ord(Str[3])) shl  8) or
217                (LongWord(Ord(Str[4])));
218 end;
219 
220 const
221     { Change LIBVERSION to proper values }
222     LIBVERSION : longword = 0;
223 
224 initialization
225   IFFParseBase := OpenLibrary(IFFPARSENAME,LIBVERSION);
226   if Assigned(IFFParseBase) then
227     IIFFParse := GetInterface(PLibrary(IFFParseBase), 'main', 1, nil);
228 finalization
229   if Assigned(IIFFParse) then
230     DropInterface(IIFFParse);
231   if Assigned(IFFParseBase) then
232     CloseLibrary(IFFParseBase);
233 end.
234 
235 
236 
237 
238 
239