handle filesystems where lowercase(file)==file more gracefully
[swftools.git] / lib / as3 / scripts.c
1 /* scripts.c
2
3    Some hardcoded abc scripts.
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008,2009 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23
24 #include <time.h>
25 #include "abc.h"
26 #include "../MD5.h"
27
28 void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events)
29 {
30     int num_frames = 0;
31     int has_buttons = 0;
32     TAG*tag=swf->firstTag;
33
34     void*md5 = init_md5();
35
36     while(tag) {
37         if(tag->id == ST_SHOWFRAME)
38             num_frames++;
39         if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2)
40             has_buttons = 1;
41         update_md5(md5, tag->data, tag->len);
42         tag = tag->next;
43     }
44     int t = time(0);
45     update_md5(md5, (unsigned char*)&t, sizeof(t));
46
47     unsigned char h[16];
48     unsigned char file_signature[33];
49     finish_md5(md5, h);
50     sprintf(file_signature, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
51             h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7],h[8],h[9],h[10],h[11],h[12],h[13],h[14],h[15]);
52
53     char scenename1[80], scenename2[80];
54     sprintf(scenename1, "rfx.MainTimeline_%s", file_signature);
55     sprintf(scenename2, "rfx::MainTimeline_%s", file_signature);
56
57     abc_file_t*file = abc_file_new();
58     abc_method_body_t*c = 0;
59    
60     abc_class_t*cls = abc_class_new2(file, scenename2, "flash.display::MovieClip");
61   
62     TAG*abctag = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC);
63     
64     tag = swf_InsertTag(abctag, ST_SYMBOLCLASS);
65     swf_SetU16(tag, 1);
66     swf_SetU16(tag, 0);
67     swf_SetString(tag, scenename1);
68
69     c = abc_class_getstaticconstructor(cls, 0)->body;
70     c->old.max_stack = 1;
71     c->old.local_count = 1;
72     c->old.init_scope_depth = 9;
73     c->old.max_scope_depth = 10;
74
75     __ getlocal_0(c);
76     __ pushscope(c);
77     __ returnvoid(c);
78
79     c = abc_class_getconstructor(cls, 0)->body;
80     c->old.max_stack = 3;
81     c->old.local_count = 1;
82     c->old.init_scope_depth = 10;
83     c->old.max_scope_depth = 11;
84     
85     debugfile(c, "constructor.as");
86
87     __ getlocal_0(c);
88     __ pushscope(c);
89
90     __ getlocal_0(c);
91     __ constructsuper(c,0);
92
93     __ getlex(c, "[package]flash.system::Security");
94     __ pushstring(c, "*");
95     __ callpropvoid(c, "[package]::allowDomain", 1);
96     
97     if(stop_each_frame || has_buttons) {
98         int frame = 0;
99         tag = swf->firstTag;
100         abc_method_body_t*f = 0; //frame script
101         while(tag && tag->id!=ST_END) {
102             char framename[80];
103             char needs_framescript=0;
104             char buttonname[80];
105             char functionname[80];
106             sprintf(framename, "[packageinternal]rfx::frame%d_%s", frame, file_signature);
107             
108             if(!f && (tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2 || stop_each_frame)) {
109                 /* make the contructor add a frame script */
110                 __ findpropstrict(c,"[package]::addFrameScript");
111                 __ pushuint(c,frame);
112                 __ getlex(c,framename);
113                 __ callpropvoid(c,"[package]::addFrameScript",2);
114
115                 f = abc_class_method(cls, 0, multiname_fromstring(framename))->body;
116                 f->old.max_stack = 3;
117                 f->old.local_count = 1;
118                 f->old.init_scope_depth = 10;
119                 f->old.max_scope_depth = 11;
120                 __ debugfile(f, "framescript.as");
121                 __ debugline(f, 1);
122                 __ getlocal_0(f);
123                 __ pushscope(f);
124                 if(stop_each_frame) {
125                     __ findpropstrict(f, "[package]::stop");
126                     __ callpropvoid(f, "[package]::stop", 0);
127                 }
128             }
129
130             if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
131                 U16 id = swf_GetDefineID(tag);
132                 sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
133                 __ getlex(f,buttonname);
134                 __ getlex(f,"flash.events::MouseEvent");
135                 __ getproperty(f, "::CLICK");
136                 sprintf(functionname, "::clickbutton%d_%s", swf_GetDefineID(tag), file_signature);
137                 __ getlex(f,functionname);
138                 __ callpropvoid(f, "::addEventListener" ,2);
139
140                 needs_framescript = 1;
141
142                 abc_method_body_t*h =
143                     abc_class_method(cls, 0, multiname_fromstring(functionname))->body;
144                 list_append(h->method->parameters, multiname_fromstring("flash.events::MouseEvent"));
145
146                 h->old.max_stack = 6;
147                 h->old.local_count = 2;
148                 h->old.init_scope_depth = 10;
149                 h->old.max_scope_depth = 11;
150                 __ getlocal_0(h);
151                 __ pushscope(h);
152
153                 ActionTAG*oldaction = swf_ButtonGetAction(tag);
154                 if(oldaction && oldaction->op == ACTION__GOTOFRAME) {
155                     int framenr = GET16(oldaction->data);
156                     if(!events) {
157                         __ findpropstrict(h,"[package]::gotoAndStop");
158                         __ pushuint(h,framenr+1);
159                         __ callpropvoid(h,"[package]::gotoAndStop", 1);
160                     } else {
161                         char framename[80];
162                         sprintf(framename, "frame%d_%s", framenr, file_signature);
163                         __ getlocal_0(h); //this
164                         __ findpropstrict(h, "[package]flash.events::TextEvent");
165                         __ pushstring(h, "link");
166                         __ pushtrue(h);
167                         __ pushtrue(h);
168                         __ pushstring(h, framename);
169                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
170                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
171                     }
172                 } else if(oldaction && oldaction->op == ACTION__GETURL) {
173                     if(!events) {
174                         __ findpropstrict(h,"flash.net::navigateToURL");
175                         __ findpropstrict(h,"flash.net::URLRequest");
176                         // TODO: target _blank
177                         __ pushstring(h,oldaction->data); //url
178                         __ constructprop(h,"flash.net::URLRequest", 1);
179                         __ callpropvoid(h,"flash.net::navigateToURL", 1);
180                     } else {
181                         __ getlocal_0(h); //this
182                         __ findpropstrict(h, "[package]flash.events::TextEvent");
183                         __ pushstring(h, "link");
184                         __ pushtrue(h);
185                         __ pushtrue(h);
186                         __ pushstring(h,oldaction->data); //url
187                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
188                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
189                     }
190                 } else if(oldaction) {
191                     fprintf(stderr, "Warning: Couldn't translate button code of button %d to flash 9 abc action\n", id);
192                 }
193                 __ returnvoid(h);
194                 swf_ActionFree(oldaction);
195             }
196             if(tag->id == ST_SHOWFRAME) {
197                 if(f) {
198                     __ returnvoid(f);
199                     f = 0;
200                 }
201                 frame++;
202             }
203             tag = tag->next;
204         }
205         if(f) {
206             __ returnvoid(f);
207         }
208     }
209     __ returnvoid(c);
210
211     tag = swf->firstTag;
212     while(tag) {
213         if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
214             char buttonname[80];
215             sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
216             multiname_t*s = multiname_fromstring(buttonname);
217             //abc_class_slot(cls, multiname_fromstring(buttonname), s);
218             abc_class_slot(cls, multiname_fromstring(buttonname), 
219                                 multiname_fromstring("flash.display::SimpleButton"));
220         }
221         tag = tag->next;
222     }
223
224
225     abc_script_t*s = abc_initscript(file);
226     c = s->method->body;
227     c->old.max_stack = 2;
228     c->old.local_count = 1;
229     c->old.init_scope_depth = 1;
230     c->old.max_scope_depth = 9;
231
232     __ getlocal_0(c);
233     __ pushscope(c);
234     __ getscopeobject(c, 0);
235     __ getlex(c,"::Object");
236     __ pushscope(c);
237     __ getlex(c,"flash.events::EventDispatcher");
238     __ pushscope(c);
239     __ getlex(c,"flash.display::DisplayObject");
240     __ pushscope(c);
241     __ getlex(c,"flash.display::InteractiveObject");
242     __ pushscope(c);
243     __ getlex(c,"flash.display::DisplayObjectContainer");
244     __ pushscope(c);
245     __ getlex(c,"flash.display::Sprite");
246     __ pushscope(c);
247     __ getlex(c,"flash.display::MovieClip");
248     __ pushscope(c);
249     __ getlex(c,"flash.display::MovieClip");
250     __ newclass(c,cls);
251     __ popscope(c);
252     __ popscope(c);
253     __ popscope(c);
254     __ popscope(c);
255     __ popscope(c);
256     __ popscope(c);
257     __ popscope(c);
258     __ initproperty(c,scenename2);
259     __ returnvoid(c);
260
261     //abc_method_body_addClassTrait(c, "rfx:MainTimeline", 1, cls);
262     multiname_t*classname = multiname_fromstring(scenename2);
263     abc_initscript_addClassTrait(s, classname, cls);
264     multiname_destroy(classname);
265
266     swf_WriteABC(abctag, file);
267 }
268
269 TAG*swf_AddAS3FontDefine(TAG*tag, U16 id, char*fontname)
270 {
271     tag = swf_InsertTag(tag, ST_DOABC);
272     abc_file_t*file = abc_file_new();
273
274     //abc_class_t*cls = abc_class_new2(file, fontname, "flash.display::MovieClip");
275     //abc_class_slot(cls, multiname_fromstring(fontname), multiname_fromstring("flash.text::Font"));
276
277     abc_class_t*cls = abc_class_new2(file, fontname, "flash.text::Font");
278
279     abc_script_t*s = abc_initscript(file);
280     code_t*c = s->method->body->code;
281     c = abc_getlocal_0(c);
282     c = abc_pushscope(c);
283     c = abc_getscopeobject(c, 0);
284     c = abc_getlex(c,"flash.text::Font");
285     c = abc_pushscope(c);
286     c = abc_getlex(c,"flash.text::Font");
287     c = abc_newclass(c,cls);
288     c = abc_popscope(c);
289     c = abc_initproperty(c, fontname);
290     c = abc_returnvoid(c);
291     s->method->body->code = c;
292
293     abc_initscript_addClassTrait(s, multiname_fromstring(fontname), cls);
294     swf_WriteABC(tag, file);
295         
296     tag = swf_InsertTag(tag, ST_SYMBOLCLASS);
297     swf_SetU16(tag, 1);
298     swf_SetU16(tag, id);
299     swf_SetString(tag, fontname);
300
301     return tag;
302 }
303