[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11949: Split the gigantic TextField
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11949: Split the gigantic TextField file into separate DisplayObject and ActionScript |
Date: |
Mon, 15 Feb 2010 16:08:21 +0100 |
User-agent: |
Bazaar (2.0.3) |
------------------------------------------------------------
revno: 11949 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2010-02-15 16:08:21 +0100
message:
Split the gigantic TextField file into separate DisplayObject and ActionScript
implementations. TextField.cpp is stil gigantic.
modified:
libcore/TextField.cpp
libcore/TextField.h
libcore/asobj/Globals.cpp
libcore/asobj/flash/text/TextField_as.cpp
libcore/asobj/flash/text/TextField_as.h
libcore/asobj/flash/text/text.am
libcore/swf/DefineEditTextTag.cpp
=== modified file 'libcore/TextField.cpp'
--- a/libcore/TextField.cpp 2010-01-28 09:25:45 +0000
+++ b/libcore/TextField.cpp 2010-02-15 14:55:30 +0000
@@ -31,37 +31,30 @@
#include "utf8.h"
#include "log.h"
#include "swf/DefineEditTextTag.h"
-#include "movie_definition.h" // to extract version info
#include "MovieClip.h"
#include "TextField.h"
#include "flash/ui/Keyboard_as.h" // for keyboard events
#include "movie_root.h" // for killing focus
#include "as_environment.h" // for parse_path
-#include "VM.h"
-#include "builtin_function.h"
-#include "NativeFunction.h"
#include "Font.h"
#include "fontlib.h"
#include "namedStrings.h"
-#include "AsBroadcaster.h" // for initializing self as a broadcaster
#include "StringPredicates.h"
-#include "flash/text/TextFormat_as.h"
-#include "GnashKey.h" // key::code
+#include "text/TextFormat_as.h"
+#include "GnashKey.h"
#include "TextRecord.h"
-#include "Global_as.h"
#include "Point2d.h"
#include "GnashNumeric.h"
#include "MouseButtonState.h"
+#include "Global_as.h"
-#include <algorithm> // std::min
+#include <algorithm>
#include <string>
-#include <boost/algorithm/string/case_conv.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
#include <cstdlib>
#include <cctype>
#include <utility>
-#include <typeinfo>
#include <map>
// Text fields have a fixed 2 pixel padding for each side (regardless of
border)
@@ -76,68 +69,6 @@
namespace gnash {
-// Forward declarations
-namespace {
- const char* autoSizeValueName(TextField::AutoSize val);
- TextField::AutoSize parseAutoSize(const std::string& val);
-
- void attachPrototypeProperties(as_object& proto);
- void attachTextFieldStaticMembers(as_object& o);
- void attachTextFieldInterface(as_object& o);
-
- as_value textfield_createTextField(const fn_call& fn);
-
- as_value textfield_variable(const fn_call& fn);
- as_value textfield_setTextFormat(const fn_call& fn);
- as_value textfield_getTextFormat(const fn_call& fn);
- as_value textfield_setNewTextFormat(const fn_call& fn);
- as_value textfield_getNewTextFormat(const fn_call& fn);
- as_value textfield_getDepth(const fn_call& fn);
- as_value textfield_getFontList(const fn_call& fn);
- as_value textfield_removeTextField(const fn_call& fn);
- as_value textfield_replaceSel(const fn_call& fn);
- as_value textfield_replaceText(const fn_call& fn);
-
- as_value textfield_password(const fn_call& fn);
- as_value textfield_ctor(const fn_call& fn);
- as_value textfield_multiline(const fn_call& fn);
- as_value textfield_scroll(const fn_call& fn);
- as_value textfield_maxscroll(const fn_call& fn);
- as_value textfield_maxhscroll(const fn_call& fn);
- as_value textfield_maxChars(const fn_call& fn);
- as_value textfield_bottomScroll(const fn_call& fn);
- as_value textfield_hscroll(const fn_call& fn);
- as_value textfield_htmlText(const fn_call& fn);
- as_value textfield_restrict(const fn_call& fn);
- as_value textfield_background(const fn_call& fn);
- as_value textfield_border(const fn_call& fn);
- as_value textfield_backgroundColor(const fn_call& fn);
- as_value textfield_borderColor(const fn_call& fn);
- as_value textfield_text(const fn_call& fn);
- as_value textfield_textColor(const fn_call& fn);
- as_value textfield_embedFonts(const fn_call& fn);
- as_value textfield_autoSize(const fn_call& fn);
- as_value textfield_type(const fn_call& fn);
- as_value textfield_wordWrap(const fn_call& fn);
- as_value textfield_html(const fn_call& fn);
- as_value textfield_selectable(const fn_call& fn);
- as_value textfield_length(const fn_call& fn);
- as_value textfield_textWidth(const fn_call& fn);
- as_value textfield_textHeight(const fn_call& fn);
-}
-
-as_object*
-createTextFieldObject(Global_as& gl)
-{
- as_value tf(gl.getMember(NSV::CLASS_TEXT_FIELD));
- as_function* ctor = tf.to_function();
- if (!ctor) return 0;
- fn_call::Args args;
- as_environment env(getVM(gl));
- return constructInstance(*ctor, env, args);
-}
-
-
TextField::TextField(as_object* object, DisplayObject* parent,
const SWF::DefineEditTextTag& def)
:
@@ -2341,46 +2272,6 @@
}
}
-/// This provides the prototype and static methods for TextField.
-//
-/// For SWF5 there is initially no prototype, for SWF6+ there is a
-/// limited prototype. This is changed later on instantiation of a
-/// TextField.
-void
-textfield_class_init(as_object& where, const ObjectURI& uri)
-{
-
- Global_as& gl = getGlobal(where);
- as_object* proto = gl.createObject();
- as_object* cl = gl.createClass(&textfield_ctor, proto);
-
- attachTextFieldInterface(*proto);
- attachTextFieldStaticMembers(*cl);
-
- where.init_member(uri, cl, as_object::DefaultFlags);
-
- // ASSetPropFlags is called on the TextField class.
- as_object* null = 0;
- callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, cl, null, 131);
-}
-
-void
-registerTextFieldNative(as_object& global)
-{
- VM& vm = getVM(global);
- vm.registerNative(textfield_replaceSel, 104, 100);
- vm.registerNative(textfield_getTextFormat, 104, 101);
- vm.registerNative(textfield_setTextFormat, 104, 102);
- vm.registerNative(textfield_removeTextField, 104, 103);
- vm.registerNative(textfield_getNewTextFormat, 104, 104);
- vm.registerNative(textfield_setNewTextFormat, 104, 105);
- vm.registerNative(textfield_getDepth, 104, 106);
- vm.registerNative(textfield_replaceText, 104, 107);
-
- vm.registerNative(textfield_createTextField, 104, 200);
- vm.registerNative(textfield_getFontList, 104, 201);
-}
-
bool
TextField::pointInShape(boost::int32_t x, boost::int32_t y) const
{
@@ -2773,1061 +2664,6 @@
/// TextField interface functions
-namespace {
-
-void
-attachPrototypeProperties(as_object& o)
-{
- // SWF6 or higher
- const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
-
- boost::intrusive_ptr<builtin_function> getset;
-
- // The following properties should only be attached to the prototype
- // on first textfield creation.
- o.init_property(NSV::PROP_TEXT_WIDTH,
- textfield_textWidth, textfield_textWidth);
- o.init_property(NSV::PROP_TEXT_HEIGHT,
- textfield_textHeight, textfield_textHeight);
-
- Global_as& gl = getGlobal(o);
-
- getset = gl.createFunction(textfield_variable);
- o.init_property("variable", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_background);
- o.init_property("background", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_text);
- o.init_property("text", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_backgroundColor);
- o.init_property("backgroundColor", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_border);
- o.init_property("border", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_borderColor);
- o.init_property("borderColor", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_textColor);
- o.init_property("textColor", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_embedFonts);
- o.init_property("embedFonts", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_autoSize);
- o.init_property("autoSize", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_type);
- o.init_property("type", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_wordWrap);
- o.init_property("wordWrap", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_html);
- o.init_property("html", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_selectable);
- o.init_property("selectable", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_length);
- o.init_property("length", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_maxscroll);
- o.init_property("maxscroll", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_maxhscroll);
- o.init_property("maxhscroll", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_maxChars);
- o.init_property("maxChars", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_bottomScroll);
- o.init_property("bottomScroll", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_scroll);
- o.init_property("scroll", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_hscroll);
- o.init_property("hscroll", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_restrict);
- o.init_property("restrict", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_multiline);
- o.init_property("multiline", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_password);
- o.init_property("password", *getset, *getset, swf6Flags);
- getset = gl.createFunction(textfield_htmlText);
- o.init_property("htmlText", *getset, *getset, swf6Flags);
-}
-
-
-/// This is in fact a property of MovieClip, but it is more a TextField
-/// function, as its major number (104) in the native table shows.
-as_value
-textfield_createTextField(const fn_call& fn)
-{
- MovieClip* ptr = ensure<IsDisplayObject<MovieClip> >(fn);
-
- // name, depth, x, y, width, height
- if (fn.nargs < 6) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("createTextField called with %d args, "
- "expected 6 - returning undefined"), fn.nargs);
- );
- return as_value();
- }
-
- const std::string& name = fn.arg(0).to_string();
- const int depth = toInt(fn.arg(1));
- const int x = toInt(fn.arg(2));
- const int y = toInt(fn.arg(3));
-
- int width = toInt(fn.arg(4));
- if (width < 0) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("createTextField: negative width (%d)"
- " - reverting sign"), width);
- );
- width = -width;
- }
-
- int height = toInt(fn.arg(5));
- if ( height < 0 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("createTextField: negative height (%d)"
- " - reverting sign"), height);
- );
- height = -height;
- }
- // Set textfield bounds
- SWFRect bounds(0, 0, pixelsToTwips(width), pixelsToTwips(height));
-
- // Tests in actionscript.all/TextField.as show that this function must:
- // 1. Call "new _global.TextField()" (which takes care of
- // assigning properties to the prototype).
- // 2. Make that object into a TextField and put it on the display list.
- as_object* obj = createTextFieldObject(getGlobal(fn));
-
- DisplayObject* tf = new TextField(obj, ptr, bounds);
-
- // Give name and mark as dynamic
- tf->set_name(name);
- tf->setDynamic();
-
- // Set _x and _y
- SWFMatrix matrix;
- matrix.set_translation(pixelsToTwips(x), pixelsToTwips(y));
- // update caches (although shouldn't be needed as we only set translation)
- tf->setMatrix(matrix, true);
-
- ptr->addDisplayListObject(tf, depth);
-
- if (getSWFVersion(fn) > 7) return as_value(obj);
- return as_value();
-}
-
-as_value
-textfield_background(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->getDrawBackground());
- }
- else {
- ptr->setDrawBackground(fn.arg(0).to_bool());
- }
-
- return as_value();
-}
-
-as_value
-textfield_border(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->getDrawBorder());
- }
- else {
- ptr->setDrawBorder(fn.arg(0).to_bool());
- }
-
- return as_value();
-}
-
-as_value
-textfield_backgroundColor(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->getBackgroundColor().toRGB());
- }
- else {
- rgba newColor;
- newColor.parseRGB(static_cast<boost::uint32_t>(toInt(fn.arg(0))));
- ptr->setBackgroundColor(newColor);
- }
-
- return as_value();
-}
-
-as_value
-textfield_borderColor(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->getBorderColor().toRGB());
- }
- else {
- rgba newColor;
- newColor.parseRGB(static_cast<boost::uint32_t>(fn.arg(0).to_number()));
- ptr->setBorderColor(newColor);
- }
-
- return as_value();
-}
-
-
-as_value
-textfield_textColor(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- // Getter
- return as_value(ptr->getTextColor().toRGB());
- }
-
- // Setter
- rgba newColor;
- newColor.parseRGB(static_cast<boost::uint32_t>(fn.arg(0).to_number()));
- ptr->setTextColor(newColor);
-
- return as_value();
-}
-
-as_value
-textfield_embedFonts(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- // Getter
- return as_value(ptr->getEmbedFonts());
- }
-
- // Setter
- ptr->setEmbedFonts(fn.arg(0).to_bool());
- return as_value();
-}
-
-as_value
-textfield_wordWrap(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->doWordWrap());
- }
- else {
- ptr->setWordWrap(fn.arg(0).to_bool());
- }
-
- return as_value();
-}
-
-as_value
-textfield_html(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (fn.nargs == 0) {
- return as_value(ptr->doHtml());
- }
- else {
- ptr->setHtml( fn.arg(0).to_bool() );
- }
-
- return as_value();
-}
-
-as_value
-textfield_selectable(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs == 0 ) // getter
- {
- return as_value(ptr->isSelectable());
- }
- else // setter
- {
- ptr->setSelectable( fn.arg(0).to_bool() );
- }
-
- return as_value();
-}
-
-as_value
-textfield_length(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs == 0 ) // getter
- {
- const std::string& s = ptr->get_text_value();
- return as_value(s.length()); // TOCHECK: utf-8 ?
- }
- else // setter
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Attempt to set length property of TextField %s"),
- ptr->getTarget());
- );
- }
-
- return as_value();
-}
-
-as_value
-textfield_textHeight(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs == 0 ) // getter
- {
- // Return the height, in pixels, of the text as laid out.
- // (I.e. the actual text content, not our defined
- // bounding box.)
- //
- // In local coords. Verified against Macromedia Flash.
- return as_value(twipsToPixels(ptr->getTextBoundingBox().height()));
-
- }
- else // setter
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Attempt to set read-only %s property of TextField "
- "%s"), "textHeight", ptr->getTarget());
- );
- }
-
- return as_value();
-}
-
-as_value
-textfield_textWidth(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs == 0 ) // getter
- {
- // Return the width, in pixels, of the text as laid out.
- // (I.e. the actual text content, not our defined
- // bounding box.)
- //
- // In local coords. Verified against Macromedia Flash.
- return as_value(twipsToPixels(ptr->getTextBoundingBox().width()));
-
- }
- else // setter
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Attempt to set read-only %s property of TextField %s"),
- "textWidth", ptr->getTarget());
- );
- }
-
- return as_value();
-}
-
-as_value
-textfield_autoSize(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs == 0 ) // getter
- {
- return autoSizeValueName(ptr->getAutoSize());
- }
- else // setter
- {
- const as_value& arg = fn.arg(0);
- if (arg.is_bool()) {
- if (arg.to_bool()) {
- // True equates to left, every other bool to none.
- ptr->setAutoSize(TextField::AUTOSIZE_LEFT);
- }
- else {
- ptr->setAutoSize(TextField::AUTOSIZE_NONE);
- }
- }
- else {
- std::string strval = arg.to_string();
- TextField::AutoSize val = parseAutoSize(strval);
- ptr->setAutoSize(val);
- }
- }
-
- return as_value();
-}
-
-as_value
-textfield_type(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- // getter
- return ptr->typeValueName(ptr->getType());
- }
-
- // setter
- const as_value& arg = fn.arg(0);
- std::string strval = arg.to_string();
- TextField::TypeValue val = ptr->parseTypeValue(strval);
-
- IF_VERBOSE_ASCODING_ERRORS(
- if (val == TextField::typeInvalid) {
- log_aserror(_("Invalid value given to TextField.type: %s"),
strval);
- }
- );
- ptr->setType(val);
- return as_value();
-}
-
-
-as_value
-textfield_variable(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs)
- {
- // Getter
- const std::string& varName = text->getVariableName();
- // An empty variable name returns null.
- if (varName.empty()) {
- as_value null;
- null.set_null();
- return null;
- }
- return as_value(varName);
- }
-
- // Setter
- const as_value& varName = fn.arg(0);
- if (varName.is_undefined() || varName.is_null()) {
- text->set_variable_name("");
- }
- else text->set_variable_name(varName.to_string());
-
- return as_value();
-
-}
-
-
-as_value
-textfield_getDepth(const fn_call& fn)
-{
- // Unlike MovieClip.getDepth this works only for TextFields.
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- const int n = text->get_depth();
- return as_value(n);
-}
-
-as_value
-textfield_getFontList(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- LOG_ONCE(log_unimpl("TextField.getFontList()"));
-
- return as_value();
-}
-
-as_value
-textfield_getNewTextFormat(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- LOG_ONCE(log_unimpl("TextField.getNewTextFormat()"));
-
- return as_value();
-}
-
-
-// This is a bit of a messy compromise. We call the TextFormat ctor (this
-// is necessary because prototype properties are not attached until that is
-// done). Then we access the relay object directly. This is because there
-// aren't enough known parameters to the TextFormat constructor to handle
-// all the values, and it isn't tested properly.
-as_value
-textfield_getTextFormat(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- Global_as& gl = getGlobal(fn);
- as_function* ctor = gl.getMember(NSV::CLASS_TEXT_FORMAT).to_function();
-
- if (!ctor) return as_value();
-
- fn_call::Args args;
- as_object* textformat = constructInstance(*ctor, fn.env(), args);
- TextFormat_as* tf;
-
- if (!isNativeType(textformat, tf)) {
- return as_value();
- }
-
- tf->alignSet(text->getTextAlignment());
- tf->sizeSet(text->getFontHeight());
- tf->indentSet(text->getIndent());
- tf->blockIndentSet(text->getBlockIndent());
- tf->leadingSet(text->getLeading());
- tf->leftMarginSet(text->getLeftMargin());
- tf->rightMarginSet(text->getRightMargin());
- tf->colorSet(text->getTextColor());
- tf->underlinedSet(text->getUnderlined());
-
- const Font* font = text->getFont();
- if (font)
- {
- tf->fontSet(font->name());
- tf->italicSet(font->isItalic());
- tf->boldSet(font->isBold());
- }
-
- // TODO: add font color and some more
-
- LOG_ONCE(
- log_unimpl("TextField.getTextFormat() discards url, target, "
- "tabStops, bullet and display")
- );
-
- return as_value(textformat);
-}
-
-as_value
-textfield_setTextFormat(const fn_call& fn)
-{
-
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( ! fn.nargs )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror("TextField.setTextFormat(%s) : %s", ss.str(),
- _("missing arg"))
- );
- return as_value();
- }
- else if ( fn.nargs > 2 )
- {
- std::stringstream ss; fn.dump_args(ss);
- log_debug("TextField.setTextFormat(%s) : args past the first are "
- "unhandled by Gnash", ss.str());
- }
-
- TextFormat_as* tf;
- if (!isNativeType(fn.arg(0).to_object(getGlobal(fn)), tf)) {
-
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror("TextField.setTextFormat(%s) : %s", ss.str(),
- _("first argument is not a TextFormat"))
- );
- return as_value();
- }
-
- if (isAS3(fn)) {
- // TODO: current font finding assumes we have a parent, which isn't
- // necessarily the case in AS3. It seems the AS2 implementation is
- // wrong anyway.
- log_unimpl("fonts in AS3 TextField.setTextFormat");
- return as_value();
- }
-
- if (tf->font())
- {
- const std::string& fontName = *tf->font();
- if ( ! fontName.empty() )
- {
- bool bold = tf->bold() ? *tf->bold() : false;
- bool italic = tf->italic() ? *tf->italic() : false;
-
- // NOTE: should query movie-private font lib, not global-shared one
- Movie* mi = text->get_root();
- assert(mi);
- const movie_definition* md = mi->definition();
- assert(md);
- Font* f = md->get_font(fontName, bold, italic);
- if ( ! f ) f = fontlib::get_font(fontName, bold, italic);
- text->setFont( f );
- }
- }
-
- // TODO: add font color and some more
- text->setTextFormat(*tf);
- return as_value();
-
-}
-
-as_value
-textfield_setNewTextFormat(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- LOG_ONCE( log_unimpl("TextField.setNewTextFormat(), we'll delegate "
- "to setTextFormat") );
- return textfield_setTextFormat(fn);
-}
-
-as_value
-textfield_password(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs)
- {
- // Getter
- return as_value(text->password());
- }
- // Setter
- text->password(fn.arg(0).to_bool());
- return as_value();
-}
-
-as_value
-textfield_multiline(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- // Getter
- return as_value(text->multiline());
- }
- // Setter
- text->multiline(fn.arg(0).to_bool());
- return as_value();
-}
-
-as_value
-textfield_restrict(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- // Getter
- if (text->isRestrict()) {
- return as_value(text->getRestrict());
- } else {
- as_value null;
- null.set_null();
- return null;
- }
- }
- // Setter
- text->setRestrict(fn.arg(0).to_string());
- return as_value();
-}
-
-as_value
-textfield_bottomScroll(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- LOG_ONCE(log_unimpl("TextField.bottomScroll is not complete"));
-
-
- if (!fn.nargs)
- {
- // Getter
- return as_value(1 + text->getBottomScroll());
- }
- // Setter
- //text->setBottomScroll(int(fn.arg(0).to_number())); READ-ONLY
-
- return as_value();
-}
-
-as_value
-textfield_maxhscroll(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- LOG_ONCE(log_unimpl("TextField.maxhscroll is not complete"));
-
-
- if (!fn.nargs)
- {
- // Getter
- return as_value(text->getMaxHScroll());
- }
- // Setter
- //text->setMaxHScroll(int(fn.arg(0).to_number())); READ-ONLY
-
- return as_value();
-}
-
-/// TextField.maxChars().
-//
-/// This does not limit the length of the text, but rather the
-/// number of DisplayObjects that can be entered in the TextField.
-//
-/// Returns null when the value is 0.
-as_value
-textfield_maxChars(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs)
- {
- boost::int32_t maxChars = text->maxChars();
- if (maxChars == 0)
- {
- as_value null;
- null.set_null();
- return null;
- }
- return as_value(maxChars);
- }
- // Setter
- text->maxChars(toInt(fn.arg(0)));
- return as_value();
-}
-
-as_value
-textfield_text(const fn_call& fn)
-{
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
- if (!fn.nargs)
- {
- // Getter
- //
- // FIXME: should return text without HTML tags.
- return as_value(ptr->get_text_value());
- }
-
- // Setter
- const int version = getSWFVersion(fn);
- ptr->setTextValue(
- utf8::decodeCanonicalString(fn.arg(0).to_string(), version));
-
- return as_value();
-}
-
-as_value
-textfield_htmlText(const fn_call& fn)
-{
- GNASH_REPORT_FUNCTION;
-
- TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
- if (!fn.nargs)
- {
- // Getter
- return as_value(ptr->get_htmltext_value());
- }
-
- // Setter
- const int version = getSWFVersion(fn);
-
- ptr->setHtmlTextValue(
- utf8::decodeCanonicalString(fn.arg(0).to_string(), version));
-
- return as_value();
-}
-
-/// TextField.replaceSel(newText)
-//
-/// Replaces the current selection with the new text, setting both
-/// begin and end of the selection to one after the inserted text.
-/// If an empty string is passed, SWF8 erases the selection; SWF7 and below
-/// is a no-op.
-/// If no argument is passed, this is a no-op.
-as_value
-textfield_replaceSel(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if (!fn.nargs) {
- IF_VERBOSE_ASCODING_ERRORS(
- std::ostringstream os;
- fn.dump_args(os);
- log_aserror("TextField.replaceSel(%s) requires exactly one "
- "argument", os.str());
- );
- return as_value();
- }
-
- const std::string& replace = fn.arg(0).to_string();
-
- /// Do nothing if text is empty and version less than 8.
- const int version = getSWFVersion(fn);
- if (version < 8 && replace.empty()) return as_value();
-
- text->replaceSelection(replace);
-
- return as_value();
-}
-
-as_value
-textfield_scroll(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
- UNUSED(text);
-
- if (!fn.nargs)
- {
- // Getter
- return as_value(1 + text->getScroll());
- }
- // Setter
- text->setScroll(int(fn.arg(0).to_number()) - 1);
-
- return as_value();
-}
-
-as_value
-textfield_hscroll(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- LOG_ONCE(log_unimpl("TextField._hscroll is not complete"));
-
- if (!fn.nargs)
- {
- // Getter
- return as_value(text->getHScroll());
- }
- // Setter
- text->setHScroll(int(fn.arg(0).to_number()));
-
- return as_value();
-}
-
-as_value
-textfield_maxscroll(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- LOG_ONCE(log_unimpl("TextField.maxscroll is not complete"));
-
- if (!fn.nargs) {
- // Getter
- return as_value(text->getMaxScroll());
- }
-
- return as_value();
-}
-
-as_value
-textfield_replaceText(const fn_call& fn)
-{
- using std::string;
- using std::wstring;
-
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- if ( fn.nargs < 3 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("TextField.replaceText() called with less than 3 args"));
- )
- return as_value();
- }
-
- int userEnd = toInt(fn.arg(1));
- if ( userEnd < 0 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror("TextField.replaceText(%s): negative endIndex"
- " - doing nothing", ss.str());
- );
- return as_value();
- }
-
- wstring::size_type start = toInt(fn.arg(0));
- wstring::size_type end = userEnd;
-
- int version = getSWFVersion(fn);
-
- // TODO: check if it's possible for SWF6 to use this function
- // and if it is whether to_string should be to_string
- // (affects the way undefined values are considered)
- const wstring& replacement =
- utf8::decodeCanonicalString(fn.arg(2).to_string(), version);
-
- // TODO: drop this round uf8 encoding and decoding by exposing
- // a TextField::getTextValue ?
- const wstring& subject =
- utf8::decodeCanonicalString(text->get_text_value(), version);
-
- if ( start > subject.length() )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror("TextField.replaceText(%s): beginIndex out of range"
- " - doing nothing", ss.str());
- );
- return as_value();
- }
-
-
- // TODO: use STL proper
- wstring newstring;
- if ( start ) newstring = subject.substr(0, start);
- newstring.append(replacement);
-
- if ( end > subject.length() )
- {
- //log_aserror...
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror("TextField.replaceText(%s): endIndex out of range"
- " - taking as end of string", ss.str());
- );
- }
- else
- {
- newstring.append(subject.substr(end));
- }
-
- // TODO: check if we should really be updating registered variables
- text->setTextValue(newstring);
-
- return as_value();
-}
-
-as_value
-textfield_removeTextField(const fn_call& fn)
-{
- TextField* text = ensure<IsDisplayObject<TextField> >(fn);
-
- text->removeTextField();
-
- LOG_ONCE(log_debug("TextField.removeTextField() TESTING"));
-
- return as_value();
-}
-
-
-/// This is called for 'new TextField()'
-//
-/// Note that MovieClip.createTextField must call this function (or anything
-/// that replaces it).
-//
-/// Tests in actionscript.all/TextField.as show that this constructor:
-/// 1. Adds properties to the prototype.
-/// 2. Removes array typing.
-/// 3. Removes any Relay.
-/// 4. Does not produce a DisplayObject.
-/// 5. Operates on a 'this' pointer that createTextField turns into a
-/// real TextField.
-as_value
-textfield_ctor(const fn_call& fn)
-{
-
- if (isAS3(fn)) {
- as_object* obj = ensure<ValidThis>(fn);
- SWFRect nullRect;
- obj->setDisplayObject(new TextField(obj, 0, nullRect));
- return as_value();
- }
-
- as_object* obj = ensure<ValidThis>(fn);
-
- // It's not clear why this happens. Attaching a relay would have the
- // same effect as both following statements.
- obj->setArray(false);
- obj->setRelay(0);
-
- as_object* proto = obj->get_prototype();
-
- if (proto) {
- attachPrototypeProperties(*proto);
- }
-
- as_object* ar = getGlobal(fn).createArray();
- callMethod(ar, NSV::PROP_PUSH, obj);
- obj->set_member(NSV::PROP_uLISTENERS, ar);
- return as_value();
-}
-
-
-void
-attachTextFieldInterface(as_object& o)
-{
- // SWF6 or higher
- const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
-
- VM& vm = getVM(o);
- o.init_member("replaceSel", vm.getNative(104, 100), swf6Flags);
- o.init_member("getTextFormat", vm.getNative(104, 101), swf6Flags);
- o.init_member("setTextFormat", vm.getNative(104, 102), swf6Flags);
- o.init_member("removeTextField", vm.getNative(104, 103), swf6Flags);
- o.init_member("getNewTextFormat", vm.getNative(104, 104), swf6Flags);
- o.init_member("setNewTextFormat",vm.getNative(104, 105), swf6Flags);
- o.init_member("getDepth", vm.getNative(104, 106), swf6Flags);
-
- // SWF7 or higher
- const int swf7Flags = as_object::DefaultFlags | PropFlags::onlySWF7Up;
-
- o.init_member("replaceText",vm.getNative(104, 107), swf7Flags);
-
- // TextField is an AsBroadcaster
- AsBroadcaster::initialize(o);
-
- // Finally ASSetPropFlags is called on the prototype.
- Global_as& gl = getGlobal(o);
- as_object* null = 0;
- callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, &o, null, 131);
-}
-
-void
-attachTextFieldStaticMembers(as_object& o)
-{
- // SWF6 or higher
- const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
- VM& vm = getVM(o);
- o.init_member("getFontList", vm.getNative(104, 201), swf6Flags);
-}
-
-
-/// Return autoSize value as a string
-//
-/// @param val AutoSize value
-/// @return a C-string representation of the autoSize value.
-/// The return is *never* NULL.
-const char*
-autoSizeValueName(TextField::AutoSize val)
-{
- switch (val) {
- case TextField::AUTOSIZE_LEFT:
- return "left";
- case TextField::AUTOSIZE_RIGHT:
- return "right";
- case TextField::AUTOSIZE_CENTER:
- return "center";
- case TextField::AUTOSIZE_NONE:
- default:
- return "none";
- }
-
-}
-
-TextField::AutoSize
-parseAutoSize(const std::string& val)
-{
- StringNoCaseEqual cmp;
-
- if (cmp(val, "left")) {
- return TextField::AUTOSIZE_LEFT;
- }
- if (cmp(val, "right")) {
- return TextField::AUTOSIZE_RIGHT;
- }
- if (cmp(val, "center")) {
- return TextField::AUTOSIZE_CENTER;
- }
- return TextField::AUTOSIZE_NONE;
-}
-
-
-} // anonymous namespace
} // namespace gnash
=== modified file 'libcore/TextField.h'
--- a/libcore/TextField.h 2010-01-25 11:13:55 +0000
+++ b/libcore/TextField.h 2010-02-15 14:55:30 +0000
@@ -838,16 +838,6 @@
};
-/// Native function to create a plain object with TextField properties
-//
-/// This function calls the TextField constructor.
-as_object* createTextFieldObject(Global_as& gl);
-
-/// Initialize the global TextField class
-void textfield_class_init(as_object& global, const ObjectURI& uri);
-
-void registerTextFieldNative(as_object& global);
-
} // namespace gnash
#endif
=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2010-01-11 06:41:38 +0000
+++ b/libcore/asobj/Globals.cpp 2010-02-15 14:55:30 +0000
@@ -67,6 +67,7 @@
#include "flash/net/NetStream_as.h"
#include "flash/system/System_as.h"
#include "flash/text/TextSnapshot_as.h"
+#include "flash/text/TextField_as.h"
#include "flash/text/TextFieldAutoSize_as.h"
#include "flash/text/Font_as.h"
#include "flash/text/FontStyle_as.h"
@@ -92,7 +93,6 @@
#include "Timers.h"
#include "URL.h"
#include "builtin_function.h"
-#include "TextField.h"
#include "rc.h"
#include "ClassHierarchy.h"
#include "namedStrings.h"
=== modified file 'libcore/asobj/flash/text/TextField_as.cpp'
--- a/libcore/asobj/flash/text/TextField_as.cpp 2010-01-25 18:52:20 +0000
+++ b/libcore/asobj/flash/text/TextField_as.cpp 2010-02-15 14:55:30 +0000
@@ -19,269 +19,1179 @@
#include "text/TextField_as.h"
+#include "TextField.h"
#include "log.h"
#include "fn_call.h"
#include "Global_as.h"
#include "smart_ptr.h" // for boost intrusive_ptr
#include "builtin_function.h" // need builtin_function
-#include "GnashException.h" // for ActionException
+#include "AsBroadcaster.h" // for initializing self as a broadcaster
+#include "flash/text/TextFormat_as.h"
+#include "MovieClip.h"
+#include "NativeFunction.h"
+#include "GnashNumeric.h"
+#include "Movie.h"
+#include "fontlib.h"
+#include "utf8.h"
namespace gnash {
// Forward declarations
namespace {
- as_value textfield_getCharBoundaries(const fn_call& fn);
- as_value textfield_getCharIndexAtPoint(const fn_call& fn);
- as_value textfield_getFirstCharInParagraph(const fn_call& fn);
- as_value textfield_getImageReference(const fn_call& fn);
- as_value textfield_getLineIndexAtPoint(const fn_call& fn);
- as_value textfield_getLineIndexOfChar(const fn_call& fn);
- as_value textfield_getLineLength(const fn_call& fn);
- as_value textfield_getLineMetrics(const fn_call& fn);
- as_value textfield_getLineOffset(const fn_call& fn);
- as_value textfield_getLineText(const fn_call& fn);
- as_value textfield_getParagraphLength(const fn_call& fn);
+ const char* autoSizeValueName(TextField::AutoSize val);
+ TextField::AutoSize parseAutoSize(const std::string& val);
+
+ void attachPrototypeProperties(as_object& proto);
+ void attachTextFieldStaticMembers(as_object& o);
+ void attachTextFieldInterface(as_object& o);
+
+ as_value textfield_createTextField(const fn_call& fn);
+
+ as_value textfield_variable(const fn_call& fn);
+ as_value textfield_setTextFormat(const fn_call& fn);
as_value textfield_getTextFormat(const fn_call& fn);
- as_value textfield_replaceSelectedText(const fn_call& fn);
+ as_value textfield_setNewTextFormat(const fn_call& fn);
+ as_value textfield_getNewTextFormat(const fn_call& fn);
+ as_value textfield_getDepth(const fn_call& fn);
+ as_value textfield_getFontList(const fn_call& fn);
+ as_value textfield_removeTextField(const fn_call& fn);
+ as_value textfield_replaceSel(const fn_call& fn);
as_value textfield_replaceText(const fn_call& fn);
- as_value textfield_setSelection(const fn_call& fn);
- as_value textfield_setTextFormat(const fn_call& fn);
- as_value textfield_change(const fn_call& fn);
- as_value textfield_link(const fn_call& fn);
+ as_value textfield_password(const fn_call& fn);
+ as_value textfield_ctor(const fn_call& fn);
+ as_value textfield_multiline(const fn_call& fn);
as_value textfield_scroll(const fn_call& fn);
- as_value textfield_textInput(const fn_call& fn);
- as_value textfield_ctor(const fn_call& fn);
- void attachTextFieldInterface(as_object& o);
- void attachTextFieldStaticInterface(as_object& o);
-}
-
-// extern (used by Global.cpp)
+ as_value textfield_maxscroll(const fn_call& fn);
+ as_value textfield_maxhscroll(const fn_call& fn);
+ as_value textfield_maxChars(const fn_call& fn);
+ as_value textfield_bottomScroll(const fn_call& fn);
+ as_value textfield_hscroll(const fn_call& fn);
+ as_value textfield_htmlText(const fn_call& fn);
+ as_value textfield_restrict(const fn_call& fn);
+ as_value textfield_background(const fn_call& fn);
+ as_value textfield_border(const fn_call& fn);
+ as_value textfield_backgroundColor(const fn_call& fn);
+ as_value textfield_borderColor(const fn_call& fn);
+ as_value textfield_text(const fn_call& fn);
+ as_value textfield_textColor(const fn_call& fn);
+ as_value textfield_embedFonts(const fn_call& fn);
+ as_value textfield_autoSize(const fn_call& fn);
+ as_value textfield_type(const fn_call& fn);
+ as_value textfield_wordWrap(const fn_call& fn);
+ as_value textfield_html(const fn_call& fn);
+ as_value textfield_selectable(const fn_call& fn);
+ as_value textfield_length(const fn_call& fn);
+ as_value textfield_textWidth(const fn_call& fn);
+ as_value textfield_textHeight(const fn_call& fn);
+}
+
+as_object*
+createTextFieldObject(Global_as& gl)
+{
+ as_value tf(gl.getMember(NSV::CLASS_TEXT_FIELD));
+ as_function* ctor = tf.to_function();
+ if (!ctor) return 0;
+ fn_call::Args args;
+ as_environment env(getVM(gl));
+ return constructInstance(*ctor, env, args);
+}
+
+/// This provides the prototype and static methods for TextField.
+//
+/// For SWF5 there is initially no prototype, for SWF6+ there is a
+/// limited prototype. This is changed later on instantiation of a
+/// TextField.
void
textfield_class_init(as_object& where, const ObjectURI& uri)
{
- registerBuiltinClass(where, textfield_ctor, attachTextFieldInterface,
- attachTextFieldStaticInterface, uri);
-}
+
+ Global_as& gl = getGlobal(where);
+ as_object* proto = gl.createObject();
+ as_object* cl = gl.createClass(&textfield_ctor, proto);
+
+ attachTextFieldInterface(*proto);
+ attachTextFieldStaticMembers(*cl);
+
+ where.init_member(uri, cl, as_object::DefaultFlags);
+
+ // ASSetPropFlags is called on the TextField class.
+ as_object* null = 0;
+ callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, cl, null, 131);
+}
+
+void
+registerTextFieldNative(as_object& global)
+{
+ VM& vm = getVM(global);
+ vm.registerNative(textfield_replaceSel, 104, 100);
+ vm.registerNative(textfield_getTextFormat, 104, 101);
+ vm.registerNative(textfield_setTextFormat, 104, 102);
+ vm.registerNative(textfield_removeTextField, 104, 103);
+ vm.registerNative(textfield_getNewTextFormat, 104, 104);
+ vm.registerNative(textfield_setNewTextFormat, 104, 105);
+ vm.registerNative(textfield_getDepth, 104, 106);
+ vm.registerNative(textfield_replaceText, 104, 107);
+
+ vm.registerNative(textfield_createTextField, 104, 200);
+ vm.registerNative(textfield_getFontList, 104, 201);
+}
+
namespace {
void
-attachTextFieldInterface(as_object& o)
-{
- o.init_member("getCharBoundaries",
gl.createFunction(textfield_getCharBoundaries));
- o.init_member("getCharIndexAtPoint",
gl.createFunction(textfield_getCharIndexAtPoint));
- o.init_member("getFirstCharInParagraph",
gl.createFunction(textfield_getFirstCharInParagraph));
- o.init_member("getImageReference",
gl.createFunction(textfield_getImageReference));
- o.init_member("getLineIndexAtPoint",
gl.createFunction(textfield_getLineIndexAtPoint));
- o.init_member("getLineIndexOfChar",
gl.createFunction(textfield_getLineIndexOfChar));
- o.init_member("getLineLength", gl.createFunction(textfield_getLineLength));
- o.init_member("getLineMetrics",
gl.createFunction(textfield_getLineMetrics));
- o.init_member("getLineOffset", gl.createFunction(textfield_getLineOffset));
- o.init_member("getLineText", gl.createFunction(textfield_getLineText));
- o.init_member("getParagraphLength",
gl.createFunction(textfield_getParagraphLength));
- o.init_member("getTextFormat", gl.createFunction(textfield_getTextFormat));
- o.init_member("replaceSelectedText",
gl.createFunction(textfield_replaceSelectedText));
- o.init_member("replaceText", gl.createFunction(textfield_replaceText));
- o.init_member("setSelection", gl.createFunction(textfield_setSelection));
- o.init_member("setTextFormat", gl.createFunction(textfield_setTextFormat));
- o.init_member("change", gl.createFunction(textfield_change));
- o.init_member("link", gl.createFunction(textfield_link));
- o.init_member("scroll", gl.createFunction(textfield_scroll));
- o.init_member("textInput", gl.createFunction(textfield_textInput));
-}
-
-void
-attachTextFieldStaticInterface(as_object& o)
-{
-}
-
-as_value
-textfield_getCharBoundaries(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getCharIndexAtPoint(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getFirstCharInParagraph(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getImageReference(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineIndexAtPoint(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineIndexOfChar(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineLength(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineMetrics(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineOffset(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getLineText(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_getParagraphLength(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
+attachPrototypeProperties(as_object& o)
+{
+ // SWF6 or higher
+ const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
+
+ boost::intrusive_ptr<builtin_function> getset;
+
+ // The following properties should only be attached to the prototype
+ // on first textfield creation.
+ o.init_property(NSV::PROP_TEXT_WIDTH,
+ textfield_textWidth, textfield_textWidth);
+ o.init_property(NSV::PROP_TEXT_HEIGHT,
+ textfield_textHeight, textfield_textHeight);
+
+ Global_as& gl = getGlobal(o);
+
+ getset = gl.createFunction(textfield_variable);
+ o.init_property("variable", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_background);
+ o.init_property("background", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_text);
+ o.init_property("text", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_backgroundColor);
+ o.init_property("backgroundColor", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_border);
+ o.init_property("border", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_borderColor);
+ o.init_property("borderColor", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_textColor);
+ o.init_property("textColor", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_embedFonts);
+ o.init_property("embedFonts", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_autoSize);
+ o.init_property("autoSize", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_type);
+ o.init_property("type", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_wordWrap);
+ o.init_property("wordWrap", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_html);
+ o.init_property("html", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_selectable);
+ o.init_property("selectable", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_length);
+ o.init_property("length", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_maxscroll);
+ o.init_property("maxscroll", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_maxhscroll);
+ o.init_property("maxhscroll", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_maxChars);
+ o.init_property("maxChars", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_bottomScroll);
+ o.init_property("bottomScroll", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_scroll);
+ o.init_property("scroll", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_hscroll);
+ o.init_property("hscroll", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_restrict);
+ o.init_property("restrict", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_multiline);
+ o.init_property("multiline", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_password);
+ o.init_property("password", *getset, *getset, swf6Flags);
+ getset = gl.createFunction(textfield_htmlText);
+ o.init_property("htmlText", *getset, *getset, swf6Flags);
+}
+
+
+/// This is in fact a property of MovieClip, but it is more a TextField
+/// function, as its major number (104) in the native table shows.
+as_value
+textfield_createTextField(const fn_call& fn)
+{
+ MovieClip* ptr = ensure<IsDisplayObject<MovieClip> >(fn);
+
+ // name, depth, x, y, width, height
+ if (fn.nargs < 6) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("createTextField called with %d args, "
+ "expected 6 - returning undefined"), fn.nargs);
+ );
+ return as_value();
+ }
+
+ const std::string& name = fn.arg(0).to_string();
+ const int depth = toInt(fn.arg(1));
+ const int x = toInt(fn.arg(2));
+ const int y = toInt(fn.arg(3));
+
+ int width = toInt(fn.arg(4));
+ if (width < 0) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("createTextField: negative width (%d)"
+ " - reverting sign"), width);
+ );
+ width = -width;
+ }
+
+ int height = toInt(fn.arg(5));
+ if ( height < 0 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("createTextField: negative height (%d)"
+ " - reverting sign"), height);
+ );
+ height = -height;
+ }
+ // Set textfield bounds
+ SWFRect bounds(0, 0, pixelsToTwips(width), pixelsToTwips(height));
+
+ // Tests in actionscript.all/TextField.as show that this function must:
+ // 1. Call "new _global.TextField()" (which takes care of
+ // assigning properties to the prototype).
+ // 2. Make that object into a TextField and put it on the display list.
+ as_object* obj = createTextFieldObject(getGlobal(fn));
+
+ DisplayObject* tf = new TextField(obj, ptr, bounds);
+
+ // Give name and mark as dynamic
+ tf->set_name(name);
+ tf->setDynamic();
+
+ // Set _x and _y
+ SWFMatrix matrix;
+ matrix.set_translation(pixelsToTwips(x), pixelsToTwips(y));
+ // update caches (although shouldn't be needed as we only set translation)
+ tf->setMatrix(matrix, true);
+
+ ptr->addDisplayListObject(tf, depth);
+
+ if (getSWFVersion(fn) > 7) return as_value(obj);
+ return as_value();
+}
+
+as_value
+textfield_background(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->getDrawBackground());
+ }
+ else {
+ ptr->setDrawBackground(fn.arg(0).to_bool());
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_border(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->getDrawBorder());
+ }
+ else {
+ ptr->setDrawBorder(fn.arg(0).to_bool());
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_backgroundColor(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->getBackgroundColor().toRGB());
+ }
+ else {
+ rgba newColor;
+ newColor.parseRGB(static_cast<boost::uint32_t>(toInt(fn.arg(0))));
+ ptr->setBackgroundColor(newColor);
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_borderColor(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->getBorderColor().toRGB());
+ }
+ else {
+ rgba newColor;
+ newColor.parseRGB(static_cast<boost::uint32_t>(fn.arg(0).to_number()));
+ ptr->setBorderColor(newColor);
+ }
+
+ return as_value();
+}
+
+
+as_value
+textfield_textColor(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ // Getter
+ return as_value(ptr->getTextColor().toRGB());
+ }
+
+ // Setter
+ rgba newColor;
+ newColor.parseRGB(static_cast<boost::uint32_t>(fn.arg(0).to_number()));
+ ptr->setTextColor(newColor);
+
+ return as_value();
+}
+
+as_value
+textfield_embedFonts(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ // Getter
+ return as_value(ptr->getEmbedFonts());
+ }
+
+ // Setter
+ ptr->setEmbedFonts(fn.arg(0).to_bool());
+ return as_value();
+}
+
+as_value
+textfield_wordWrap(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->doWordWrap());
+ }
+ else {
+ ptr->setWordWrap(fn.arg(0).to_bool());
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_html(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (fn.nargs == 0) {
+ return as_value(ptr->doHtml());
+ }
+ else {
+ ptr->setHtml( fn.arg(0).to_bool() );
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_selectable(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs == 0 ) // getter
+ {
+ return as_value(ptr->isSelectable());
+ }
+ else // setter
+ {
+ ptr->setSelectable( fn.arg(0).to_bool() );
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_length(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs == 0 ) // getter
+ {
+ const std::string& s = ptr->get_text_value();
+ return as_value(s.length()); // TOCHECK: utf-8 ?
+ }
+ else // setter
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Attempt to set length property of TextField %s"),
+ ptr->getTarget());
+ );
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_textHeight(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs == 0 ) // getter
+ {
+ // Return the height, in pixels, of the text as laid out.
+ // (I.e. the actual text content, not our defined
+ // bounding box.)
+ //
+ // In local coords. Verified against Macromedia Flash.
+ return as_value(twipsToPixels(ptr->getTextBoundingBox().height()));
+
+ }
+ else // setter
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Attempt to set read-only %s property of TextField "
+ "%s"), "textHeight", ptr->getTarget());
+ );
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_textWidth(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs == 0 ) // getter
+ {
+ // Return the width, in pixels, of the text as laid out.
+ // (I.e. the actual text content, not our defined
+ // bounding box.)
+ //
+ // In local coords. Verified against Macromedia Flash.
+ return as_value(twipsToPixels(ptr->getTextBoundingBox().width()));
+
+ }
+ else // setter
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Attempt to set read-only %s property of TextField %s"),
+ "textWidth", ptr->getTarget());
+ );
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_autoSize(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs == 0 ) // getter
+ {
+ return autoSizeValueName(ptr->getAutoSize());
+ }
+ else // setter
+ {
+ const as_value& arg = fn.arg(0);
+ if (arg.is_bool()) {
+ if (arg.to_bool()) {
+ // True equates to left, every other bool to none.
+ ptr->setAutoSize(TextField::AUTOSIZE_LEFT);
+ }
+ else {
+ ptr->setAutoSize(TextField::AUTOSIZE_NONE);
+ }
+ }
+ else {
+ std::string strval = arg.to_string();
+ TextField::AutoSize val = parseAutoSize(strval);
+ ptr->setAutoSize(val);
+ }
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_type(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ // getter
+ return ptr->typeValueName(ptr->getType());
+ }
+
+ // setter
+ const as_value& arg = fn.arg(0);
+ std::string strval = arg.to_string();
+ TextField::TypeValue val = ptr->parseTypeValue(strval);
+
+ IF_VERBOSE_ASCODING_ERRORS(
+ if (val == TextField::typeInvalid) {
+ log_aserror(_("Invalid value given to TextField.type: %s"),
strval);
+ }
+ );
+ ptr->setType(val);
+ return as_value();
+}
+
+
+as_value
+textfield_variable(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs)
+ {
+ // Getter
+ const std::string& varName = text->getVariableName();
+ // An empty variable name returns null.
+ if (varName.empty()) {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+ return as_value(varName);
+ }
+
+ // Setter
+ const as_value& varName = fn.arg(0);
+ if (varName.is_undefined() || varName.is_null()) {
+ text->set_variable_name("");
+ }
+ else text->set_variable_name(varName.to_string());
+
+ return as_value();
+
+}
+
+
+as_value
+textfield_getDepth(const fn_call& fn)
+{
+ // Unlike MovieClip.getDepth this works only for TextFields.
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ const int n = text->get_depth();
+ return as_value(n);
+}
+
+as_value
+textfield_getFontList(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ LOG_ONCE(log_unimpl("TextField.getFontList()"));
+
+ return as_value();
+}
+
+as_value
+textfield_getNewTextFormat(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ LOG_ONCE(log_unimpl("TextField.getNewTextFormat()"));
+
+ return as_value();
+}
+
+
+// This is a bit of a messy compromise. We call the TextFormat ctor (this
+// is necessary because prototype properties are not attached until that is
+// done). Then we access the relay object directly. This is because there
+// aren't enough known parameters to the TextFormat constructor to handle
+// all the values, and it isn't tested properly.
as_value
textfield_getTextFormat(const fn_call& fn)
{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_replaceSelectedText(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_replaceText(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_setSelection(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ Global_as& gl = getGlobal(fn);
+ as_function* ctor = gl.getMember(NSV::CLASS_TEXT_FORMAT).to_function();
+
+ if (!ctor) return as_value();
+
+ fn_call::Args args;
+ as_object* textformat = constructInstance(*ctor, fn.env(), args);
+ TextFormat_as* tf;
+
+ if (!isNativeType(textformat, tf)) {
+ return as_value();
+ }
+
+ tf->alignSet(text->getTextAlignment());
+ tf->sizeSet(text->getFontHeight());
+ tf->indentSet(text->getIndent());
+ tf->blockIndentSet(text->getBlockIndent());
+ tf->leadingSet(text->getLeading());
+ tf->leftMarginSet(text->getLeftMargin());
+ tf->rightMarginSet(text->getRightMargin());
+ tf->colorSet(text->getTextColor());
+ tf->underlinedSet(text->getUnderlined());
+
+ const Font* font = text->getFont();
+ if (font)
+ {
+ tf->fontSet(font->name());
+ tf->italicSet(font->isItalic());
+ tf->boldSet(font->isBold());
+ }
+
+ // TODO: add font color and some more
+
+ LOG_ONCE(
+ log_unimpl("TextField.getTextFormat() discards url, target, "
+ "tabStops, bullet and display")
+ );
+
+ return as_value(textformat);
}
as_value
textfield_setTextFormat(const fn_call& fn)
{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_change(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_link(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
+
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( ! fn.nargs )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror("TextField.setTextFormat(%s) : %s", ss.str(),
+ _("missing arg"))
+ );
+ return as_value();
+ }
+ else if ( fn.nargs > 2 )
+ {
+ std::stringstream ss; fn.dump_args(ss);
+ log_debug("TextField.setTextFormat(%s) : args past the first are "
+ "unhandled by Gnash", ss.str());
+ }
+
+ TextFormat_as* tf;
+ if (!isNativeType(fn.arg(0).to_object(getGlobal(fn)), tf)) {
+
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror("TextField.setTextFormat(%s) : %s", ss.str(),
+ _("first argument is not a TextFormat"))
+ );
+ return as_value();
+ }
+
+ if (isAS3(fn)) {
+ // TODO: current font finding assumes we have a parent, which isn't
+ // necessarily the case in AS3. It seems the AS2 implementation is
+ // wrong anyway.
+ log_unimpl("fonts in AS3 TextField.setTextFormat");
+ return as_value();
+ }
+
+ if (tf->font())
+ {
+ const std::string& fontName = *tf->font();
+ if ( ! fontName.empty() )
+ {
+ bool bold = tf->bold() ? *tf->bold() : false;
+ bool italic = tf->italic() ? *tf->italic() : false;
+
+ // NOTE: should query movie-private font lib, not global-shared one
+ Movie* mi = text->get_root();
+ assert(mi);
+ const movie_definition* md = mi->definition();
+ assert(md);
+ Font* f = md->get_font(fontName, bold, italic);
+ if ( ! f ) f = fontlib::get_font(fontName, bold, italic);
+ text->setFont( f );
+ }
+ }
+
+ // TODO: add font color and some more
+ text->setTextFormat(*tf);
+ return as_value();
+
+}
+
+as_value
+textfield_setNewTextFormat(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ LOG_ONCE( log_unimpl("TextField.setNewTextFormat(), we'll delegate "
+ "to setTextFormat") );
+ return textfield_setTextFormat(fn);
+}
+
+as_value
+textfield_password(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(text->password());
+ }
+ // Setter
+ text->password(fn.arg(0).to_bool());
+ return as_value();
+}
+
+as_value
+textfield_multiline(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ // Getter
+ return as_value(text->multiline());
+ }
+ // Setter
+ text->multiline(fn.arg(0).to_bool());
+ return as_value();
+}
+
+as_value
+textfield_restrict(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ // Getter
+ if (text->isRestrict()) {
+ return as_value(text->getRestrict());
+ } else {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+ }
+ // Setter
+ text->setRestrict(fn.arg(0).to_string());
+ return as_value();
+}
+
+as_value
+textfield_bottomScroll(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ LOG_ONCE(log_unimpl("TextField.bottomScroll is not complete"));
+
+
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(1 + text->getBottomScroll());
+ }
+ // Setter
+ //text->setBottomScroll(int(fn.arg(0).to_number())); READ-ONLY
+
+ return as_value();
+}
+
+as_value
+textfield_maxhscroll(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ LOG_ONCE(log_unimpl("TextField.maxhscroll is not complete"));
+
+
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(text->getMaxHScroll());
+ }
+ // Setter
+ //text->setMaxHScroll(int(fn.arg(0).to_number())); READ-ONLY
+
+ return as_value();
+}
+
+/// TextField.maxChars().
+//
+/// This does not limit the length of the text, but rather the
+/// number of DisplayObjects that can be entered in the TextField.
+//
+/// Returns null when the value is 0.
+as_value
+textfield_maxChars(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs)
+ {
+ boost::int32_t maxChars = text->maxChars();
+ if (maxChars == 0)
+ {
+ as_value null;
+ null.set_null();
+ return null;
+ }
+ return as_value(maxChars);
+ }
+ // Setter
+ text->maxChars(toInt(fn.arg(0)));
+ return as_value();
+}
+
+as_value
+textfield_text(const fn_call& fn)
+{
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+ if (!fn.nargs)
+ {
+ // Getter
+ //
+ // FIXME: should return text without HTML tags.
+ return as_value(ptr->get_text_value());
+ }
+
+ // Setter
+ const int version = getSWFVersion(fn);
+ ptr->setTextValue(
+ utf8::decodeCanonicalString(fn.arg(0).to_string(), version));
+
+ return as_value();
+}
+
+as_value
+textfield_htmlText(const fn_call& fn)
+{
+ GNASH_REPORT_FUNCTION;
+
+ TextField* ptr = ensure<IsDisplayObject<TextField> >(fn);
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(ptr->get_htmltext_value());
+ }
+
+ // Setter
+ const int version = getSWFVersion(fn);
+
+ ptr->setHtmlTextValue(
+ utf8::decodeCanonicalString(fn.arg(0).to_string(), version));
+
+ return as_value();
+}
+
+/// TextField.replaceSel(newText)
+//
+/// Replaces the current selection with the new text, setting both
+/// begin and end of the selection to one after the inserted text.
+/// If an empty string is passed, SWF8 erases the selection; SWF7 and below
+/// is a no-op.
+/// If no argument is passed, this is a no-op.
+as_value
+textfield_replaceSel(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if (!fn.nargs) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::ostringstream os;
+ fn.dump_args(os);
+ log_aserror("TextField.replaceSel(%s) requires exactly one "
+ "argument", os.str());
+ );
+ return as_value();
+ }
+
+ const std::string& replace = fn.arg(0).to_string();
+
+ /// Do nothing if text is empty and version less than 8.
+ const int version = getSWFVersion(fn);
+ if (version < 8 && replace.empty()) return as_value();
+
+ text->replaceSelection(replace);
+
return as_value();
}
as_value
textfield_scroll(const fn_call& fn)
{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_textInput(const fn_call& fn)
-{
- as_object* ptr = ensure<ValidThis>(fn);
- UNUSED(ptr);
- log_unimpl (__FUNCTION__);
- return as_value();
-}
-
-as_value
-textfield_ctor(const fn_call& /*fn*/)
-{
- return as_value();
-}
-
-} // anonymous namespace
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+ UNUSED(text);
+
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(1 + text->getScroll());
+ }
+ // Setter
+ text->setScroll(int(fn.arg(0).to_number()) - 1);
+
+ return as_value();
+}
+
+as_value
+textfield_hscroll(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ LOG_ONCE(log_unimpl("TextField._hscroll is not complete"));
+
+ if (!fn.nargs)
+ {
+ // Getter
+ return as_value(text->getHScroll());
+ }
+ // Setter
+ text->setHScroll(int(fn.arg(0).to_number()));
+
+ return as_value();
+}
+
+as_value
+textfield_maxscroll(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ LOG_ONCE(log_unimpl("TextField.maxscroll is not complete"));
+
+ if (!fn.nargs) {
+ // Getter
+ return as_value(text->getMaxScroll());
+ }
+
+ return as_value();
+}
+
+as_value
+textfield_replaceText(const fn_call& fn)
+{
+ using std::string;
+ using std::wstring;
+
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ if ( fn.nargs < 3 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("TextField.replaceText() called with less than 3 args"));
+ )
+ return as_value();
+ }
+
+ int userEnd = toInt(fn.arg(1));
+ if ( userEnd < 0 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror("TextField.replaceText(%s): negative endIndex"
+ " - doing nothing", ss.str());
+ );
+ return as_value();
+ }
+
+ wstring::size_type start = toInt(fn.arg(0));
+ wstring::size_type end = userEnd;
+
+ int version = getSWFVersion(fn);
+
+ // TODO: check if it's possible for SWF6 to use this function
+ // and if it is whether to_string should be to_string
+ // (affects the way undefined values are considered)
+ const wstring& replacement =
+ utf8::decodeCanonicalString(fn.arg(2).to_string(), version);
+
+ // TODO: drop this round uf8 encoding and decoding by exposing
+ // a TextField::getTextValue ?
+ const wstring& subject =
+ utf8::decodeCanonicalString(text->get_text_value(), version);
+
+ if ( start > subject.length() )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror("TextField.replaceText(%s): beginIndex out of range"
+ " - doing nothing", ss.str());
+ );
+ return as_value();
+ }
+
+
+ // TODO: use STL proper
+ wstring newstring;
+ if ( start ) newstring = subject.substr(0, start);
+ newstring.append(replacement);
+
+ if ( end > subject.length() )
+ {
+ //log_aserror...
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror("TextField.replaceText(%s): endIndex out of range"
+ " - taking as end of string", ss.str());
+ );
+ }
+ else
+ {
+ newstring.append(subject.substr(end));
+ }
+
+ // TODO: check if we should really be updating registered variables
+ text->setTextValue(newstring);
+
+ return as_value();
+}
+
+as_value
+textfield_removeTextField(const fn_call& fn)
+{
+ TextField* text = ensure<IsDisplayObject<TextField> >(fn);
+
+ text->removeTextField();
+
+ LOG_ONCE(log_debug("TextField.removeTextField() TESTING"));
+
+ return as_value();
+}
+
+
+/// This is called for 'new TextField()'
+//
+/// Note that MovieClip.createTextField must call this function (or anything
+/// that replaces it).
+//
+/// Tests in actionscript.all/TextField.as show that this constructor:
+/// 1. Adds properties to the prototype.
+/// 2. Removes array typing.
+/// 3. Removes any Relay.
+/// 4. Does not produce a DisplayObject.
+/// 5. Operates on a 'this' pointer that createTextField turns into a
+/// real TextField.
+as_value
+textfield_ctor(const fn_call& fn)
+{
+
+ if (isAS3(fn)) {
+ as_object* obj = ensure<ValidThis>(fn);
+ SWFRect nullRect;
+ obj->setDisplayObject(new TextField(obj, 0, nullRect));
+ return as_value();
+ }
+
+ as_object* obj = ensure<ValidThis>(fn);
+
+ // It's not clear why this happens. Attaching a relay would have the
+ // same effect as both following statements.
+ obj->setArray(false);
+ obj->setRelay(0);
+
+ as_object* proto = obj->get_prototype();
+
+ if (proto) {
+ attachPrototypeProperties(*proto);
+ }
+
+ as_object* ar = getGlobal(fn).createArray();
+ callMethod(ar, NSV::PROP_PUSH, obj);
+ obj->set_member(NSV::PROP_uLISTENERS, ar);
+ return as_value();
+}
+
+
+void
+attachTextFieldInterface(as_object& o)
+{
+ // SWF6 or higher
+ const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
+
+ VM& vm = getVM(o);
+ o.init_member("replaceSel", vm.getNative(104, 100), swf6Flags);
+ o.init_member("getTextFormat", vm.getNative(104, 101), swf6Flags);
+ o.init_member("setTextFormat", vm.getNative(104, 102), swf6Flags);
+ o.init_member("removeTextField", vm.getNative(104, 103), swf6Flags);
+ o.init_member("getNewTextFormat", vm.getNative(104, 104), swf6Flags);
+ o.init_member("setNewTextFormat",vm.getNative(104, 105), swf6Flags);
+ o.init_member("getDepth", vm.getNative(104, 106), swf6Flags);
+
+ // SWF7 or higher
+ const int swf7Flags = as_object::DefaultFlags | PropFlags::onlySWF7Up;
+
+ o.init_member("replaceText",vm.getNative(104, 107), swf7Flags);
+
+ // TextField is an AsBroadcaster
+ AsBroadcaster::initialize(o);
+
+ // Finally ASSetPropFlags is called on the prototype.
+ Global_as& gl = getGlobal(o);
+ as_object* null = 0;
+ callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, &o, null, 131);
+}
+
+void
+attachTextFieldStaticMembers(as_object& o)
+{
+ // SWF6 or higher
+ const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
+ VM& vm = getVM(o);
+ o.init_member("getFontList", vm.getNative(104, 201), swf6Flags);
+}
+
+
+/// Return autoSize value as a string
+//
+/// @param val AutoSize value
+/// @return a C-string representation of the autoSize value.
+/// The return is *never* NULL.
+const char*
+autoSizeValueName(TextField::AutoSize val)
+{
+ switch (val) {
+ case TextField::AUTOSIZE_LEFT:
+ return "left";
+ case TextField::AUTOSIZE_RIGHT:
+ return "right";
+ case TextField::AUTOSIZE_CENTER:
+ return "center";
+ case TextField::AUTOSIZE_NONE:
+ default:
+ return "none";
+ }
+
+}
+
+TextField::AutoSize
+parseAutoSize(const std::string& val)
+{
+ StringNoCaseEqual cmp;
+
+ if (cmp(val, "left")) {
+ return TextField::AUTOSIZE_LEFT;
+ }
+ if (cmp(val, "right")) {
+ return TextField::AUTOSIZE_RIGHT;
+ }
+ if (cmp(val, "center")) {
+ return TextField::AUTOSIZE_CENTER;
+ }
+ return TextField::AUTOSIZE_NONE;
+}
+
+
+} // anonymous namespace
} // gnash namespace
// local Variables:
=== modified file 'libcore/asobj/flash/text/TextField_as.h'
--- a/libcore/asobj/flash/text/TextField_as.h 2010-01-25 18:52:20 +0000
+++ b/libcore/asobj/flash/text/TextField_as.h 2010-02-15 14:55:30 +0000
@@ -17,23 +17,29 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-#ifndef GNASH_ASOBJ3_TEXTFIELD_H
-#define GNASH_ASOBJ3_TEXTFIELD_H
-
-
-
-namespace gnash {
-
-// Forward declarations
-class as_object;
-class ObjectURI;
+#ifndef GNASH_TEXTFIELD_AS_H
+#define GNASH_TEXTFIELD_AS_H
+
+namespace gnash {
+ class as_object;
+ class ObjectURI;
+ class Global_as;
+}
+
+namespace gnash {
+
+/// Native function to create a plain object with TextField properties
+//
+/// This function calls the TextField constructor.
+as_object* createTextFieldObject(Global_as& gl);
/// Initialize the global TextField class
-void textfield_class_init(as_object& where, const ObjectURI& uri);
-
-} // gnash namespace
-
-// GNASH_ASOBJ3_TEXTFIELD_H
+void textfield_class_init(as_object& global, const ObjectURI& uri);
+
+void registerTextFieldNative(as_object& global);
+
+} // namespace gnash
+
#endif
// local Variables:
=== modified file 'libcore/asobj/flash/text/text.am'
--- a/libcore/asobj/flash/text/text.am 2010-01-01 17:48:26 +0000
+++ b/libcore/asobj/flash/text/text.am 2010-02-15 14:55:30 +0000
@@ -85,7 +85,7 @@
# FIXME: already exists
if BUILD_TEXTFIELD_AS3
-# TEXT_SOURCES += asobj/flash/text/TextField_as.cpp
+TEXT_SOURCES += asobj/flash/text/TextField_as.cpp
TEXT_HEADERS += asobj/flash/text/TextField_as.h
endif
=== modified file 'libcore/swf/DefineEditTextTag.cpp'
--- a/libcore/swf/DefineEditTextTag.cpp 2010-01-01 17:48:26 +0000
+++ b/libcore/swf/DefineEditTextTag.cpp 2010-02-15 14:55:30 +0000
@@ -16,6 +16,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "DefineEditTextTag.h"
+#include "text/TextField_as.h"
#include "TextField.h"
#include "movie_definition.h"
#include "Font.h"
@@ -48,27 +49,6 @@
as_object* obj = createTextFieldObject(gl);
TextField* ch = new TextField(obj, parent, *this);
- // This gives an "instance name" to the TextField, but
- // it is not really what we need.
- //
- // First of all the VariableName ("_variableName") is
- // NOT the default name of an instance, rather it is
- // a variable associated with it and can contain path
- // information (ie. we can associate a variable in a different
- // timeline)
- //
- // We actually need to set that variable to an object which
- // is a TextField dinamic variable. The object should take
- // care of updating this TextField text when assigned to
- // and to retrive this TextField text when extracted value from.
- //
- // The DefineEditTextVariableNameTest.swf file under
- // testsuite/misc-ming.all gives an idea of the problem
- // (in particular it shows a case in which VariableName is
- // outside of TextField timeline/scope)
- //
- //ch->set_name(m_variable_name.c_str());
-
return ch;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11949: Split the gigantic TextField file into separate DisplayObject and ActionScript,
Benjamin Wolsey <=