test HAVE_JPEGLIB_H before including the jpeglib header
[swftools.git] / lib / rfxswf.c
1 /* rfxswf.c\r
2 \r
3    Library for creating and reading SWF files or parts of it.\r
4    There's a module directory which provides some extended functionality.\r
5    Most modules are included at the bottom of this file.\r
6 \r
7    Part of the swftools package.\r
8 \r
9    Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
10  \r
11    This file is distributed under the GPL, see file COPYING for details \r
12 \r
13 */\r
14 \r
15 #include "rfxswf.h"\r
16 \r
17 #ifdef HAVE_JPEGLIB_H\r
18 #include <jpeglib.h>\r
19 #define _JPEGLIB_INCLUDED_\r
20 #endif\r
21 \r
22 // Win32 support may be broken since it was only tested in an older version for Watcom C\r
23 #ifdef __NT__\r
24 #  include <io.h>\r
25 #  include <malloc.h>\r
26 #  include <string.h>\r
27 #  ifdef DEBUG_RFXSWF\r
28 #    include <stdio.h>\r
29 #  endif\r
30 #else\r
31 #endif\r
32 \r
33 // internal constants\r
34 \r
35 #define MALLOC_SIZE     128\r
36 #define INSERT_RFX_TAG\r
37 \r
38 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)\r
39 \r
40 // inline wrapper functions\r
41 \r
42 LPTAG NextTag(LPTAG t) { return t->next; }\r
43 LPTAG PrevTag(LPTAG t) { return t->prev; }\r
44 int   GetFrameNo(LPTAG t)  { return t->frame; }\r
45 U16   GetTagID(LPTAG t)    { return t->id; }\r
46 U32   GetDataSize(LPTAG t) { return t->len; }\r
47 U8*   GetDataSizePtr(LPTAG t) { return &(t->data[t->len]); }\r
48 U32   GetTagPos(LPTAG t)   { return t->pos; }\r
49 \r
50 // Basic Data Access Functions\r
51 \r
52 #define ResetBitmask(tag)   if (tag->bitmask)  { tag->pos++; tag->bitmask = 0; }\r
53 #define ResetBitcount(tag)  if (tag->bitcount) { tag->bitcount = 0; }\r
54 \r
55 // for future purpose: avoid high level lib functions to change tagpos/bitcount\r
56 \r
57 #define SaveTagPos(tag)\r
58 #define RestoreTagPos(tag)\r
59 \r
60 void SetTagPos(LPTAG t,U32 pos)\r
61 { ResetBitmask(t);\r
62   if (pos<=t->len) t->pos = pos;\r
63   #ifdef DEBUG_RFXSWF\r
64   else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);\r
65   #endif\r
66 }\r
67 \r
68 U8 GetU8(LPTAG t)\r
69 { ResetBitmask(t);\r
70   #ifdef DEBUG_RFXSWF\r
71     if (t->pos>=t->len) \r
72     { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);\r
73       return 0;\r
74     }\r
75   #endif\r
76   return t->data[t->pos++];\r
77 }\r
78 \r
79 U16 GetU16(LPTAG t)\r
80 { U16 res;\r
81   ResetBitmask(t);\r
82   #ifdef DEBUG_RFXSWF\r
83     if (t->pos>(t->len-2)) \r
84     { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);\r
85       return 0;\r
86     }\r
87   #endif\r
88   res = t->data[t->pos] | (t->data[t->pos+1]<<8);\r
89   t->pos+=2;\r
90   return res;\r
91 }\r
92 \r
93 U32 GetU32(LPTAG t)\r
94 { U32 res;\r
95   ResetBitmask(t);\r
96   #ifdef DEBUG_RFXSWF\r
97     if (t->pos>(t->len-4)) \r
98     { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);\r
99       return 0;\r
100     }\r
101   #endif\r
102   res = t->data[t->pos]        | (t->data[t->pos+1]<<8) | \r
103        (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);\r
104   t->pos+=4;\r
105   return res;\r
106 }\r
107 \r
108 int GetBlock(LPTAG t,U8 * b,int l)\r
109 // returns number of bytes written (<=l)\r
110 // b = NULL -> skip data\r
111 { ResetBitmask(t);\r
112   if ((t->len-t->pos)<l) l=t->len-t->pos;\r
113   if (b && l) memcpy(b,&t->data[t->pos],l);\r
114   t->pos+=l;\r
115   return l;\r
116 }\r
117 \r
118 int SetBlock(LPTAG t,U8 * b,int l)\r
119 // Appends Block to the end of Tagdata, returns size\r
120 { U32 newlen = t->len + l;\r
121   ResetBitcount(t);\r
122   if (newlen>t->memsize)\r
123   { U32  newmem  = MEMSIZE(newlen);  \r
124     U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));\r
125     if (!newdata)\r
126     {\r
127       #ifdef DEBUG_RFXSWF\r
128         fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
129       #endif\r
130       return 0;\r
131     }\r
132     t->memsize = newmem;\r
133     t->data    = newdata;\r
134   }\r
135   if (b) memcpy(&t->data[t->len],b,l);\r
136   else memset(&t->data[t->len],0x00,l);\r
137   t->len+=l;\r
138   return l;\r
139 }\r
140 \r
141 int SetU8(LPTAG t,U8 v)\r
142 { ResetBitcount(t);\r
143   if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;\r
144   t->data[t->len++] = v;\r
145   return 0;\r
146 }\r
147 \r
148 int SetU16(LPTAG t,U16 v)\r
149 { U8 a[2];\r
150   a[0] = v&0xff;\r
151   a[1] = v>>8;\r
152   \r
153   ResetBitcount(t);\r
154   if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;\r
155   t->data[t->len++] = a[0];\r
156   t->data[t->len++] = a[1];\r
157   return 0;\r
158 }\r
159 \r
160 int SetU32(LPTAG t,U32 v)\r
161 { U8 a[4];\r
162   a[0] = v&0xff;        // to ensure correct handling of non-intel byteorder\r
163   a[1] = (v>>8)&0xff;\r
164   a[2] = (v>>16)&0xff;\r
165   a[3] = (v>>24)&0xff;\r
166   \r
167   ResetBitcount(t);\r
168   if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1;\r
169   t->data[t->len++] = a[0];\r
170   t->data[t->len++] = a[1];\r
171   t->data[t->len++] = a[2];\r
172   t->data[t->len++] = a[3];\r
173   return 0;\r
174 }\r
175 \r
176 U32 GetBits(LPTAG t,int nbits)\r
177 { U32 res = 0;\r
178   if (!nbits) return 0;\r
179   if (!t->bitmask) t->bitmask = 0x80;\r
180   while (nbits)\r
181   { res<<=1;\r
182     if (t->data[t->pos]&t->bitmask) res|=1;\r
183     t->bitmask>>=1;\r
184     nbits--;\r
185     if (!t->bitmask)\r
186     { if (nbits) t->bitmask = 0x80;\r
187       #ifdef DEBUG_RFXSWF\r
188       if (t->pos>=t->len) \r
189       { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);\r
190         return res;\r
191       }\r
192       #endif\r
193       t->pos++;\r
194     }\r
195   }\r
196   return res;\r
197 }\r
198 \r
199 S32 GetSBits(LPTAG t,int nbits)\r
200 { U32 res = GetBits(t,nbits);\r
201   if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);  \r
202   return (S32)res;\r
203 }\r
204 \r
205 int SetBits(LPTAG t,U32 v,int nbits)\r
206 { U32 bm = 1<<(nbits-1);\r
207 \r
208   while (nbits)\r
209   { if (!t->bitcount)\r
210     { if (FAILED(SetU8(t,0))) return -1;\r
211       t->bitcount = 0x80;\r
212     }\r
213     if (v&bm) t->data[t->len-1] |= t->bitcount;\r
214     bm>>=1;\r
215     t->bitcount>>=1;\r
216     nbits--;\r
217   }\r
218   return 0;\r
219 }\r
220 \r
221 // Advanced Data Access Functions\r
222 \r
223 int SetRGB(LPTAG t,LPRGBA col)\r
224 { if (!t) return -1;\r
225   if (col)\r
226   { SetU8(t,col->r);\r
227     SetU8(t,col->g);\r
228     SetU8(t,col->b);\r
229   } else SetBlock(t,NULL,3);\r
230   return 0;\r
231 }\r
232 \r
233 int SetRGBA(LPTAG t,LPRGBA col)\r
234 { if (!t) return -1;\r
235   if (col)\r
236   { SetU8(t,col->r);\r
237     SetU8(t,col->g);\r
238     SetU8(t,col->b);\r
239     SetU8(t,col->a);\r
240   } else SetBlock(t,NULL,4);\r
241   return 0;\r
242 }\r
243 \r
244 int CountBits(U32 v,int nbits)\r
245 { int n = 33;\r
246   U32 m = 0x80000000;\r
247   if (!v) n = 0; else\r
248   if (v&m)\r
249   { while (v&m)\r
250     { n--;\r
251       m>>=1;\r
252       if (!m) break;\r
253     } \r
254   }\r
255   else\r
256   { while (!(v&m))\r
257     { n--;\r
258       m>>=1;\r
259       if (!m) break;\r
260     } \r
261   }\r
262   return (n>nbits)?n:nbits;\r
263 }\r
264 \r
265 int GetRect(LPTAG t,LPSRECT r)\r
266 { int nbits;\r
267   SRECT dummy;\r
268   if (!r) r = &dummy;\r
269   nbits = (int) GetBits(t,5);\r
270   r->xmin = GetSBits(t,nbits);\r
271   r->xmax = GetSBits(t,nbits);\r
272   r->ymin = GetSBits(t,nbits);\r
273   r->ymax = GetSBits(t,nbits);\r
274   return 0;\r
275 }\r
276 \r
277 int SetRect(LPTAG t,LPSRECT r)\r
278 { int nbits;\r
279     \r
280   nbits = CountBits(r->xmin,0);\r
281   nbits = CountBits(r->xmax,nbits);\r
282   nbits = CountBits(r->ymin,nbits);\r
283   nbits = CountBits(r->ymax,nbits);\r
284 \r
285   SetBits(t,nbits,5);\r
286   SetBits(t,r->xmin,nbits);\r
287   SetBits(t,r->xmax,nbits);\r
288   SetBits(t,r->ymin,nbits);\r
289   SetBits(t,r->ymax,nbits);\r
290 \r
291   return 0;\r
292 }\r
293 \r
294 int GetMatrix(LPTAG t,LPMATRIX m)\r
295 { MATRIX dummy;\r
296   int nbits;\r
297     \r
298   if (!m) m = &dummy;\r
299   \r
300   if (!t)\r
301   { m->sx = m->sy = 0x10000;\r
302     m->r0 = m->r1 = 0;\r
303     m->tx = m->ty = 0;\r
304     return -1;\r
305   }\r
306 \r
307   ResetBitmask(t);\r
308   \r
309   if (GetBits(t,1))\r
310   { nbits = GetBits(t,5);\r
311     m->sx = GetSBits(t,nbits);\r
312     m->sy = GetSBits(t,nbits);\r
313   }\r
314   else m->sx = m->sy = 0x10000;\r
315   \r
316   if (GetBits(t,1))\r
317   { nbits = GetBits(t,5);\r
318     m->r0 = GetSBits(t,nbits);\r
319     m->r1 = GetSBits(t,nbits);\r
320   }\r
321   else m->r0 = m->r1 = 0x0;\r
322 \r
323   nbits = GetBits(t,5);\r
324   m->tx = GetSBits(t,nbits);\r
325   m->ty = GetSBits(t,nbits);\r
326   \r
327   return 0;\r
328 }\r
329 \r
330 int SetMatrix(LPTAG t,LPMATRIX m)\r
331 { int nbits;\r
332   MATRIX ma;\r
333 \r
334   if (!m)\r
335   { m = &ma;\r
336     ma.sx = ma.sy = 0x10000;\r
337     ma.r0 = ma.r1 = 0;\r
338     ma.tx = ma.ty = 0;\r
339   }\r
340 \r
341   ResetBitcount(t);\r
342 \r
343   if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);\r
344   else\r
345   { SetBits(t,1,1);\r
346     nbits = CountBits(m->sx,0);\r
347     nbits = CountBits(m->sy,nbits);\r
348     SetBits(t,nbits,5);\r
349     SetBits(t,m->sx,nbits);\r
350     SetBits(t,m->sy,nbits);\r
351   }\r
352 \r
353   if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);\r
354   else\r
355   { SetBits(t,1,1);\r
356     nbits = CountBits(m->r0,0);\r
357     nbits = CountBits(m->r1,nbits);\r
358     SetBits(t,nbits,5);\r
359     SetBits(t,m->r0,nbits);\r
360     SetBits(t,m->r1,nbits);\r
361   }\r
362 \r
363   nbits = CountBits(m->tx,0);\r
364   nbits = CountBits(m->ty,nbits);\r
365   SetBits(t,nbits,5);\r
366   SetBits(t,m->tx,nbits);\r
367   SetBits(t,m->ty,nbits);\r
368 \r
369   return 0;\r
370 }\r
371 \r
372 int GetCXForm(LPTAG t,LPCXFORM cx,U8 alpha) //FIXME: alpha should be type bool\r
373 { CXFORM cxf;\r
374   int hasadd;\r
375   int hasmul;\r
376   int nbits;\r
377     \r
378   if (!cx) cx = &cxf;\r
379   \r
380   cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
381   cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
382 \r
383   if (!t) return 0;\r
384   \r
385   ResetBitmask(t);\r
386   hasadd = GetBits(t,1);\r
387   hasmul = GetBits(t,1);\r
388   nbits  = GetBits(t,4);\r
389 \r
390   if (hasmul)\r
391   { cx->r0 = (S16)GetSBits(t,nbits);\r
392     cx->g0 = (S16)GetSBits(t,nbits);\r
393     cx->b0 = (S16)GetSBits(t,nbits);\r
394     if (alpha)\r
395       cx->a0 = (S16)GetSBits(t,nbits);\r
396   }\r
397 \r
398   if (hasadd)\r
399   { cx->r1 = (S16)GetSBits(t,nbits);\r
400     cx->g1 = (S16)GetSBits(t,nbits);\r
401     cx->b1 = (S16)GetSBits(t,nbits);\r
402     if (alpha)\r
403       cx->a1 = (S16)GetSBits(t,nbits);\r
404   }\r
405   \r
406   return 0;\r
407 }\r
408 \r
409 int SetCXForm(LPTAG t,LPCXFORM cx,U8 alpha)\r
410 { CXFORM cxf;\r
411   int hasadd;\r
412   int hasmul;\r
413   int nbits;\r
414     \r
415   if (!cx)\r
416   { cx = &cxf;\r
417     cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
418     cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
419   }\r
420 \r
421   if (!alpha)\r
422   { cx->a0 = 256;\r
423     cx->a1 = 0;\r
424   }\r
425 \r
426   nbits = 0;\r
427 \r
428   hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);\r
429   hasadd = cx->a1|cx->r1|cx->g1|cx->b1;\r
430 \r
431   if (hasmul)\r
432   { if (alpha) nbits = CountBits((S32)cx->a0,nbits);\r
433     nbits = CountBits((S32)cx->r0,nbits);\r
434     nbits = CountBits((S32)cx->g0,nbits);\r
435     nbits = CountBits((S32)cx->b0,nbits);\r
436   }\r
437 \r
438   if (hasadd)\r
439   { if (alpha) nbits = CountBits((S32)cx->a1,nbits);\r
440     nbits = CountBits((S32)cx->r1,nbits);\r
441     nbits = CountBits((S32)cx->g1,nbits);\r
442     nbits = CountBits((S32)cx->b1,nbits);\r
443   }\r
444   \r
445   ResetBitcount(t);\r
446   SetBits(t,hasadd?1:0,1);\r
447   SetBits(t,hasmul?1:0,1);\r
448   SetBits(t,nbits,4);\r
449 \r
450   if (hasmul)\r
451   { SetBits(t,cx->r0,nbits);\r
452     SetBits(t,cx->g0,nbits);\r
453     SetBits(t,cx->b0,nbits);\r
454     if (alpha) SetBits(t,cx->a0,nbits);\r
455   }\r
456 \r
457   if (hasadd)\r
458   { SetBits(t,cx->r1,nbits);\r
459     SetBits(t,cx->g1,nbits);\r
460     SetBits(t,cx->b1,nbits);\r
461     if (alpha) SetBits(t,cx->a1,nbits);\r
462   }\r
463   \r
464   return 0;\r
465 }\r
466 \r
467 int GetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
468 int SetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
469 \r
470 // Tag List Manipulating Functions\r
471 \r
472 int RFXSWF_UpdateFrame(LPTAG t,S8 delta)\r
473 // returns number of frames\r
474 { int res = -1;\r
475   while (t)\r
476   { t->frame+=delta;\r
477     res = t->frame;\r
478     t = t->next;\r
479   }\r
480   return res;\r
481 }\r
482 \r
483 #define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)\r
484 \r
485 LPTAG InsertTag(LPTAG after,U16 id)     // updates frames, if nescessary\r
486 { LPTAG t;\r
487 \r
488   t = (LPTAG)malloc(sizeof(TAG));\r
489   if (t)\r
490   { memset(t,0x00,sizeof(TAG));\r
491     t->id = id;\r
492     t->bitcount = 0x80;\r
493     \r
494     if (after)\r
495     { t->frame = after->frame;\r
496       t->prev  = after;\r
497       t->next  = after->next;\r
498       after->next = t;\r
499       if (t->next) t->next->prev = t;\r
500       \r
501       if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1);\r
502     }\r
503   }\r
504   return t;\r
505 }\r
506 \r
507 int DeleteTag(LPTAG t)\r
508 { if (!t) return -1;\r
509 \r
510   if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1);\r
511     \r
512   if (t->prev) t->prev->next = t->next;\r
513   if (t->next) t->next->prev = t->prev;\r
514 \r
515   if (t->data) free(t->data);\r
516   free(t);\r
517   return 0;\r
518 }\r
519 \r
520 LPTAG RFXSWF_ReadTag(int handle,LPTAG prev)\r
521 { LPTAG t;\r
522   U16 raw;\r
523   U32 len;\r
524   int id;\r
525 \r
526   if (read(handle,&raw,2)!=2) return NULL;\r
527 \r
528   len = raw&0x3f;\r
529   id  = raw>>6;\r
530 \r
531   if (len==0x3f)\r
532   { if (read(handle,&len,4)!=4) return NULL;\r
533   }\r
534 \r
535   if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);\r
536   // Sprite handling fix: Flaten sprite tree\r
537 \r
538   t = (LPTAG)malloc(sizeof(TAG));\r
539   \r
540   if (!t)\r
541   {\r
542     #ifdef DEBUG_RFXSWF\r
543       fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
544     #endif\r
545     return NULL;\r
546   }\r
547 \r
548   memset(t,0x00,sizeof(TAG));\r
549   \r
550   t->len = len;\r
551   t->id  = id;\r
552 \r
553   if (t->len)\r
554   { t->data = (U8*)malloc(t->len);\r
555     if (!t->data)\r
556     {\r
557       #ifdef DEBUG_RFXSWF\r
558         fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
559       #endif\r
560       return NULL;\r
561     }\r
562     t->memsize = t->len;\r
563     if (read(handle,t->data,t->len)!=t->len) return NULL;\r
564   }\r
565 \r
566   if (prev)\r
567   { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);\r
568     t->prev  = prev;\r
569     prev->next = t;\r
570   }\r
571 \r
572   return t;\r
573 }\r
574 \r
575 int DefineSprite_GetRealSize(LPTAG t);\r
576 \r
577 int RFXSWF_WriteTag(int handle,LPTAG t)\r
578 // returns tag length in bytes (incl. Header), -1 = Error\r
579 // handle = -1 -> no output\r
580 { U16 raw[3];\r
581   U32 len;\r
582   int short_tag;\r
583 \r
584   if (!t) return -1;\r
585 \r
586   len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len;\r
587 \r
588   short_tag = len<0x3f;\r
589 \r
590   if (handle>=0)\r
591   { if (short_tag)\r
592     { raw[0] = len|((t->id&0x3ff)<<6);\r
593       if (write(handle,raw,2)!=2)\r
594       {\r
595         #ifdef DEBUG_RFXSWF\r
596           fprintf(stderr,"WriteTag() failed: Short Header.\n");\r
597         #endif\r
598         return -1;\r
599       }\r
600     }\r
601     else\r
602     { raw[0] = (t->id<<6)|0x3f;\r
603       raw[1] = (U16)(len&0xffff);\r
604       raw[2] = (U16)(len>>16);\r
605       if (write(handle,raw,6)!=6)\r
606       {\r
607         #ifdef DEBUG_RFXSWF\r
608           fprintf(stderr,"WriteTag() failed: Long Header.\n");\r
609         #endif\r
610         return -1;\r
611       }\r
612     }\r
613     \r
614     if (t->data)\r
615     { if (write(handle,t->data,t->len)!=t->len)\r
616       {\r
617         #ifdef DEBUG_RFXSWF\r
618           fprintf(stderr,"WriteTag() failed: Data.\n");\r
619         #endif\r
620         return -1;\r
621       }\r
622     }\r
623     #ifdef DEBUG_RFXSWF\r
624       else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);\r
625     #endif\r
626   }\r
627 \r
628   return t->len+(short_tag?2:6);\r
629 }\r
630 \r
631 int DefineSprite_GetRealSize(LPTAG t)\r
632 // Sprite Handling: Helper function to pack DefineSprite-Tag\r
633 { U32 len = t->len;\r
634   do\r
635   { t = NextTag(t);\r
636     if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);\r
637     else t = NULL;\r
638   } while (t&&(t->id!=ST_END));\r
639   return len;\r
640 }\r
641 \r
642 #define ReadTag(a,b)  RFXSWF_ReadTag(a,b)\r
643 #define WriteTag(a,b) RFXSWF_WriteTag(a,b)\r
644 \r
645 // Movie Functions\r
646 \r
647 int ReadSWF(int handle,LPSWF swf)       // Reads SWF to memory (malloc'ed), returns length or <0 if fails\r
648 {     \r
649   if (!swf) return -1;\r
650   memset(swf,0x00,sizeof(SWF));\r
651 \r
652   { char b[32];                         // Header lesen\r
653     TAG t1;\r
654     LPTAG t;\r
655     \r
656     memset(&t1,0x00,sizeof(TAG));\r
657     \r
658     if ((t1.len=read(handle,b,32))<21) return -1;\r
659     t1.data = (U8*)b;\r
660 \r
661     if (GetU8(&t1)!=(U8)'F') return -1;\r
662     if (GetU8(&t1)!=(U8)'W') return -1;\r
663     if (GetU8(&t1)!=(U8)'S') return -1;\r
664 \r
665     swf->FileVersion = GetU8(&t1);\r
666     swf->FileSize    = GetU32(&t1);\r
667     GetRect(&t1,&swf->MovieSize);\r
668     swf->FrameRate   = GetU16(&t1);\r
669     swf->FrameCount  = GetU16(&t1);\r
670 \r
671     GetU8(&t1);\r
672     lseek(handle,GetTagPos(&t1)-1,SEEK_SET);\r
673   \r
674                                         // Tags lesen und verketten\r
675     t = &t1;\r
676     while (t) t = ReadTag(handle,t);\r
677     swf->FirstTag = t1.next;\r
678     t1.next->prev = NULL;\r
679   }\r
680   \r
681   return 0;\r
682 }\r
683 int  WriteSWF(int handle,LPSWF swf)     // Writes SWF to file, returns length or <0 if fails\r
684 { U32 len;\r
685   LPTAG t;\r
686     \r
687   if (!swf) return -1;\r
688 \r
689   // Insert REFLEX Tag\r
690 \r
691 #ifdef INSERT_RFX_TAG\r
692 \r
693   if (NextTag(swf->FirstTag))\r
694     if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)\r
695       SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);\r
696 \r
697 #endif // INSERT_RFX_TAG\r
698 \r
699   // Count Frames + File Size\r
700 \r
701   len = 0;\r
702   t = swf->FirstTag;\r
703   swf->FrameCount = 0;\r
704 \r
705   while(t)\r
706   { len += WriteTag(-1,t);\r
707     if (t->id==ST_SHOWFRAME) swf->FrameCount++;\r
708     t = NextTag(t);\r
709   }\r
710   \r
711   { TAG t1;\r
712     char b[64];\r
713     U32 l;\r
714 \r
715     memset(&t1,0x00,sizeof(TAG));\r
716     t1.data    = (U8*)b;\r
717     t1.memsize = 64;\r
718     \r
719     SetU8(&t1,'F');      \r
720     SetU8(&t1,'W');      \r
721     SetU8(&t1,'S');\r
722     SetU8(&t1,swf->FileVersion);\r
723     \r
724     SetU32(&t1,0);                      // Keep space for filesize\r
725     SetRect(&t1,&swf->MovieSize);\r
726     SetU16(&t1,swf->FrameRate);\r
727     SetU16(&t1,swf->FrameCount);\r
728 \r
729     l = GetDataSize(&t1);\r
730     swf->FileSize = l+len;\r
731     t1.len = 4;                         // bad & ugly trick !\r
732     SetU32(&t1,swf->FileSize);\r
733 \r
734     if (handle>=0)\r
735     { \r
736       int ret = write(handle,b,l);\r
737       if (ret!=l)\r
738       {\r
739         #ifdef DEBUG_RFXSWF\r
740           printf("ret:%d (fd:%d)\n",ret, handle);\r
741           perror("write:");\r
742           fprintf(stderr,"WriteSWF() failed: Header.\n");\r
743         #endif\r
744         return -1;\r
745       }\r
746 \r
747       t = swf->FirstTag;\r
748       while (t)\r
749       { if (WriteTag(handle,t)<0) return -1;\r
750         t = NextTag(t);\r
751       }\r
752     }\r
753   }\r
754   return (int)swf->FileSize;\r
755 }\r
756 \r
757 int WriteCGI(LPSWF swf)\r
758 { int len;\r
759   char s[1024];\r
760     \r
761   len = WriteSWF(-1,swf);\r
762 \r
763   if (len<0) return -1;\r
764 \r
765   sprintf(s,"Content-type: application/x-shockwave-flash\n"\r
766             "Accept-Ranges: bytes\n"\r
767             "Content-Length: %lu\n"\r
768             "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"\r
769             "\n",len);\r
770             \r
771   write(fileno(stdout),s,strlen(s));\r
772   return WriteSWF(fileno(stdout),swf);\r
773 }\r
774 \r
775 void FreeTags(LPSWF swf)                 // Frees all malloc'ed memory for tags\r
776 { LPTAG t = swf->FirstTag;\r
777 \r
778   while (t)\r
779   { LPTAG tnew = t->next;\r
780     if (t->data) free(t->data);\r
781     free(t);\r
782     t = tnew;\r
783   }\r
784 }\r
785 \r
786 // include advanced functions\r
787 \r
788 #ifdef __NT__\r
789 \r
790 #include "modules\swfdump.c"\r
791 #include "modules\swfshape.c"\r
792 #include "modules\swftext.c"\r
793 #include "modules\swfobject.c"\r
794 #include "modules\swfbutton.c"\r
795 #include "modules\swftools.c"\r
796 #include "modules\swfcgi.c"\r
797 #include "modules\swfbits.c"\r
798 \r
799 #else\r
800 \r
801 #include "modules/swfdump.c"\r
802 #include "modules/swfshape.c"\r
803 #include "modules/swftext.c"\r
804 #include "modules/swfobject.c"\r
805 #include "modules/swfbutton.c"\r
806 #include "modules/swftools.c"\r
807 #include "modules/swfcgi.c"\r
808 #include "modules/swfbits.c"\r
809 \r
810 #endif\r
811 \r
812 \r