Make automated FSCommand invocation tests show player-side output.
[gnash.git] / libcore / TextField.h
blob6544cc0cf0467bd1c4d978e500331a3f7b92ca86
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef GNASH_TEXTFIELD_H
20 #define GNASH_TEXTFIELD_H
22 #include <boost/intrusive_ptr.hpp>
23 #include <map>
24 #include <string>
25 #include <vector>
27 #include "InteractiveObject.h" // for inheritance
28 #include "snappingrange.h"
29 #include "SWFRect.h" // for inlines
30 #include "GnashKey.h"
31 #include "RGBA.h" // for rgba
33 // Forward declarations
34 namespace gnash {
35 namespace SWF {
36 class DefineEditTextTag;
37 class TextRecord;
39 class TextFormat_as;
40 class Font;
43 #ifdef __ANDROID__
44 namespace std {
45 typedef basic_string
46 <wchar_t
47 ,std::char_traits<wchar_t>
48 ,std::allocator<wchar_t> >
49 wstring;
51 #endif
53 namespace gnash {
55 /// An instance of a DefineEditTextTag
56 class DSOTEXPORT TextField : public InteractiveObject
59 public:
61 typedef std::vector<size_t> LineStarts;
63 /// Text alignment values
64 enum TextAlignment
66 ALIGN_LEFT = 0,
67 ALIGN_RIGHT,
68 ALIGN_CENTER,
69 ALIGN_JUSTIFY
72 /// Text format display values
73 enum TextFormatDisplay
75 TEXTFORMAT_BLOCK = 0,
76 TEXTFORMAT_INLINE = 1
79 /// Possible autoSize values
80 enum AutoSize {
82 /// Do not automatically resize TextField as text grow/shrink
83 AUTOSIZE_NONE,
85 /// Expand TextField, anchor the top-left side
86 AUTOSIZE_LEFT,
88 /// Expand TextField, anchor the horizontal center
89 AUTOSIZE_CENTER,
91 /// Expand TextField, anchor the top-right side
92 AUTOSIZE_RIGHT
95 /// Possible type values
96 enum TypeValue {
98 /// Invalid value
99 typeInvalid,
101 /// Do not accept input, text is only changed by variable name
102 /// or assigning to the .text member
103 typeDynamic,
105 /// Accept user input
106 typeInput
109 /// Constructs a TextField as specified in a DefineEditText tag.
110 TextField(as_object* object, DisplayObject* parent,
111 const SWF::DefineEditTextTag& def);
113 /// Constructs a TextField with default values and the specified bounds.
115 /// Notably, the default textHeight is 12pt (240 twips).
116 /// @param parent A pointer to the DisplayObject parent of this TextField
117 /// @param bounds A SWFRect specifying the bounds of this TextField
118 TextField(as_object* object, DisplayObject* parent, SWFRect bounds);
121 ~TextField();
123 // TODO: should this return isSelectable() ?
124 /// Returns true for now, TextField is always "Mouse-Enabled"
125 bool mouseEnabled() const { return true; }
127 /// Returns a pointer to the topmost InteractiveObject at (x,y)
129 /// @param x x-coordinate
130 /// @param y y-coordinate
131 InteractiveObject* topmostMouseEntity(std::int32_t x, std::int32_t y);
133 /// Return the version of the SWF this was parsed from.
135 /// TODO: work out what this means for dynamic TextFields.
136 virtual int getDefinitionVersion() const;
138 /// This function is called as a user-input handler
139 void mouseEvent(const event_id& id);
141 /// Handle user input from a key press.
142 void keyInput(key::code k);
144 const std::string& getVariableName() const
146 return _variable_name;
149 /// Set the name of a variable associated to this
150 /// TextField's displayed text.
152 /// Calling this function will override any previous
153 /// setting for the variable name.
154 ///
155 void set_variable_name(const std::string& newname);
157 /// \brief Set our text to the given string by effect of an update of a
158 /// registered variable name
160 /// This call only updates the text and is only meant to be called
161 /// by ourselves or by MovieClip when a registered TextVariable is
162 /// updated.
163 void updateText(const std::string& s);
165 /// Return value of our text.
166 std::string get_text_value() const;
168 /// Return value of our htmlText.
169 std::string get_htmltext_value() const;
171 /// Return true if text is defined
172 bool getTextDefined() const { return _textDefined; }
174 size_t getCaretIndex() const {
175 return m_cursor;
178 /// Get a std::pair of size_t with start/end of selection
180 /// Both start and end should invariably be within the
181 /// range of the text.
182 const std::pair<size_t, size_t>& getSelection() const {
183 return _selection;
186 /// Replace the current selection with the new text.
188 /// @param replace String to replace the current selection
189 void replaceSelection(const std::string& replace);
191 /// Set the current selection
193 /// @param start The index of the beginning of the selection.
194 /// @param end The index of the end of the selection.
196 /// If start is greater than end, the values are swapped, ensuring
197 /// end is never less than start.
198 void setSelection(int start, int end);
200 /// Override of DisplayObject::setWidth
202 /// TextField width currently behaves differently from MovieClip width
203 virtual void setWidth(double width);
205 /// Override of DisplayObject::setHeight
207 /// TextField height currently behaves differently from MovieClip height
208 virtual void setHeight(double height);
210 /// Draw the dynamic string.
211 virtual void display(Renderer& renderer, const Transform& xform);
213 void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
215 /// Get bounding SWFRect of this TextField
216 virtual SWFRect getBounds() const
218 return _bounds;
221 // See dox in DisplayObject.h
222 bool pointInShape(std::int32_t x, std::int32_t y) const;
224 /// Return true if the 'background' should be drawn
225 bool getDrawBackground() const;
227 /// Specify whether to draw the background
229 /// @param draw If true the background of this TextField will be drawn
230 void setDrawBackground(bool draw);
232 /// \brief Return color of the background
233 rgba getBackgroundColor() const;
235 /// Set color of the background
237 /// Use setDrawBackground to actually use this value.
238 /// @param col RGBA Object with color information. TextField
239 /// background will be drawn in this color
240 void setBackgroundColor(const rgba& col);
242 /// Return true if this TextField should have its border visible
243 bool getDrawBorder() const;
245 /// Specify whether to draw the border
247 /// @param draw If true the border of this TextField will be drawn
248 void setDrawBorder(bool draw);
250 /// Return color of the border
251 rgba getBorderColor() const;
253 /// Set color of the border
255 /// Use setDrawBorder to actually use this value.
256 /// @param col RGBA Object with color information. TextField border
257 /// will be drawn in this color.
258 void setBorderColor(const rgba& col);
260 /// Return color of the text
261 const rgba& getTextColor() const
263 return _textColor;
266 /// Set color of the text
268 /// @param col RGBA Object with color information. Text in this TextField
269 /// will be displayed in this color.
270 void setTextColor(const rgba& col);
272 /// \brief
273 /// Return true if this TextField should use embedded font glyphs,
274 /// false if it should use device font glyphs
275 bool getEmbedFonts() const {
276 return _embedFonts;
279 /// Get the current maxChars setting of the TextField
280 std::int32_t maxChars() const {
281 return _maxChars;
284 /// Set the current maxChars setting of the TextField
286 /// @param max The maximum number of characters that can be
287 /// input by the user (Does not restrict Scripts)
288 void maxChars(std::int32_t max) {
289 _maxChars = max;
292 /// Get the current multiline setting of the TextField
293 bool multiline() const {
294 return _multiline;
297 /// Set the current multiline setting of the TextField
299 /// @param b If true "Enter" key will be recognized (Does not
300 /// restrict Scripts)
301 void multiline(bool b) {
302 _multiline = b;
305 /// Get the current password setting of the TextField
306 bool password() const {
307 return _password;
310 /// Set the current password setting of the TextField
312 /// @param b If true characters in the TextField will be displayed
313 /// as (*)
314 void password(bool b) {
315 _password = b;
317 /// \brief
318 /// Set whether this TextField should use embedded font glyphs,
319 /// or use device font glyphs
321 /// @param use
322 void setEmbedFonts(bool use);
324 /// Get autoSize value
325 AutoSize getAutoSize() const
327 return _autoSize;
330 /// Return text TextAlignment
331 TextAlignment getTextAlignment();
333 /// Set autoSize value
335 /// @param val
336 /// The AutoSize to use
338 void setAutoSize(AutoSize val);
340 /// Set type (input or dynamic)
342 /// @param val
343 /// The TypeValue to use, no-op if typeInvalid.
345 void setType(TypeValue val) { if (val != typeInvalid) _type=val; }
347 /// Get type (input, dynamic or invalid)
348 TypeValue getType() const
350 return _type;
353 /// Return true if this TextField is read-only
354 bool isReadOnly() const { return _type != typeInput; }
356 /// Parse type string value
358 /// @param val
359 /// Type value as a string (one of input or dynamic)
361 /// @return an TypeValue identifier. typeInvalid if invalid.
363 static TypeValue parseTypeValue(const std::string& val);
365 /// Return type value as a string
367 /// @param val
368 /// Type value (enum)
370 /// @return a C-string representation of the type value.
371 /// The returns is *never* NULL.
373 static const char* typeValueName(TypeValue val);
375 /// \brief
376 /// Return true if text should continue to next available line
377 /// when hitting end of bounding box.
379 bool doWordWrap() const {
380 return _wordWrap;
383 /// Set wordWrap parameter
385 /// @param on
386 /// If true text hitting bounding box limits will continue
387 /// to next line.
388 /// If false, either text will be truncated or bounding box
389 /// expanded, depending on autoSize (see getAutoSize)
391 void setWordWrap(bool on);
393 /// Return true if HTML markup in text should be rendered.
394 bool doHtml() const {
395 return _html;
398 /// Set html parameter
400 /// @param on
401 /// If true HTML tags in the text will be parsed and rendered
402 void setHtml(bool on) {
403 _html = on;
406 /// Return true if the TextField text is selectable
407 bool isSelectable() const
409 return _selectable;
412 /// Set 'selectable' parameter
414 /// @param v
415 /// If true text in this TextField will be selectable
416 void setSelectable(bool v)
418 _selectable = v;
421 // See DisplayObject::isActiveTextField
422 /// Return true if the TextField text is selectable
423 virtual bool isSelectableTextField() const
425 return isSelectable();
428 /// Remove this textfield from the stage
430 /// This is to implement TextField.removeTextField, will
431 /// basically forward the request to its parent.
432 /// Eventually this and MovieClip::removeMovieClip
433 /// will be merged in a single function to be later used
434 /// also for AS3 removeChild().
436 void removeTextField();
438 /// Set our font, return previously set one.
440 /// @param newfont
441 /// Will be stored in an intrusive_ptr
443 boost::intrusive_ptr<const Font> setFont(
444 boost::intrusive_ptr<const Font> newfont);
446 const Font* getFont() { return _font.get(); }
449 std::uint16_t getFontHeight() const
451 return _fontHeight;
454 void setFontHeight(std::uint16_t h);
456 std::uint16_t getLeftMargin() const
458 return _leftMargin;
461 void setLeftMargin(std::uint16_t h);
463 std::uint16_t getRightMargin() const
465 return _rightMargin;
468 void setRightMargin(std::uint16_t h);
470 std::uint16_t getIndent() const
472 return _indent;
475 void setIndent(std::uint16_t h);
477 std::uint16_t getBlockIndent() const
479 return _blockIndent;
482 void setBlockIndent(std::uint16_t h);
484 TextAlignment getAlignment() const
486 return _alignment;
489 void setAlignment(TextAlignment h);
491 std::int16_t getLeading() const
493 return _leading;
496 void setLeading(std::int16_t h);
498 bool getUnderlined() const
500 return _underlined;
503 TextFormatDisplay getDisplay() const
505 return _display;
508 bool getBullet() const
510 return _bullet;
513 const std::vector<int>& getTabStops() const
515 return _tabStops;
518 bool isRestrict() const
520 return _restrictDefined;
523 const std::string& getRestrict() const
525 return _restrict;
528 size_t getScroll() const
530 return _scroll;
533 size_t getMaxScroll() const
535 return _maxScroll;
538 size_t getHScroll() const
540 return _hScroll;
543 size_t getMaxHScroll() const
545 return _maxHScroll;
548 size_t getBottomScroll() const
550 return _bottomScroll;
553 void setUnderlined(bool v);
554 void setTabStops(const std::vector<int>& tabStops);
555 void setBullet(bool b);
556 void setURL(std::string url);
557 void setTarget(std::string target);
558 void setRestrict(const std::string& restrict);
559 void setDisplay(TextFormatDisplay display);
560 void setScroll(size_t scroll) {
561 _scroll = scroll;
562 format_text();
564 void setMaxScroll(size_t maxScroll) {
565 _maxScroll = maxScroll;
566 format_text();
568 void setHScroll(size_t hScroll) {
569 _hScroll = hScroll;
570 format_text();
572 void setMaxHScroll(size_t maxHScroll) {
573 _maxHScroll = maxHScroll;
574 format_text();
576 void setbottomScroll(size_t bottomScroll) {
577 _bottomScroll = bottomScroll;
578 format_text();
581 /// Returns the number of the record that the cursor is in
583 size_t cursorRecord();
585 void setTextFormat(TextFormat_as& tf);
587 const SWFRect& getTextBoundingBox() const {
588 return m_text_bounding_box;
591 /// Set our text to the given string.
593 /// This function will also update any registered variable
595 void setTextValue(const std::wstring& wstr);
597 private:
599 void init();
601 /// \brief Set our text to the given string by effect of an update of a
602 /// registered variable name
604 /// This call only updates the text and is only meant to be called
605 /// by ourselves or by MovieClip when a registered TextVariable is
606 /// updated.
607 void updateText(const std::wstring& s);
609 void updateHtmlText(const std::wstring& s);
611 void insertTab(SWF::TextRecord& rec, std::int32_t& x, float scale);
613 /// What happens when setFocus() is called on this TextField.
615 /// @return true if focus was set. A TextField can always receive focus,
616 /// so this always returns true.
617 virtual bool handleFocus();
619 /// Kill focus
620 virtual void killFocus();
622 /// Call this function when willing to invoke the onChanged event handler
623 void onChanged();
625 /// Reset our text bounding box to the given point.
626 void reset_bounding_box(std::int32_t x, std::int32_t y)
628 m_text_bounding_box.set_to_point(x, y);
631 /// Convert the DisplayObjects in _text into a series of
632 /// text_glyph_records to be rendered.
633 void format_text();
635 /// Move viewable lines based on m_cursor
636 void scrollLines();
638 /// Handles a new line, this will be called several times, so this
639 /// will hopefully make code cleaner
640 void newLine(std::int32_t& x, std::int32_t& y,
641 SWF::TextRecord& rec, int& last_space_glyph,
642 LineStarts::value_type& last_line_start_record, float div);
644 /// De-reference and do appropriate action for character iterator
645 void handleChar(std::wstring::const_iterator& it,
646 const std::wstring::const_iterator& e, std::int32_t& x,
647 std::int32_t& y, SWF::TextRecord& rec, int& last_code,
648 int& last_space_glyph,
649 LineStarts::value_type& last_line_start_record);
651 /// Extracts an HTML tag.
653 /// @param tag This string is filled with the extracted HTML tag.
654 /// @param attributes This is a map of attribute names and values
655 /// @param it An iterator pointing to the first DisplayObject of the
656 /// HTML tag. It is left pointing to the DisplayObject after the
657 /// closing tag or the end of the string.
658 /// @param e An iterator pointing to the end of the string.
659 /// @return Whether the tag is complete or not (i.e. whether a '>'
660 /// was found).
661 bool parseHTML(std::wstring& tag,
662 std::map<std::string, std::string>& attributes,
663 std::wstring::const_iterator& it,
664 const std::wstring::const_iterator& e,
665 bool& selfclosing) const;
667 /// Does LEFT/CENTER/RIGHT alignment on the records in
668 /// m_text_glyph_records[], starting with
669 /// last_line_start_record and going through the end of
670 /// m_text_glyph_records.
671 float align_line(TextAlignment align, int last_line_start_record, float x);
673 /// Associate a variable to the text of this DisplayObject
675 /// Setting the associated variable actually changes the
676 /// displayed text. Getting the variable would return the
677 /// displayed text.
679 /// If the given variable already exist use it to set
680 /// current text before overriding it.
682 /// Since the variable target may be undefined at time
683 /// of instantiation of this EditText DisplayObject, the
684 /// class keeps track of wheter it succeeded registering
685 /// the variable and this function will do nothing in this
686 /// case. Thus it is safe to call it multiple time, using
687 /// an as-needed policy (will be called from get_text_value and
688 /// display)
690 void registerTextVariable();
692 typedef std::pair<as_object*, ObjectURI> VariableRef;
694 /// \brief
695 /// Parse the given variable name
696 /// into sprite and a string_table::key components
698 VariableRef parseTextVariableRef(const std::string& variableName) const;
700 /// Called in display(), sets the cursor using m_cursor and _textRecords
702 /// @param renderer
703 /// @param mat
704 void show_cursor(Renderer& renderer, const SWFMatrix& mat);
706 /// The immutable definition of our TextField
708 /// This is NULL for dynamic TextFields.
709 boost::intrusive_ptr<const SWF::DefineEditTextTag> _tag;
711 /// The actual text.
713 /// Because we have to deal with non-ascii DisplayObjects (129-255), this
714 /// is a wide string; the cursor position and the position within the
715 /// string are then the same, which makes manipulating the string much
716 /// easier.
717 std::wstring _text;
719 /// The html representation of our text
721 std::wstring _htmlText;
723 /// bounds of dynamic text, as laid out
724 SWFRect m_text_bounding_box;
726 typedef std::vector<SWF::TextRecord> TextRecords;
727 TextRecords _textRecords;
729 std::vector<size_t> _recordStarts;
731 TextRecords _displayRecords;
733 std::string _url;
734 std::string _target;
735 std::string _restrict;
736 std::set<wchar_t> _restrictedchars;
737 TextFormatDisplay _display;
738 std::vector<int> _tabStops;
739 LineStarts _line_starts;
741 /// The text variable name
743 /// This is stored here, and not just in the definition,
744 /// because it can be changed programmatically, by setting
745 /// 'TextFields.variable'
746 std::string _variable_name;
748 rgba _backgroundColor;
750 rgba _borderColor;
752 rgba _textColor;
754 TextAlignment _alignment;
756 boost::intrusive_ptr<const Font> _font;
757 size_t m_cursor;
758 size_t _glyphcount;
759 size_t _scroll;
760 size_t _maxScroll;
761 size_t _hScroll;
762 size_t _maxHScroll;
763 size_t _bottomScroll;
764 size_t _linesindisplay;
766 /// Corresponds to the maxChars property.
767 size_t _maxChars;
769 AutoSize _autoSize;
771 TypeValue _type;
773 /// Area in which the text is drawn.
775 /// This area encloses all the text, can be automatically
776 /// extended to fit text or hide text overflowing it.
777 /// See the setAutoSize() method to change that.
779 SWFRect _bounds;
781 /// Represents the selected part of the text. The second element must
782 /// never be less than the first.
783 std::pair<size_t, size_t> _selection;
785 std::int16_t _leading;
786 std::uint16_t _indent;
788 /// Indentation for every line (including the ones created by
789 /// effect of a word-wrap.
790 std::uint16_t _blockIndent;
792 std::uint16_t _leftMargin;
794 std::uint16_t _rightMargin;
796 std::uint16_t _fontHeight;
798 /// This flag will be true as soon as the TextField
799 /// is assigned a text value. Only way to be false is
800 /// when definition has the hasText flag set to false
801 /// and no actionscript added text.
802 bool _textDefined;
804 bool _restrictDefined;
805 bool _underlined;
806 bool _bullet;
808 bool m_has_focus;
811 /// Corresponds to the multiline property.
812 bool _multiline;
814 /// Corresponds to the password property.
815 bool _password;
817 /// The flag keeping status of TextVariable registration
819 /// It will be set to true if there's no need to register
820 /// a text variable (ie. non-specified in the SWF)
822 bool _text_variable_registered;
824 bool _drawBackground;
826 bool _drawBorder;
828 bool _embedFonts;
830 bool _wordWrap;
832 bool _html;
834 bool _selectable;
838 } // namespace gnash
840 #endif