void as_global_clearinterval(const fn_call& fn) { if (fn.nargs > 0) { fn.get_root()->remove_listener(fn.arg(0).to_object()); } }
void as_point_subtract(const fn_call& fn) { if (fn.nargs < 1) { return; } as_point* point = cast_to<as_point>(fn.this_ptr); if (point == NULL) { return; } if (fn.arg(0).to_object() == NULL) { return; } as_point* other_point = cast_to<as_point>(fn.arg(0).to_object()); if (other_point) { smart_ptr<as_point> obj; obj = new as_point(fn.get_player(), point->m_point.m_x - other_point->m_point.m_x, point->m_point.m_y - other_point->m_point.m_y); fn.result->set_as_object(obj.get_ptr()); } }
void string_last_index_of(const fn_call& fn) { const tu_string& sstr = fn.this_value.to_tu_string(); if (fn.nargs < 1) { fn.result->set_double(-1); } else { int start_index = 0; if (fn.nargs > 1) { start_index = fn.arg(1).to_int(); } const char* str = sstr.c_str(); const char* last_hit = NULL; const char* haystack = str; for (;;) { const char* p = strstr(haystack, fn.arg(0).to_string()); if (p == NULL || (start_index !=0 && p > str + start_index ) ) // FIXME: not UTF-8 correct! { break; } last_hit = p; haystack = p + 1; } if (last_hit == NULL) { fn.result->set_double(-1); } else { fn.result->set_double(tu_string::utf8_char_count(str, (int) (last_hit - str))); } } }
void string_index_of(const fn_call& fn) { const tu_string& sstr = fn.this_value.to_tu_string(); if (fn.nargs < 1) { fn.result->set_double(-1); } else { int start_index = 0; if (fn.nargs > 1) { start_index = fn.arg(1).to_int(); } const char* str = sstr.c_str(); const char* p = strstr( str + start_index, // FIXME: not UTF-8 correct! fn.arg(0).to_string()); if (p == NULL) { fn.result->set_double(-1); return; } fn.result->set_double(tu_string::utf8_char_count(str, (int) (p - str))); } }
void string_slice(const fn_call& fn) { const tu_string& this_str = fn.this_value.to_tu_string(); int len = this_str.utf8_length(); int start = 0; if (fn.nargs >= 1) { start = fn.arg(0).to_int(); if (start < 0) { start = len + start; } } int end = len; if (fn.nargs >= 2) { end = fn.arg(1).to_int(); if (end < 0) { end = len + end; } } start = iclamp(start, 0, len); end = iclamp(end, start, len); fn.result->set_tu_string(this_str.utf8_substring(start, end)); }
void as_mcloader_loadclip(const fn_call& fn) { as_mcloader* mcl = cast_to<as_mcloader>(fn.this_ptr); assert(mcl); fn.result->set_bool(false); // on default if (fn.nargs == 2) { array<as_value> event_args; // for event handler args event_args.push_back(as_value()); // undefined tu_string infile = get_full_url(fn.get_player()->get_workdir(), fn.arg(0).to_string()); movie_definition* md = fn.get_player()->create_movie(infile.c_str()); if (md == NULL) { IF_VERBOSE_ACTION(log_msg("can't create movie from %s\n", fn.arg(0).to_string())); event_args.push_back("URLNotFound"); // 2-d param mcl->m_listeners.notify(event_id(event_id::ONLOAD_ERROR, &event_args)); return; } as_mcloader::loadable_movie lm; lm.m_def = cast_to<movie_def_impl>(md); lm.m_target = cast_to<character>(fn.env->find_target(fn.arg(1))); mcl->m_lm.push_back(lm); mcl->m_listeners.notify(event_id(event_id::ONLOAD_START, &event_args)); fn.result->set_bool(true); } }
// Invokes the function represented by a Function object. // public call(thisObject:Object, [parameter1:Object]) : Object void as_s_function_call(const fn_call& fn) { assert(fn.this_ptr); if (fn.nargs > 0) { as_object* properties = fn.this_ptr; if (properties->m_this_ptr != NULL) { as_object* func = properties->m_this_ptr.get_ptr(); if (func) { as_environment env(fn.get_player()); int nargs = 0; if (fn.nargs > 1) { nargs = 1; env.push(fn.arg(1)); } *fn.result = call_method(func, &env, fn.arg(0).to_object(), nargs, env.get_top_index()); } } } }
void as_map_material(const fn_call& fn) { x3ds_instance* x3ds = cast_to<x3ds_instance>(fn.this_ptr); if (x3ds && fn.nargs == 2) { x3ds->m_map[fn.arg(0).to_tu_string()] = fn.arg(1); } }
void as_global_movieclip_ctor(const fn_call& fn) // Constructor for ActionScript class XMLSocket { root* rm = fn.get_player()->get_root(); sprite_definition* empty_sprite_def = new sprite_definition(fn.get_player(), NULL); character* ch = new sprite_instance(fn.get_player(), empty_sprite_def, rm, rm->get_root_movie(), 0); fn.result->set_as_object(ch); }
// flash9 void sprite_add_script(const fn_call& fn) { sprite_instance* sprite = sprite_getptr(fn); if (fn.nargs == 2) { // arg #1 - frame number, 0 based // arg #2 - function sprite->add_script(fn.arg(0).to_int(), fn.arg(1).to_function()); } }
void sound_attach(const fn_call& fn) { if (fn.nargs < 1) { log_error("attach sound needs one argument\n"); return; } as_sound* snd = cast_to<as_sound>(fn.this_ptr); assert(snd); assert(fn.env); // find target movieclip character* target = snd->m_target.get_ptr(); if (target == NULL) { target = fn.env->get_target(); } // find resource character_def* res = NULL; if (target) { res = target->find_exported_resource(fn.arg(0).to_string()); } if (res == NULL) { IF_VERBOSE_ACTION(log_msg("import error: resource '%s' is not exported\n", fn.arg(0).to_string())); return; } int si = 0; sound_sample* ss = cast_to<sound_sample>(res); if (ss != NULL) { si = ss->m_sound_handler_id; } else { log_error("sound sample is NULL\n"); return; } snd->clear(); // sanity check assert(si >= 0 && si < 1000); snd->m_id = si; snd->m_is_loaded_sound = false; }
// public watch(name:String, callback:Function, [userData:Object]) : Boolean // Registers an event handler to be invoked when a specified property of // an ActionScript object changes. When the property changes, // the event handler is invoked with myObject as the containing object. void as_object_watch(const fn_call& fn) { bool ret = false; if (fn.nargs >= 2) { assert(fn.this_ptr); ret = fn.this_ptr->watch(fn.arg(0).to_tu_string(), fn.arg(1).to_function(), fn.nargs > 2 ? fn.arg(2) : as_value()); } fn.result->set_bool(ret); }
// Transform( mc:MovieClip ) void as_global_transform_ctor(const fn_call& fn) { if (fn.nargs == 1) { gc_ptr<as_transform> obj; if (character* movie = cast_to<character>(fn.arg(0).to_object())) { obj = new as_transform(fn.get_player(), movie); } fn.result->set_as_object(obj.get_ptr()); } }
void as_listener::broadcast(const fn_call& fn) { assert(fn.env); if (m_reentrance) { // keep call args // we must process one event completely then another array<as_value> arg; for (int i = 0; i < fn.nargs; i++) { arg.push_back(fn.arg(i)); } m_suspended_event.push(arg); return; } m_reentrance = true; // event handler may affects 'fn.arg' using broadcastMessage // so we iterate through the copy of args tu_string event_name = fn.arg(0).to_tu_string(); for (int j = fn.nargs - 1; j > 0; j--) { fn.env->push(fn.arg(j)); } m_listeners.notify(event_name, fn_call(NULL, 0, fn.env, fn.nargs - 1, fn.env->get_top_index())); fn.env->drop(fn.nargs - 1); // check reentrances while (m_suspended_event.size() > 0) { // event handler may affects m_suspended_event using broadcastMessage // so we iterate through the copy of args array<as_value>& arg = m_suspended_event.front(); tu_string event_name = arg[0].to_tu_string(); for (int j = arg.size() - 1; j > 0; j--) { fn.env->push(arg[j]); } m_listeners.notify(event_name, fn_call(NULL, 0, fn.env, arg.size() - 1, fn.env->get_top_index())); fn.env->drop(fn.nargs - 1); m_suspended_event.pop(); } m_reentrance = false; }
as_value launcher_verify_md5sum(const fn_call& fn) { GNASH_REPORT_FUNCTION; boost::intrusive_ptr<launcher_as_object> ptr = ensureType<launcher_as_object>(fn.this_ptr); if (fn.nargs > 0) { string filespec = fn.arg(0).to_string(); string md5 = fn.arg(1).to_string(); return as_value(ptr->obj.verify_md5sum(filespec.c_str(), md5.c_str())); } return as_value(true); }
// this takes two arguments as_value gtkext_container_add(const fn_call& fn) { // GNASH_REPORT_FUNCTION; boost::intrusive_ptr<GtkExt> ptr = ensureType<GtkExt>(fn.this_ptr); if (fn.nargs > 0) { GtkExt *parent = dynamic_cast<GtkExt *>(fn.arg(0).to_object(*getGlobal(fn)).get()); GtkExt *child = dynamic_cast<GtkExt *>(fn.arg(1).to_object(*getGlobal(fn)).get()); gtk_container_add (GTK_CONTAINER (parent->getWindow()), child->getWindow()); return as_value(true); } return as_value(false); }
//createEmptyMovieClip(name:String, depth:Number) : MovieClip void sprite_create_empty_movieclip(const fn_call& fn) { sprite_instance* sprite = sprite_getptr(fn); if (fn.nargs != 2) { log_error("createEmptyMovieClip needs 2 args\n"); return; } character* ch = sprite->add_empty_movieclip(fn.arg(0).to_string(), fn.arg(1).to_int() + ADJUST_DEPTH_VALUE); fn.result->set_as_object(ch); }
void as_xmlsock_connect(const fn_call& fn) { if (fn.nargs != 2) { fn.result->set_bool(false); return; } as_xmlsock* xmls = cast_to<as_xmlsock>(fn.this_ptr); assert(xmls); fn.result->set_bool(xmls->connect(fn.arg(0).to_string(), fn.arg(1).to_int())); }
void as_global_parse_int(const fn_call& fn) { if (fn.nargs > 0) { int res; int base = fn.nargs > 1 ? fn.arg(1).to_int() : 10; if (string_to_number(&res, fn.arg(0).to_string(), base)) { fn.result->set_int(res); return; } } fn.result->set_nan(); }
void as_global_textformat_ctor(const fn_call& fn) { gc_ptr<as_textformat> obj = new as_textformat(fn.get_player()); assert(unsigned(fn.nargs) <= TU_ARRAYSIZE(as_global_textformat_ctor_paramnames)); // TODO: check parameters type for (int i = 0; i < fn.nargs; i++) { obj->set_member(as_global_textformat_ctor_paramnames[i], fn.arg(i)); } fn.result->set_as_object(obj.get_ptr()); }
// public static initialize(obj:Object) : Void // Adds event notification and listener management functionality to a given object. // This is a static method; it must be called by using the AsBroadcaster class void as_broadcaster_initialize(const fn_call& fn) { if (fn.nargs == 1) { as_object* obj = fn.arg(0).to_object(); if (obj) { obj->set_member("_listeners", new as_listener(fn.get_player())); obj->set_member("addListener", as_broadcast_addlistener); obj->set_member("removeListener", as_broadcast_removelistener); obj->set_member("broadcastMessage", as_broadcast_sendmessage); } } }
// this callback takes 2 arguments // void gtk_container_set_border_width (GtkContainer *container, guint border_width); as_value gtkext_container_set_border_width(const fn_call& fn) { // GNASH_REPORT_FUNCTION; boost::intrusive_ptr<GtkExt> ptr = ensureType<GtkExt>(fn.this_ptr); if (fn.nargs > 0) { GtkExt *window = dynamic_cast<GtkExt *>(fn.arg(0).to_object(*getGlobal(fn)).get()); int width = fn.arg(1).to_int(); window->container_set_border_width(width); dbglogfile << "set container border width to " << width << " !" << endl; } return as_value(); }
void as_global_array_ctor(const fn_call& fn) // Constructor for ActionScript class Array. { smart_ptr<as_array> ao = new as_array(fn.get_player()); // case of "var x = ["abc","def", 1,2,3,4,..];" // called from "init array" operation only if (fn.nargs == -1 && fn.first_arg_bottom_index == -1) { // Use the arguments as initializers. int size = fn.env->pop().to_int(); as_value index_number; for (int i = 0; i < size; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), fn.env->pop()); } } else // case of "var x = new Array(777)" if (fn.nargs == 1) { // Create an empty array with the given number of undefined elements. int size = fn.arg(0).to_int(); as_value index_number; for (int i = 0; i < size; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), as_value()); } } else // case of "var x = new Array(1,2,3,4,5,6,7,8,..);" { assert(fn.env); // Use the arguments as initializers. as_value index_number; for (int i = 0; i < fn.nargs; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), fn.arg(i)); } } fn.result->set_as_object(ao.get_ptr()); }
// public curveTo(controlX:Number, controlY:Number, anchorX:Number, anchorY:Number) : Void void sprite_curve_to(const fn_call& fn) { sprite_instance* sprite = sprite_getptr(fn); canvas* canva = sprite->get_canvas(); assert(canva); if (fn.nargs >= 4) { float cx = PIXELS_TO_TWIPS(fn.arg(0).to_float()); float cy = PIXELS_TO_TWIPS(fn.arg(1).to_float()); float ax = PIXELS_TO_TWIPS(fn.arg(2).to_float()); float ay = PIXELS_TO_TWIPS(fn.arg(3).to_float()); canva->curve_to(cx, cy, ax, ay); } }
// Point(x:Number, y:Number) void as_global_point_ctor(const fn_call& fn) { smart_ptr<as_point> obj; float x = 0.0f; float y = 0.0f; if (fn.nargs == 2) { y = fn.arg(1).to_float(); x = fn.arg(0).to_float(); } obj = new as_point(fn.get_player(), x, y); fn.result->set_as_object(obj.get_ptr()); }
void as_netconnection_connect(const fn_call& fn) { // Opens a local connection through which you can play back video files // from an HTTP address or from the local file system. as_netconnection* nc = cast_to<as_netconnection>(fn.this_ptr); assert(nc); UNUSED(nc); if (fn.nargs == 1) { assert(fn.env); if (fn.arg(0).is_null()) // local file system { fn.result->set_bool(true); return; } else // from an HTTP address { //todo } } fn.result->set_bool(false); return; }
as_value number_ctor(const fn_call& fn) { double val = 0; if (fn.nargs > 0) { val = toNumber(fn.arg(0), getVM(fn)); } if (!fn.isInstantiation()) { return as_value(val); } fn.this_ptr->setRelay(new Number_as(val)); return as_value(); }
// for asBroadcaster, ... void listener::notify(const tu_string& event_name, const fn_call& fn) { // may be called from multithread plugin ==> // we should check current root if (fn.get_player()->get_root() == NULL) { return; } // event handler may affects m_listeners using addListener & removeListener // iterate through a copy of it array< weak_ptr<as_object> > listeners(m_listeners); for (int i = 0, n = listeners.size(); i < n; i++) { smart_ptr<as_object> obj = listeners[i]; if (obj != NULL) // is listener destroyed ? { as_value function; if (obj->get_member(event_name, &function)) { call_method(function, fn.env, obj.get_ptr(), fn.nargs, fn.env->get_top_index()); } } } }
void sprite_goto_and_stop(const fn_call& fn) { sprite_instance* sprite = sprite_getptr(fn); if (fn.nargs < 1) { log_error("error: sprite_goto_and_stop needs one arg\n"); return; } // gotoAndStop(NaN) will be ignored if (fn.arg(0).is_string() || fn.arg(0).is_number() || fn.arg(0).is_property()) { sprite->goto_frame(fn.arg(0).to_tu_string()); sprite->set_play_state(character::STOP); } }
void as_mcloader_getprogress(const fn_call& fn) { if (fn.nargs == 1) { sprite_instance* m = cast_to<sprite_instance>(fn.arg(0).to_object()); if (m) { as_object* info = new as_object(fn.get_player()); info->set_member("bytesLoaded", (int) m->get_loaded_bytes()); info->set_member("bytesTotal", (int) m->get_file_bytes()); fn.result->set_as_object(info); return; } } fn.result->set_as_object(NULL); }