Include program counter on action limit notification log
[gnash.git] / libcore / TextField.h
blobbac30345acf3994ca3b6e31302dc16c6d33212ab
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // 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 "LineStyle.h" // for LineStyle
29 #include "snappingrange.h"
30 #include "SWFRect.h" // for inlines
32 // Forward declarations
33 namespace gnash {
34 namespace SWF {
35 class DefineEditTextTag;
36 class TextRecord;
38 class TextFormat_as;
39 class Font;
42 namespace gnash {
44 /// An instance of a DefineEditTextTag
45 class TextField : public InteractiveObject
48 public:
50 typedef std::vector<size_t> LineStarts;
52 /// Text alignment values
53 enum TextAlignment
55 ALIGN_LEFT = 0,
56 ALIGN_RIGHT,
57 ALIGN_CENTER,
58 ALIGN_JUSTIFY
61 /// Text format display values
62 enum TextFormatDisplay
64 TEXTFORMAT_BLOCK = 0,
65 TEXTFORMAT_INLINE = 1
68 /// Possible autoSize values
69 enum AutoSize {
71 /// Do not automatically resize TextField as text grow/shrink
72 AUTOSIZE_NONE,
74 /// Expand TextField, anchor the top-left side
75 AUTOSIZE_LEFT,
77 /// Expand TextField, anchor the horizontal center
78 AUTOSIZE_CENTER,
80 /// Expand TextField, anchor the top-right side
81 AUTOSIZE_RIGHT
84 /// Possible type values
85 enum TypeValue {
87 /// Invalid value
88 typeInvalid,
90 /// Do not accept input, text is only changed by variable name
91 /// or assigning to the .text member
92 typeDynamic,
94 /// Accept user input
95 typeInput
98 /// Constructs a TextField as specified in a DefineEditText tag.
99 TextField(as_object* object, DisplayObject* parent,
100 const SWF::DefineEditTextTag& def);
102 /// Constructs a TextField with default values and the specified bounds.
104 /// Notably, the default textHeight is 12pt (240 twips).
105 /// @param parent A pointer to the DisplayObject parent of this TextField
106 /// @param bounds A SWFRect specifying the bounds of this TextField
107 TextField(as_object* object, DisplayObject* parent, const SWFRect& bounds);
110 ~TextField();
112 // TODO: should this return isSelectable() ?
113 /// Returns true for now, TextField is always "Mouse-Enabled"
114 bool mouseEnabled() const { return true; }
116 /// Returns a pointer to the topmost InteractiveObject at (x,y)
118 /// @param x x-coordinate
119 /// @param y y-coordinate
120 InteractiveObject* topmostMouseEntity(boost::int32_t x, boost::int32_t y);
122 /// Return the version of the SWF this was parsed from.
124 /// TODO: work out what this means for dynamic TextFields.
125 virtual int getDefinitionVersion() const;
127 /// This function is called as a user-input handler
128 void notifyEvent(const event_id& id);
130 const std::string& getVariableName() const
132 return _variable_name;
135 /// Set the name of a variable associated to this
136 /// TextField's displayed text.
138 /// Calling this function will override any previous
139 /// setting for the variable name.
140 ///
141 void set_variable_name(const std::string& newname);
143 /// \brief Set our text to the given string by effect of an update of a
144 /// registered variable name
146 /// This call only updates the text and is only meant to be called
147 /// by ourselves or by MovieClip when a registered TextVariable is
148 /// updated.
149 void updateText(const std::string& s);
151 /// Return value of our text.
152 std::string get_text_value() const;
154 /// Return value of our htmlText.
155 std::string get_htmltext_value() const;
157 /// Return true if text is defined
158 bool getTextDefined() const { return _textDefined; }
160 size_t getCaretIndex() const {
161 return m_cursor;
164 /// Get a std::pair of size_t with start/end of selection
166 /// Both start and end should invariably be within the
167 /// range of the text.
168 const std::pair<size_t, size_t>& getSelection() const {
169 return _selection;
172 /// Replace the current selection with the new text.
174 /// @param replace String to replace the current selection
175 void replaceSelection(const std::string& replace);
177 /// Set the current selection
179 /// @param start The index of the beginning of the selection.
180 /// @param end The index of the end of the selection.
182 /// If start is greater than end, the values are swapped, ensuring
183 /// end is never less than start.
184 void setSelection(int start, int end);
186 /// Override of DisplayObject::setWidth
188 /// TextField width currently behaves differently from MovieClip width
189 virtual void setWidth(double width);
191 /// Override of DisplayObject::setHeight
193 /// TextField height currently behaves differently from MovieClip height
194 virtual void setHeight(double height);
196 /// Draw the dynamic string.
197 virtual void display(Renderer& renderer, const Transform& xform);
199 void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
201 /// Get bounding SWFRect of this TextField
202 virtual SWFRect getBounds() const
204 return _bounds;
207 // See dox in DisplayObject.h
208 bool pointInShape(boost::int32_t x, boost::int32_t y) const;
210 /// Return true if the 'background' should be drawn
211 bool getDrawBackground() const;
213 /// Specify whether to draw the background
215 /// @param draw If true the background of this TextField will be drawn
216 void setDrawBackground(bool draw);
218 /// \brief Return color of the background
219 rgba getBackgroundColor() const;
221 /// Set color of the background
223 /// Use setDrawBackground to actually use this value.
224 /// @param col RGBA Object with color information. TextField
225 /// background will be drawn in this color
226 void setBackgroundColor(const rgba& col);
228 /// Return true if this TextField should have its border visible
229 bool getDrawBorder() const;
231 /// Specify whether to draw the border
233 /// @param draw If true the border of this TextField will be drawn
234 void setDrawBorder(bool draw);
236 /// Return color of the border
237 rgba getBorderColor() const;
239 /// Set color of the border
241 /// Use setDrawBorder to actually use this value.
242 /// @param col RGBA Object with color information. TextField border
243 /// will be drawn in this color.
244 void setBorderColor(const rgba& col);
246 /// Return color of the text
247 const rgba& getTextColor() const
249 return _textColor;
252 /// Set color of the text
254 /// @param col RGBA Object with color information. Text in this TextField
255 /// will be displayed in this color.
256 void setTextColor(const rgba& col);
258 /// \brief
259 /// Return true if this TextField should use embedded font glyphs,
260 /// false if it should use device font glyphs
261 bool getEmbedFonts() const {
262 return _embedFonts;
265 /// Get the current maxChars setting of the TextField
266 boost::int32_t maxChars() const {
267 return _maxChars;
270 /// Set the current maxChars setting of the TextField
272 /// @param max The maximum number of characters that can be
273 /// input by the user (Does not restrict Scripts)
274 void maxChars(boost::int32_t max) {
275 _maxChars = max;
278 /// Get the current multiline setting of the TextField
279 bool multiline() const {
280 return _multiline;
283 /// Set the current multiline setting of the TextField
285 /// @param b If true "Enter" key will be recognized (Does not
286 /// restrict Scripts)
287 void multiline(bool b) {
288 _multiline = b;
291 /// Get the current password setting of the TextField
292 bool password() const {
293 return _password;
296 /// Set the current password setting of the TextField
298 /// @param b If true characters in the TextField will be displayed
299 /// as (*)
300 void password(bool b) {
301 _password = b;
303 /// \brief
304 /// Set whether this TextField should use embedded font glyphs,
305 /// or use device font glyphs
307 /// @param use
308 void setEmbedFonts(bool use);
310 /// Get autoSize value
311 AutoSize getAutoSize() const
313 return _autoSize;
316 /// Return text TextAlignment
317 TextAlignment getTextAlignment();
319 /// Set autoSize value
321 /// @param val
322 /// The AutoSize to use
324 void setAutoSize(AutoSize val);
326 /// Set type (input or dynamic)
328 /// @param val
329 /// The TypeValue to use, no-op if typeInvalid.
331 void setType(TypeValue val) { if (val != typeInvalid) _type=val; }
333 /// Get type (input, dynamic or invalid)
334 TypeValue getType() const
336 return _type;
339 /// Return true if this TextField is read-only
340 bool isReadOnly() const { return _type != typeInput; }
342 /// Parse type string value
344 /// @param val
345 /// Type value as a string (one of input or dynamic)
347 /// @return an TypeValue identifier. typeInvalid if invalid.
349 static TypeValue parseTypeValue(const std::string& val);
351 /// Return type value as a string
353 /// @param val
354 /// Type value (enum)
356 /// @return a C-string representation of the type value.
357 /// The returns is *never* NULL.
359 static const char* typeValueName(TypeValue val);
361 /// \brief
362 /// Return true if text should continue to next available line
363 /// when hitting end of bounding box.
365 bool doWordWrap() const {
366 return _wordWrap;
369 /// Set wordWrap parameter
371 /// @param on
372 /// If true text hitting bounding box limits will continue
373 /// to next line.
374 /// If false, either text will be truncated or bounding box
375 /// expanded, depending on autoSize (see getAutoSize)
377 void setWordWrap(bool on);
379 /// Return true if HTML markup in text should be rendered.
380 bool doHtml() const {
381 return _html;
384 /// Set html parameter
386 /// @param on
387 /// If true HTML tags in the text will be parsed and rendered
388 void setHtml(bool on) {
389 _html = on;
392 /// Return true if the TextField text is selectable
393 bool isSelectable() const
395 return _selectable;
398 /// Set 'selectable' parameter
400 /// @param v
401 /// If true text in this TextField will be selectable
402 void setSelectable(bool v)
404 _selectable = v;
407 // See DisplayObject::isActiveTextField
408 /// Return true if the TextField text is selectable
409 virtual bool isSelectableTextField() const
411 return isSelectable();
414 /// Remove this textfield from the stage
416 /// This is to implement TextField.removeTextField, will
417 /// basically forward the request to its parent.
418 /// Eventually this and MovieClip::removeMovieClip
419 /// will be merged in a single function to be later used
420 /// also for AS3 removeChild().
422 void removeTextField();
424 /// Set our font, return previously set one.
426 /// @param newfont
427 /// Will be stored in an intrusive_ptr
429 boost::intrusive_ptr<const Font> setFont(
430 boost::intrusive_ptr<const Font> newfont);
432 const Font* getFont() { return _font.get(); }
435 boost::uint16_t getFontHeight() const
437 return _fontHeight;
440 void setFontHeight(boost::uint16_t h);
442 boost::uint16_t getLeftMargin() const
444 return _leftMargin;
447 void setLeftMargin(boost::uint16_t h);
449 boost::uint16_t getRightMargin() const
451 return _rightMargin;
454 void setRightMargin(boost::uint16_t h);
456 boost::uint16_t getIndent() const
458 return _indent;
461 void setIndent(boost::uint16_t h);
463 boost::uint16_t getBlockIndent() const
465 return _blockIndent;
468 void setBlockIndent(boost::uint16_t h);
470 TextAlignment getAlignment() const
472 return _alignment;
475 void setAlignment(TextAlignment h);
477 boost::int16_t getLeading() const
479 return _leading;
482 void setLeading(boost::int16_t h);
484 bool getUnderlined() const
486 return _underlined;
489 TextFormatDisplay getDisplay() const
491 return _display;
494 bool getBullet() const
496 return _bullet;
499 const std::vector<int>& getTabStops() const
501 return _tabStops;
504 bool isRestrict() const
506 return _restrictDefined;
509 const std::string& getRestrict() const
511 return _restrict;
514 size_t getScroll() const
516 return _scroll;
519 size_t getMaxScroll() const
521 return _maxScroll;
524 size_t getHScroll() const
526 return _hScroll;
529 size_t getMaxHScroll() const
531 return _maxHScroll;
534 size_t getBottomScroll() const
536 return _bottomScroll;
539 void setUnderlined(bool v);
540 void setTabStops(const std::vector<int>& tabStops);
541 void setBullet(bool b);
542 void setURL(std::string url);
543 void setTarget(std::string target);
544 void setRestrict(const std::string& restrict);
545 void setDisplay(TextFormatDisplay display);
546 void setScroll(size_t scroll) {
547 _scroll = scroll;
548 format_text();
550 void setMaxScroll(size_t maxScroll) {
551 _maxScroll = maxScroll;
552 format_text();
554 void setHScroll(size_t hScroll) {
555 _hScroll = hScroll;
556 format_text();
558 void setMaxHScroll(size_t maxHScroll) {
559 _maxHScroll = maxHScroll;
560 format_text();
562 void setbottomScroll(size_t bottomScroll) {
563 _bottomScroll = bottomScroll;
564 format_text();
567 /// Returns the number of the record that the cursor is in
569 size_t cursorRecord();
571 void setTextFormat(TextFormat_as& tf);
573 const SWFRect& getTextBoundingBox() const {
574 return m_text_bounding_box;
577 /// Set our text to the given string.
579 /// This function will also update any registered variable
581 void setTextValue(const std::wstring& wstr);
583 private:
585 void init();
587 /// \brief Set our text to the given string by effect of an update of a
588 /// registered variable name
590 /// This call only updates the text and is only meant to be called
591 /// by ourselves or by MovieClip when a registered TextVariable is
592 /// updated.
593 void updateText(const std::wstring& s);
595 void updateHtmlText(const std::wstring& s);
597 void insertTab(SWF::TextRecord& rec, boost::int32_t& x, float scale);
599 /// What happens when setFocus() is called on this TextField.
601 /// @return true if focus was set. A TextField can always receive focus,
602 /// so this always returns true.
603 virtual bool handleFocus();
605 /// Kill focus
606 virtual void killFocus();
608 /// Call this function when willing to invoke the onChanged event handler
609 void onChanged();
611 /// Reset our text bounding box to the given point.
612 void reset_bounding_box(boost::int32_t x, boost::int32_t y)
614 m_text_bounding_box.set_to_point(x, y);
617 /// Convert the DisplayObjects in _text into a series of
618 /// text_glyph_records to be rendered.
619 void format_text();
621 /// Move viewable lines based on m_cursor
622 void scrollLines();
624 /// Handles a new line, this will be called several times, so this
625 /// will hopefully make code cleaner
626 void newLine(boost::int32_t& x, boost::int32_t& y,
627 SWF::TextRecord& rec, int& last_space_glyph,
628 LineStarts::value_type& last_line_start_record, float div);
630 /// De-reference and do appropriate action for character iterator
631 void handleChar(std::wstring::const_iterator& it,
632 const std::wstring::const_iterator& e, boost::int32_t& x,
633 boost::int32_t& y, SWF::TextRecord& rec, int& last_code,
634 int& last_space_glyph,
635 LineStarts::value_type& last_line_start_record);
637 /// Extracts an HTML tag.
639 /// @param tag This string is filled with the extracted HTML tag.
640 /// @param attributes This is a map of attribute names and values
641 /// @param it An iterator pointing to the first DisplayObject of the
642 /// HTML tag. It is left pointing to the DisplayObject after the
643 /// closing tag or the end of the string.
644 /// @param e An iterator pointing to the end of the string.
645 /// @return Whether the tag is complete or not (i.e. whether a '>'
646 /// was found).
647 bool parseHTML(std::wstring& tag,
648 std::map<std::string, std::string>& attributes,
649 std::wstring::const_iterator& it,
650 const std::wstring::const_iterator& e,
651 bool& selfclosing) const;
653 /// Does LEFT/CENTER/RIGHT alignment on the records in
654 /// m_text_glyph_records[], starting with
655 /// last_line_start_record and going through the end of
656 /// m_text_glyph_records.
657 float align_line(TextAlignment align, int last_line_start_record, float x);
659 /// Associate a variable to the text of this DisplayObject
661 /// Setting the associated variable actually changes the
662 /// displayed text. Getting the variable would return the
663 /// displayed text.
665 /// If the given variable already exist use it to set
666 /// current text before overriding it.
668 /// Since the variable target may be undefined at time
669 /// of instantiation of this EditText DisplayObject, the
670 /// class keeps track of wheter it succeeded registering
671 /// the variable and this function will do nothing in this
672 /// case. Thus it is safe to call it multiple time, using
673 /// an as-needed policy (will be called from get_text_value and
674 /// display)
676 void registerTextVariable();
678 typedef std::pair<as_object*, ObjectURI> VariableRef;
680 /// \brief
681 /// Parse the given variable name
682 /// into sprite and a string_table::key components
684 VariableRef parseTextVariableRef(const std::string& variableName) const;
686 /// Called in display(), sets the cursor using m_cursor and _textRecords
688 /// @param renderer
689 /// @param mat
690 void show_cursor(Renderer& renderer, const SWFMatrix& mat);
692 /// The immutable definition of our TextField
694 /// This is NULL for dynamic TextFields.
695 boost::intrusive_ptr<const SWF::DefineEditTextTag> _tag;
697 /// The actual text.
699 /// Because we have to deal with non-ascii DisplayObjects (129-255), this
700 /// is a wide string; the cursor position and the position within the
701 /// string are then the same, which makes manipulating the string much
702 /// easier.
703 std::wstring _text;
705 /// The html representation of our text
707 std::wstring _htmlText;
709 /// bounds of dynamic text, as laid out
710 SWFRect m_text_bounding_box;
712 typedef std::vector<SWF::TextRecord> TextRecords;
713 TextRecords _textRecords;
715 std::vector<size_t> _recordStarts;
717 TextRecords _displayRecords;
719 std::string _url;
720 std::string _target;
721 std::string _restrict;
722 std::set<wchar_t> _restrictedchars;
723 TextFormatDisplay _display;
724 std::vector<int> _tabStops;
725 LineStarts _line_starts;
727 /// The text variable name
729 /// This is stored here, and not just in the definition,
730 /// because it can be changed programmatically, by setting
731 /// 'TextFields.variable'
732 std::string _variable_name;
734 rgba _backgroundColor;
736 rgba _borderColor;
738 rgba _textColor;
740 TextAlignment _alignment;
742 boost::intrusive_ptr<const Font> _font;
743 size_t m_cursor;
744 size_t _glyphcount;
745 size_t _scroll;
746 size_t _maxScroll;
747 size_t _hScroll;
748 size_t _maxHScroll;
749 size_t _bottomScroll;
750 size_t _linesindisplay;
752 /// Corresponds to the maxChars property.
753 size_t _maxChars;
755 AutoSize _autoSize;
757 TypeValue _type;
759 /// Area in which the text is drawn.
761 /// This area encloses all the text, can be automatically
762 /// extended to fit text or hide text overflowing it.
763 /// See the setAutoSize() method to change that.
765 SWFRect _bounds;
767 /// Represents the selected part of the text. The second element must
768 /// never be less than the first.
769 std::pair<size_t, size_t> _selection;
771 boost::int16_t _leading;
772 boost::uint16_t _indent;
774 /// Indentation for every line (including the ones created by
775 /// effect of a word-wrap.
776 boost::uint16_t _blockIndent;
778 boost::uint16_t _leftMargin;
780 boost::uint16_t _rightMargin;
782 boost::uint16_t _fontHeight;
784 /// This flag will be true as soon as the TextField
785 /// is assigned a text value. Only way to be false is
786 /// when definition has the hasText flag set to false
787 /// and no actionscript added text.
788 bool _textDefined;
790 bool _restrictDefined;
791 bool _underlined;
792 bool _bullet;
794 bool m_has_focus;
797 /// Corresponds to the multiline property.
798 bool _multiline;
800 /// Corresponds to the password property.
801 bool _password;
803 /// The flag keeping status of TextVariable registration
805 /// It will be set to true if there's no need to register
806 /// a text variable (ie. non-specified in the SWF)
808 bool _text_variable_registered;
810 bool _drawBackground;
812 bool _drawBorder;
814 bool _embedFonts;
816 bool _wordWrap;
818 bool _html;
820 bool _selectable;
824 } // namespace gnash
826 #endif