new parameter -s textonly
[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 = initialize_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((char*)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],
52             h[4],h[5],h[6],h[7],
53             h[8],h[9],h[10],h[11],
54             h[12],h[13],h[14],h[15]);
55
56     char scenename1[80], scenename2[80];
57     sprintf(scenename1, "rfx.MainTimeline_%s", file_signature);
58     sprintf(scenename2, "rfx::MainTimeline_%s", file_signature);
59
60     abc_file_t*file = abc_file_new();
61     abc_method_body_t*c = 0;
62    
63     abc_class_t*cls = abc_class_new2(file, scenename2, "flash.display::MovieClip");
64   
65     TAG*abctag = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC);
66     
67     tag = swf_InsertTag(abctag, ST_SYMBOLCLASS);
68     swf_SetU16(tag, 1);
69     swf_SetU16(tag, 0);
70     swf_SetString(tag, scenename1);
71
72     c = abc_class_getstaticconstructor(cls, 0)->body;
73     c->old.max_stack = 1;
74     c->old.local_count = 1;
75     c->old.init_scope_depth = 9;
76     c->old.max_scope_depth = 10;
77
78     __ getlocal_0(c);
79     __ pushscope(c);
80     __ returnvoid(c);
81
82     c = abc_class_getconstructor(cls, 0)->body;
83     c->old.max_stack = 3;
84     c->old.local_count = 1;
85     c->old.init_scope_depth = 10;
86     c->old.max_scope_depth = 11;
87     
88     debugfile(c, "constructor.as");
89
90     __ getlocal_0(c);
91     __ pushscope(c);
92
93     __ getlocal_0(c);
94     __ constructsuper(c,0);
95
96     __ getlex(c, "[package]flash.system::Security");
97     __ pushstring(c, "*");
98     __ callpropvoid(c, "[package]::allowDomain", 1);
99     
100     if(stop_each_frame || has_buttons) {
101         int frame = 0;
102         tag = swf->firstTag;
103         abc_method_body_t*f = 0; //frame script
104         while(tag && tag->id!=ST_END) {
105             char framename[80];
106             char needs_framescript=0;
107             char buttonname[80];
108             char functionname[80];
109             sprintf(framename, "[packageinternal]rfx::frame%d_%s", frame, file_signature);
110             
111             if(!f && (tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2 || stop_each_frame)) {
112                 /* make the contructor add a frame script */
113                 __ findpropstrict(c,"[package]::addFrameScript");
114                 __ pushuint(c,frame);
115                 __ getlex(c,framename);
116                 __ callpropvoid(c,"[package]::addFrameScript",2);
117
118                 f = abc_class_method(cls, 0, multiname_fromstring(framename))->body;
119                 f->old.max_stack = 3;
120                 f->old.local_count = 1;
121                 f->old.init_scope_depth = 10;
122                 f->old.max_scope_depth = 11;
123                 __ debugfile(f, "framescript.as");
124                 __ debugline(f, 1);
125                 __ getlocal_0(f);
126                 __ pushscope(f);
127                 if(stop_each_frame) {
128                     __ findpropstrict(f, "[package]::stop");
129                     __ callpropvoid(f, "[package]::stop", 0);
130                 }
131             }
132
133             if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
134                 U16 id = swf_GetDefineID(tag);
135                 sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
136                 __ getlex(f,buttonname);
137                 __ getlex(f,"flash.events::MouseEvent");
138                 __ getproperty(f, "::CLICK");
139                 sprintf(functionname, "::clickbutton%d_%s", swf_GetDefineID(tag), file_signature);
140                 __ getlex(f,functionname);
141                 __ callpropvoid(f, "::addEventListener" ,2);
142
143                 needs_framescript = 1;
144
145                 abc_method_body_t*h =
146                     abc_class_method(cls, 0, multiname_fromstring(functionname))->body;
147                 list_append(h->method->parameters, multiname_fromstring("flash.events::MouseEvent"));
148
149                 h->old.max_stack = 6;
150                 h->old.local_count = 2;
151                 h->old.init_scope_depth = 10;
152                 h->old.max_scope_depth = 11;
153                 __ getlocal_0(h);
154                 __ pushscope(h);
155
156                 ActionTAG*oldaction = swf_ButtonGetAction(tag);
157                 if(oldaction && oldaction->op == ACTION__GOTOFRAME) {
158                     int framenr = GET16(oldaction->data);
159                     if(!events) {
160                         __ findpropstrict(h,"[package]::gotoAndStop");
161                         __ pushuint(h,framenr+1);
162                         __ callpropvoid(h,"[package]::gotoAndStop", 1);
163                     } else {
164                         char framename[80];
165                         sprintf(framename, "frame%d_%s", framenr, file_signature);
166                         __ getlocal_0(h); //this
167                         __ findpropstrict(h, "[package]flash.events::TextEvent");
168                         __ pushstring(h, "link");
169                         __ pushtrue(h);
170                         __ pushtrue(h);
171                         __ pushstring(h, framename);
172                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
173                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
174                     }
175                 } else if(oldaction && oldaction->op == ACTION__GETURL) {
176                     if(!events) {
177                         __ findpropstrict(h,"flash.net::navigateToURL");
178                         __ findpropstrict(h,"flash.net::URLRequest");
179                         // TODO: target _blank
180                         __ pushstring(h,(char*)oldaction->data); //url
181                         __ constructprop(h,"flash.net::URLRequest", 1);
182                         __ callpropvoid(h,"flash.net::navigateToURL", 1);
183                     } else {
184                         __ getlocal_0(h); //this
185                         __ findpropstrict(h, "[package]flash.events::TextEvent");
186                         __ pushstring(h, "link");
187                         __ pushtrue(h);
188                         __ pushtrue(h);
189                         __ pushstring(h,(char*)oldaction->data); //url
190                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
191                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
192                     }
193                 } else if(oldaction) {
194                     fprintf(stderr, "Warning: Couldn't translate button code of button %d to flash 9 abc action\n", id);
195                 }
196                 __ returnvoid(h);
197                 swf_ActionFree(oldaction);
198             }
199             if(tag->id == ST_SHOWFRAME) {
200                 if(f) {
201                     __ returnvoid(f);
202                     f = 0;
203                 }
204                 frame++;
205             }
206             tag = tag->next;
207         }
208         if(f) {
209             __ returnvoid(f);
210         }
211     }
212     __ returnvoid(c);
213
214     tag = swf->firstTag;
215     while(tag) {
216         if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
217             char buttonname[80];
218             sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
219             multiname_t*s = multiname_fromstring(buttonname);
220             //abc_class_slot(cls, multiname_fromstring(buttonname), s);
221             abc_class_slot(cls, multiname_fromstring(buttonname), 
222                                 multiname_fromstring("flash.display::SimpleButton"));
223         }
224         tag = tag->next;
225     }
226
227
228     abc_script_t*s = abc_initscript(file);
229     c = s->method->body;
230     c->old.max_stack = 2;
231     c->old.local_count = 1;
232     c->old.init_scope_depth = 1;
233     c->old.max_scope_depth = 9;
234
235     __ getlocal_0(c);
236     __ pushscope(c);
237     __ getscopeobject(c, 0);
238     __ getlex(c,"::Object");
239     __ pushscope(c);
240     __ getlex(c,"flash.events::EventDispatcher");
241     __ pushscope(c);
242     __ getlex(c,"flash.display::DisplayObject");
243     __ pushscope(c);
244     __ getlex(c,"flash.display::InteractiveObject");
245     __ pushscope(c);
246     __ getlex(c,"flash.display::DisplayObjectContainer");
247     __ pushscope(c);
248     __ getlex(c,"flash.display::Sprite");
249     __ pushscope(c);
250     __ getlex(c,"flash.display::MovieClip");
251     __ pushscope(c);
252     __ getlex(c,"flash.display::MovieClip");
253     __ newclass(c,cls);
254     __ popscope(c);
255     __ popscope(c);
256     __ popscope(c);
257     __ popscope(c);
258     __ popscope(c);
259     __ popscope(c);
260     __ popscope(c);
261     __ initproperty(c,scenename2);
262     __ returnvoid(c);
263
264     //abc_method_body_addClassTrait(c, "rfx:MainTimeline", 1, cls);
265     multiname_t*classname = multiname_fromstring(scenename2);
266     abc_initscript_addClassTrait(s, classname, cls);
267     multiname_destroy(classname);
268
269     swf_WriteABC(abctag, file);
270 }
271
272 TAG*swf_AddAS3FontDefine(TAG*tag, U16 id, char*fontname)
273 {
274     tag = swf_InsertTag(tag, ST_DOABC);
275     abc_file_t*file = abc_file_new();
276
277     //abc_class_t*cls = abc_class_new2(file, fontname, "flash.display::MovieClip");
278     //abc_class_slot(cls, multiname_fromstring(fontname), multiname_fromstring("flash.text::Font"));
279
280     abc_class_t*cls = abc_class_new2(file, fontname, "flash.text::Font");
281
282     abc_script_t*s = abc_initscript(file);
283     code_t*c = s->method->body->code;
284     c = abc_getlocal_0(c);
285     c = abc_pushscope(c);
286     c = abc_getscopeobject(c, 0);
287     c = abc_getlex(c,"flash.text::Font");
288     c = abc_pushscope(c);
289     c = abc_getlex(c,"flash.text::Font");
290     c = abc_newclass(c,cls);
291     c = abc_popscope(c);
292     c = abc_initproperty(c, fontname);
293     c = abc_returnvoid(c);
294     s->method->body->code = c;
295
296     abc_initscript_addClassTrait(s, multiname_fromstring(fontname), cls);
297     swf_WriteABC(tag, file);
298         
299     tag = swf_InsertTag(tag, ST_SYMBOLCLASS);
300     swf_SetU16(tag, 1);
301     swf_SetU16(tag, id);
302     swf_SetString(tag, fontname);
303
304     return tag;
305 }
306