avm1: Implement TextField.html
This commit is contained in:
parent
d97a515330
commit
b40f9d4c1a
|
@ -6,7 +6,6 @@ use crate::avm1::return_value::ReturnValue;
|
|||
use crate::avm1::{Avm1, Object, ScriptObject, TObject, UpdateContext, Value};
|
||||
use crate::display_object::{AutoSizeMode, EditText, TDisplayObject};
|
||||
use crate::html::TextFormat;
|
||||
use crate::xml::XMLDocument;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
/// Implements `TextField`
|
||||
|
@ -61,23 +60,23 @@ pub fn get_html<'gc>(
|
|||
_args: &[Value<'gc>],
|
||||
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
||||
if let Some(display_object) = this.as_display_object() {
|
||||
if let Some(_text_field) = display_object.as_edit_text() {
|
||||
return Ok(true.into());
|
||||
if let Some(text_field) = display_object.as_edit_text() {
|
||||
return Ok(text_field.is_html().into());
|
||||
}
|
||||
}
|
||||
Ok(Value::Undefined.into())
|
||||
}
|
||||
|
||||
pub fn set_html<'gc>(
|
||||
_avm: &mut Avm1<'gc>,
|
||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
avm: &mut Avm1<'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
||||
if let Some(display_object) = this.as_display_object() {
|
||||
if let Some(_text_field) = display_object.as_edit_text() {
|
||||
if let Some(_value) = args.get(0) {
|
||||
//TODO: Do something with this bool value
|
||||
if let Some(text_field) = display_object.as_edit_text() {
|
||||
if let Some(value) = args.get(0) {
|
||||
text_field.set_is_html(context, value.as_bool(avm.current_swf_version()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,17 +91,9 @@ pub fn get_html_text<'gc>(
|
|||
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
||||
if let Some(display_object) = this.as_display_object() {
|
||||
if let Some(text_field) = display_object.as_edit_text() {
|
||||
let html_tree = text_field.html_tree(context).as_node();
|
||||
let html_string_result = html_tree.into_string(&mut |_node| true);
|
||||
|
||||
if let Err(err) = &html_string_result {
|
||||
log::warn!(
|
||||
"Serialization error when reading TextField.htmlText: {}",
|
||||
err
|
||||
);
|
||||
if let Ok(text) = text_field.html_text(context) {
|
||||
return Ok(text.into());
|
||||
}
|
||||
|
||||
return Ok(html_string_result.unwrap_or_else(|_| "".to_string()).into());
|
||||
}
|
||||
}
|
||||
Ok(Value::Undefined.into())
|
||||
|
@ -115,26 +106,13 @@ pub fn set_html_text<'gc>(
|
|||
args: &[Value<'gc>],
|
||||
) -> Result<ReturnValue<'gc>, Error<'gc>> {
|
||||
if let Some(display_object) = this.as_display_object() {
|
||||
if let Some(mut text_field) = display_object.as_edit_text() {
|
||||
if let Some(value) = args.get(0) {
|
||||
let html_string = value
|
||||
.clone()
|
||||
.coerce_to_string(avm, context)?
|
||||
.into_owned()
|
||||
.replace("<sbr>", "\n")
|
||||
.replace("<br>", "\n");
|
||||
let document = XMLDocument::new(context.gc_context);
|
||||
|
||||
if let Err(err) =
|
||||
document
|
||||
.as_node()
|
||||
.replace_with_str(context.gc_context, &html_string, false)
|
||||
{
|
||||
log::warn!("Parsing error when setting TextField.htmlText: {}", err);
|
||||
}
|
||||
|
||||
text_field.set_html_tree(document, context);
|
||||
}
|
||||
if let Some(text_field) = display_object.as_edit_text() {
|
||||
let text = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_string(avm, context)?;
|
||||
let _ = text_field.set_html_text(text.into_owned(), context);
|
||||
// Changing the htmlText does NOT update variable bindings (does not call EditText::propagate_text_binding).
|
||||
}
|
||||
}
|
||||
Ok(Value::Undefined.into())
|
||||
|
|
|
@ -187,7 +187,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
|
|||
{
|
||||
let _ = binding
|
||||
.text_field
|
||||
.set_text(value.coerce_to_string(avm, context)?.into_owned(), context);
|
||||
.set_html_text(value.coerce_to_string(avm, context)?.into_owned(), context);
|
||||
}
|
||||
|
||||
let result = if obj.base.has_own_property(avm, context, name) {
|
||||
|
|
|
@ -80,6 +80,9 @@ pub struct EditTextData<'gc> {
|
|||
/// If the text field is required to use device fonts only.
|
||||
is_device_font: bool,
|
||||
|
||||
/// If the text field renders as HTML.
|
||||
is_html: bool,
|
||||
|
||||
/// The current border drawing.
|
||||
drawing: Drawing,
|
||||
|
||||
|
@ -119,6 +122,7 @@ impl<'gc> EditText<'gc> {
|
|||
) -> Self {
|
||||
let is_multiline = swf_tag.is_multiline;
|
||||
let is_word_wrap = swf_tag.is_word_wrap;
|
||||
let is_html = swf_tag.is_html;
|
||||
let document = XMLDocument::new(context.gc_context);
|
||||
let text = swf_tag.initial_text.clone().unwrap_or_default();
|
||||
let default_format = TextFormat::from_swf_tag(swf_tag.clone(), swf_movie.clone(), context);
|
||||
|
@ -126,7 +130,7 @@ impl<'gc> EditText<'gc> {
|
|||
let mut text_spans = FormatSpans::new();
|
||||
text_spans.set_default_format(default_format.clone());
|
||||
|
||||
if swf_tag.is_html {
|
||||
if is_html {
|
||||
document
|
||||
.as_node()
|
||||
.replace_with_str(context.gc_context, &text, false)
|
||||
|
@ -178,6 +182,7 @@ impl<'gc> EditText<'gc> {
|
|||
is_word_wrap,
|
||||
has_border,
|
||||
is_device_font,
|
||||
is_html,
|
||||
drawing: Drawing::new(),
|
||||
object: None,
|
||||
layout,
|
||||
|
@ -268,6 +273,51 @@ impl<'gc> EditText<'gc> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn html_text(self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<String, Error> {
|
||||
if self.is_html() {
|
||||
let html_tree = self.html_tree(context).as_node();
|
||||
let html_string_result = html_tree.into_string(&mut |_node| true);
|
||||
|
||||
if let Err(err) = &html_string_result {
|
||||
log::warn!(
|
||||
"Serialization error when reading TextField.htmlText: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
return Ok(html_string_result.unwrap_or_else(|_| "".to_string()).into());
|
||||
} else {
|
||||
// Non-HTML text fields always return plain text.
|
||||
return Ok(self.text());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_html_text(
|
||||
self,
|
||||
text: String,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
if self.is_html() {
|
||||
let html_string = text.replace("<sbr>", "\n").replace("<br>", "\n");
|
||||
let document = XMLDocument::new(context.gc_context);
|
||||
|
||||
if let Err(err) =
|
||||
document
|
||||
.as_node()
|
||||
.replace_with_str(context.gc_context, &html_string, false)
|
||||
{
|
||||
log::warn!("Parsing error when setting TextField.htmlText: {}", err);
|
||||
}
|
||||
|
||||
self.set_html_tree(document, context);
|
||||
} else {
|
||||
if let Err(err) = self.set_text(text, context) {
|
||||
log::error!("Error when setting TextField.htmlText: {}", err);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn html_tree(self, context: &mut UpdateContext<'_, 'gc, '_>) -> XMLDocument<'gc> {
|
||||
self.0.read().text_spans.raise_to_html(context.gc_context)
|
||||
}
|
||||
|
@ -282,11 +332,7 @@ impl<'gc> EditText<'gc> {
|
|||
/// In stylesheet mode, the opposite is true: text spans are an
|
||||
/// intermediate, user-facing text span APIs don't work, and the document
|
||||
/// is retained.
|
||||
pub fn set_html_tree(
|
||||
&mut self,
|
||||
doc: XMLDocument<'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) {
|
||||
pub fn set_html_tree(self, doc: XMLDocument<'gc>, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
let mut write = self.0.write(context.gc_context);
|
||||
|
||||
write.document = doc;
|
||||
|
@ -379,6 +425,14 @@ impl<'gc> EditText<'gc> {
|
|||
self.relayout(context);
|
||||
}
|
||||
|
||||
pub fn is_html(self) -> bool {
|
||||
self.0.read().is_html
|
||||
}
|
||||
|
||||
pub fn set_is_html(self, context: &mut UpdateContext<'_, 'gc, '_>, is_html: bool) {
|
||||
self.0.write(context.gc_context).is_html = is_html;
|
||||
}
|
||||
|
||||
pub fn replace_text(
|
||||
self,
|
||||
from: usize,
|
||||
|
@ -713,7 +767,7 @@ impl<'gc> EditText<'gc> {
|
|||
self.parent().unwrap(),
|
||||
&variable_path,
|
||||
) {
|
||||
let text = if avm.current_swf_version() >= 6 {
|
||||
let text = if self.0.read().is_html {
|
||||
let html_tree = self.html_tree(context).as_node();
|
||||
let html_string_result = html_tree.into_string(&mut |_node| true);
|
||||
html_string_result.unwrap_or_default()
|
||||
|
|
Loading…
Reference in New Issue