Drop the bool operator for ObjectURI, to avoid getting the kind of side-effect that...
[gnash.git] / libcore / TextField.h
blobd1a17858710ca6c8d421ae4d778a2218c006bd00
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 "InteractiveObject.h" // for inheritance
23 #include "LineStyle.h" // for LineStyle
24 #include "snappingrange.h"
25 #include "SWFRect.h" // for inlines
27 #include <boost/intrusive_ptr.hpp>
28 #include <map>
29 #include <string>
30 #include <vector>
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 void updateHtmlText(const std::string& s);
153 /// Return value of our text.
154 std::string get_text_value() const;
156 /// Return value of our htmlText.
157 std::string get_htmltext_value() const;
159 /// Return true if text is defined
160 bool getTextDefined() const { return _textDefined; }
162 size_t getCaretIndex() const {
163 return m_cursor;
166 /// Get a std::pair of size_t with start/end of selection
167 const std::pair<size_t, size_t>& getSelection() const {
168 return _selection;
171 /// Replace the current selection with the new text.
173 /// @param replace String to replace the current selection
174 void replaceSelection(const std::string& replace);
176 /// Set the current selection
178 /// @param start The index of the beginning of the selection.
179 /// @param end The index of the end of the selection.
181 /// If start is greater than end, the values are swapped, ensuring
182 /// end is never less than start.
183 void setSelection(int start, int end);
185 /// Override of DisplayObject::setWidth
187 /// TextField width currently behaves differently from MovieClip width
188 virtual void setWidth(double width);
190 /// Override of DisplayObject::setHeight
192 /// TextField height currently behaves differently from MovieClip height
193 virtual void setHeight(double height);
195 /// Draw the dynamic string.
196 virtual void display(Renderer& renderer, const Transform& xform);
198 void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
200 /// Get bounding SWFRect of this TextField
201 virtual SWFRect getBounds() const
203 return _bounds;
206 // See dox in DisplayObject.h
207 bool pointInShape(boost::int32_t x, boost::int32_t y) const;
209 /// Return true if the 'background' should be drawn
210 bool getDrawBackground() const;
212 /// Specify whether to draw the background
214 /// @param draw If true the background of this TextField will be drawn
215 void setDrawBackground(bool draw);
217 /// \brief Return color of the background
218 rgba getBackgroundColor() const;
220 /// Set color of the background
222 /// Use setDrawBackground to actually use this value.
223 /// @param col RGBA Object with color information. TextField
224 /// background will be drawn in this color
225 void setBackgroundColor(const rgba& col);
227 /// Return true if this TextField should have its border visible
228 bool getDrawBorder() const;
230 /// Specify whether to draw the border
232 /// @param draw If true the border of this TextField will be drawn
233 void setDrawBorder(bool draw);
235 /// Return color of the border
236 rgba getBorderColor() const;
238 /// Set color of the border
240 /// Use setDrawBorder to actually use this value.
241 /// @param col RGBA Object with color information. TextField border
242 /// will be drawn in this color.
243 void setBorderColor(const rgba& col);
245 /// Return color of the text
246 const rgba& getTextColor() const
248 return _textColor;
251 /// Set color of the text
253 /// @param col RGBA Object with color information. Text in this TextField
254 /// will be displayed in this color.
255 void setTextColor(const rgba& col);
257 /// \brief
258 /// Return true if this TextField should use embedded font glyphs,
259 /// false if it should use device font glyphs
260 bool getEmbedFonts() const {
261 return _embedFonts;
264 /// Get the current maxChars setting of the TextField
265 boost::int32_t maxChars() const {
266 return _maxChars;
269 /// Set the current maxChars setting of the TextField
271 /// @param max The maximum number of characters that can be
272 /// input by the user (Does not restrict Scripts)
273 void maxChars(boost::int32_t max) {
274 _maxChars = max;
277 /// Get the current multiline setting of the TextField
278 bool multiline() const {
279 return _multiline;
282 /// Set the current multiline setting of the TextField
284 /// @param b If true "Enter" key will be recognized (Does not
285 /// restrict Scripts)
286 void multiline(bool b) {
287 _multiline = b;
290 /// Get the current password setting of the TextField
291 bool password() const {
292 return _password;
295 /// Set the current password setting of the TextField
297 /// @param b If true characters in the TextField will be displayed
298 /// as (*)
299 void password(bool b) {
300 _password = b;
302 /// \brief
303 /// Set whether this TextField should use embedded font glyphs,
304 /// or use device font glyphs
306 /// @param use
307 void setEmbedFonts(bool use);
309 /// Get autoSize value
310 AutoSize getAutoSize() const
312 return _autoSize;
315 /// Return text TextAlignment
316 TextAlignment getTextAlignment();
318 /// Set autoSize value
320 /// @param val
321 /// The AutoSize to use
323 void setAutoSize(AutoSize val);
325 /// Set type (input or dynamic)
327 /// @param val
328 /// The TypeValue to use, no-op if typeInvalid.
330 void setType(TypeValue val) { if (val != typeInvalid) _type=val; }
332 /// Get type (input, dynamic or invalid)
333 TypeValue getType() const
335 return _type;
338 /// Return true if this TextField is read-only
339 bool isReadOnly() const { return _type != typeInput; }
341 /// Parse type string value
343 /// @param val
344 /// Type value as a string (one of input or dynamic)
346 /// @return an TypeValue identifier. typeInvalid if invalid.
348 static TypeValue parseTypeValue(const std::string& val);
350 /// Return type value as a string
352 /// @param val
353 /// Type value (enum)
355 /// @return a C-string representation of the type value.
356 /// The returns is *never* NULL.
358 static const char* typeValueName(TypeValue val);
360 /// \brief
361 /// Return true if text should continue to next available line
362 /// when hitting end of bounding box.
364 bool doWordWrap() const {
365 return _wordWrap;
368 /// Set wordWrap parameter
370 /// @param on
371 /// If true text hitting bounding box limits will continue
372 /// to next line.
373 /// If false, either text will be truncated or bounding box
374 /// expanded, depending on autoSize (see getAutoSize)
376 void setWordWrap(bool on);
378 /// Return true if HTML markup in text should be rendered.
379 bool doHtml() const {
380 return _html;
383 /// Set html parameter
385 /// @param on
386 /// If true HTML tags in the text will be parsed and rendered
387 void setHtml(bool on) {
388 _html = on;
391 /// Return true if the TextField text is selectable
392 bool isSelectable() const
394 return _selectable;
397 /// Set 'selectable' parameter
399 /// @param v
400 /// If true text in this TextField will be selectable
401 void setSelectable(bool v)
403 _selectable = v;
406 // See DisplayObject::isActiveTextField
407 /// Return true if the TextField text is selectable
408 virtual bool isSelectableTextField() const
410 return isSelectable();
413 /// Remove this textfield from the stage
415 /// This is to implement TextField.removeTextField, will
416 /// basically forward the request to its parent.
417 /// Eventually this and MovieClip::removeMovieClip
418 /// will be merged in a single function to be later used
419 /// also for AS3 removeChild().
421 void removeTextField();
423 /// Set our font, return previously set one.
425 /// @param newfont
426 /// Will be stored in an intrusive_ptr
428 boost::intrusive_ptr<const Font> setFont(
429 boost::intrusive_ptr<const Font> newfont);
431 const Font* getFont() { return _font.get(); }
434 boost::uint16_t getFontHeight() const
436 return _fontHeight;
439 void setFontHeight(boost::uint16_t h);
441 boost::uint16_t getLeftMargin() const
443 return _leftMargin;
446 void setLeftMargin(boost::uint16_t h);
448 boost::uint16_t getRightMargin() const
450 return _rightMargin;
453 void setRightMargin(boost::uint16_t h);
455 boost::uint16_t getIndent() const
457 return _indent;
460 void setIndent(boost::uint16_t h);
462 boost::uint16_t getBlockIndent() const
464 return _blockIndent;
467 void setBlockIndent(boost::uint16_t h);
469 TextAlignment getAlignment() const
471 return _alignment;
474 void setAlignment(TextAlignment h);
476 boost::int16_t getLeading() const
478 return _leading;
481 void setLeading(boost::int16_t h);
483 bool getUnderlined() const
485 return _underlined;
488 TextFormatDisplay getDisplay() const
490 return _display;
493 bool getBullet() const
495 return _bullet;
498 const std::vector<int>& getTabStops() const
500 return _tabStops;
503 bool isRestrict() const
505 return _restrictDefined;
508 const std::string& getRestrict() const
510 return _restrict;
513 size_t getScroll() const
515 return _scroll;
518 size_t getMaxScroll() const
520 return _maxScroll;
523 size_t getHScroll() const
525 return _hScroll;
528 size_t getMaxHScroll() const
530 return _maxHScroll;
533 size_t getBottomScroll() const
535 return _bottomScroll;
538 void setUnderlined(bool v);
539 void setTabStops(const std::vector<int>& tabStops);
540 void setBullet(bool b);
541 void setURL(std::string url);
542 void setTarget(std::string target);
543 void setRestrict(const std::string& restrict);
544 void setDisplay(TextFormatDisplay display);
545 void setScroll(size_t scroll) {
546 _scroll = scroll;
547 format_text();
549 void setMaxScroll(size_t maxScroll) {
550 _maxScroll = maxScroll;
551 format_text();
553 void setHScroll(size_t hScroll) {
554 _hScroll = hScroll;
555 format_text();
557 void setMaxHScroll(size_t maxHScroll) {
558 _maxHScroll = maxHScroll;
559 format_text();
561 void setbottomScroll(size_t bottomScroll) {
562 _bottomScroll = bottomScroll;
563 format_text();
566 /// Returns the number of the record that the cursor is in
568 size_t cursorRecord();
570 void setTextFormat(TextFormat_as& tf);
572 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 /// Set our htmlText to the given string.
585 void setHtmlTextValue(const std::wstring& wstr);
587 private:
589 void init();
591 /// \brief Set our text to the given string by effect of an update of a
592 /// registered variable name
594 /// This call only updates the text and is only meant to be called
595 /// by ourselves or by MovieClip when a registered TextVariable is
596 /// updated.
597 void updateText(const std::wstring& s);
599 void updateHtmlText(const std::wstring& s);
601 void insertTab(SWF::TextRecord& rec, boost::int32_t& x, float scale);
603 /// What happens when setFocus() is called on this TextField.
605 /// @return true if focus was set. A TextField can always receive focus,
606 /// so this always returns true.
607 virtual bool handleFocus();
609 /// Kill focus
610 virtual void killFocus();
612 /// Call this function when willing to invoke the onChanged event handler
613 void onChanged();
615 /// Reset our text bounding box to the given point.
616 void reset_bounding_box(boost::int32_t x, boost::int32_t y)
618 m_text_bounding_box.set_to_point(x, y);
621 /// Convert the DisplayObjects in _text into a series of
622 /// text_glyph_records to be rendered.
623 void format_text();
625 /// Move viewable lines based on m_cursor
626 void scrollLines();
628 /// Handles a new line, this will be called several times, so this
629 /// will hopefully make code cleaner
630 void newLine(boost::int32_t& x, boost::int32_t& y,
631 SWF::TextRecord& rec, int& last_space_glyph,
632 LineStarts::value_type& last_line_start_record, float div);
634 /// De-reference and do appropriate action for character iterator
635 void handleChar(std::wstring::const_iterator& it,
636 const std::wstring::const_iterator& e, boost::int32_t& x,
637 boost::int32_t& y, SWF::TextRecord& rec, int& last_code,
638 int& last_space_glyph,
639 LineStarts::value_type& last_line_start_record);
641 /// Extracts an HTML tag.
643 /// @param tag This string is filled with the extracted HTML tag.
644 /// @param attributes This is a map of attribute names and values
645 /// @param it An iterator pointing to the first DisplayObject of the
646 /// HTML tag. It is left pointing to the DisplayObject after the
647 /// closing tag or the end of the string.
648 /// @param e An iterator pointing to the end of the string.
649 /// @return Whether the tag is complete or not (i.e. whether a '>'
650 /// was found).
651 bool parseHTML(std::wstring& tag,
652 std::map<std::string, std::string>& attributes,
653 std::wstring::const_iterator& it,
654 const std::wstring::const_iterator& e,
655 bool& selfclosing) const;
657 /// Does LEFT/CENTER/RIGHT alignment on the records in
658 /// m_text_glyph_records[], starting with
659 /// last_line_start_record and going through the end of
660 /// m_text_glyph_records.
661 float align_line(TextAlignment align, int last_line_start_record, float x);
663 /// Associate a variable to the text of this DisplayObject
665 /// Setting the associated variable actually changes the
666 /// displayed text. Getting the variable would return the
667 /// displayed text.
669 /// If the given variable already exist use it to set
670 /// current text before overriding it.
672 /// Since the variable target may be undefined at time
673 /// of instantiation of this EditText DisplayObject, the
674 /// class keeps track of wheter it succeeded registering
675 /// the variable and this function will do nothing in this
676 /// case. Thus it is safe to call it multiple time, using
677 /// an as-needed policy (will be called from get_text_value and
678 /// display)
680 void registerTextVariable();
682 typedef std::pair<as_object*, string_table::key> VariableRef;
684 /// \brief
685 /// Parse the given variable name
686 /// into sprite and a string_table::key components
688 VariableRef parseTextVariableRef(const std::string& variableName) const;
690 /// Called in display(), sets the cursor using m_cursor and _textRecords
692 /// @param renderer
693 /// @param mat
694 void show_cursor(Renderer& renderer, const SWFMatrix& mat);
696 /// The immutable definition of our TextField
698 /// This is NULL for dynamic TextFields.
699 boost::intrusive_ptr<const SWF::DefineEditTextTag> _tag;
701 /// The actual text.
703 /// Because we have to deal with non-ascii DisplayObjects (129-255), this
704 /// is a wide string; the cursor position and the position within the
705 /// string are then the same, which makes manipulating the string much
706 /// easier.
707 std::wstring _text;
709 /// The html representation of our text
711 std::wstring _htmlText;
713 /// bounds of dynamic text, as laid out
714 SWFRect m_text_bounding_box;
716 typedef std::vector<SWF::TextRecord> TextRecords;
717 TextRecords _textRecords;
719 std::vector<size_t> _recordStarts;
721 TextRecords _displayRecords;
723 std::string _url;
724 std::string _target;
725 std::string _restrict;
726 std::set<wchar_t> _restrictedchars;
727 TextFormatDisplay _display;
728 std::vector<int> _tabStops;
729 LineStarts _line_starts;
731 /// The text variable name
733 /// This is stored here, and not just in the definition,
734 /// because it can be changed programmatically, by setting
735 /// 'TextFields.variable'
736 std::string _variable_name;
738 rgba _backgroundColor;
740 rgba _borderColor;
742 rgba _textColor;
744 TextAlignment _alignment;
746 boost::intrusive_ptr<const Font> _font;
747 size_t m_cursor;
748 size_t _glyphcount;
749 size_t _scroll;
750 size_t _maxScroll;
751 size_t _hScroll;
752 size_t _maxHScroll;
753 size_t _bottomScroll;
754 size_t _linesindisplay;
756 /// Corresponds to the maxChars property.
757 size_t _maxChars;
759 AutoSize _autoSize;
761 TypeValue _type;
763 /// Area in which the text is drawn.
765 /// This area encloses all the text, can be automatically
766 /// extended to fit text or hide text overflowing it.
767 /// See the setAutoSize() method to change that.
769 SWFRect _bounds;
771 /// Represents the selected part of the text. The second element must
772 /// never be less than the first.
773 std::pair<size_t, size_t> _selection;
775 boost::int16_t _leading;
776 boost::uint16_t _indent;
778 /// Indentation for every line (including the ones created by
779 /// effect of a word-wrap.
780 boost::uint16_t _blockIndent;
782 boost::uint16_t _leftMargin;
784 boost::uint16_t _rightMargin;
786 boost::uint16_t _fontHeight;
788 /// This flag will be true as soon as the TextField
789 /// is assigned a text value. Only way to be false is
790 /// when definition has the hasText flag set to false
791 /// and no actionscript added text.
792 bool _textDefined;
794 bool _htmlTextDefined;
796 bool _restrictDefined;
797 bool _underlined;
798 bool _bullet;
800 bool m_has_focus;
803 /// Corresponds to the multiline property.
804 bool _multiline;
806 /// Corresponds to the password property.
807 bool _password;
809 /// The flag keeping status of TextVariable registration
811 /// It will be set to true if there's no need to register
812 /// a text variable (ie. non-specified in the SWF)
814 bool _text_variable_registered;
816 bool _drawBackground;
818 bool _drawBorder;
820 bool _embedFonts;
822 bool _wordWrap;
824 bool _html;
826 bool _selectable;
830 } // namespace gnash
832 #endif