1 /* libsswf_actions.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */
2
3 /*
4
5 Copyright (c) 2002-2008 Made to Order Software Corp.
6
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31
32 */
33
34 /** \file
35 *
36 * \brief The implementation of the sswf::Action and derived classes.
37 *
38 * This file declares the body of the functions which are not
39 * inline. It is part of the SSWF library.
40 */
41
42 #include "sswf/libsswf.h"
43
44 using namespace sswf;
45
46
47
48 /////////////////////////////////////////// Action
49
50 /** \class sswf::Action
51 *
52 * \brief Holds an action.
53 *
54 * The Action class is used to hold ONE action. An array of actions
55 * can be used to generate an ActionScript.
56 *
57 * The Action class represents one SWF raw action (i.e. no JavaScript!)
58 *
59 * The organization of actions to create a valid script is described in my
60 * <a href="../SWFalexref.html#tag_doaction">Alexis' SWF Reference—Do Action</a>
61 * document.
62 *
63 * Actions are ItemBase objects which can thus be added in a Vectors
64 * array. Tags which support actions will usually expose the vector
65 * used to save actions in it. Also, some actions can have sub-actions.
66 * Similarly, you have the sswf::Action::SubList(void) function which
67 * can be used to retrieve the sub-actions of a given action.
68 *
69 * Note that newer action script code is much different from the old
70 * one. This applies to movies version 9 or better when setup to run
71 * ActionScript version 3 (see the
72 * <a href="../abcFormat.html">abcFormat.html</a> document.)
73 *
74 * \warning
75 * Most actions which support sub-actions are limited to about 64Kb
76 * of sub-action data (depending on the actions used, some actions
77 * save data in the action list and can use a lot more than 1 byte,
78 * especially the sswf::Action::ACTION_PUSH_DATA action!)
79 *
80 * \par
81 * The sswf::Action::ACTION_WAIT_FOR_FRAME and sswf::Action::ACTION_WAIT_FOR_FRAME2
82 * are limited to 255 bytes. Also, they branch as long as the frame
83 * is not reached which is somewhat the opposite of what we would
84 * usually need.
85 *
86 * \sa <a href="../SWFalexref.html#tag_doaction">Alexis' SWF Reference—Do Action</a>
87 */
88
89
90
91 /** \enum sswf::Action::action_t
92 *
93 * \brief List all the actions supported by SSWF.
94 *
95 * These action enumeration variables are used whenever you create
96 * an action object. All the actions which do not require any data
97 * are created using the Action object. In this case you must specify
98 * the action enumeration variable.
99 *
100 * Actions which require some additional data will automatically
101 * receive a default (i.e. sswf::ActionBranch is set to ACTION_BRANCH_ALWAYS
102 * by default.) Some cannot actually be changed by you (i.e. sswf::ActionCallFrame).
103 * All of them can only receive a very few set of values. Trying to set
104 * another value will generate an error on creation.
105 */
106
107
108 /** \var sswf::Action::ACTION_UNKNOWN
109 *
110 * \brief The special unknown value.
111 *
112 * This special action number can be used to mark an entry as
113 * unknown. You cannot create and save an unknown action
114 * in an SWF file.
115 *
116 * <hr>
117 */
118
119
120 /** \var sswf::Action::ACTION_LABEL
121 *
122 * \brief A label to branch to.
123 *
124 * This special action repesents a label. A specific object
125 * must be created to use an ACTION_LABEL the sswf::ActionLabel
126 * object. You should name labels and then use their name with
127 * sswf::ActionBranch to jump to the
128 * instructions appearing after that label.
129 *
130 * It is legal to create multiple labels one after another
131 * without adding other instructions in between, in effect
132 * creating one label and aliases.
133 *
134 * \sa sswf::ActionBranch
135 * \sa sswf::ActionBranch::SetLabel(const char *label)
136 * \sa sswf::ActionLabel
137 * \sa sswf::ActionLabel::SetLabel(const char *label)
138 *
139 * <hr>
140 */
141
142
143 /** \var sswf::Action::ACTION_min
144 *
145 * \brief Very first valid action.
146 *
147 * The ACTION_min value represents the smallest valid action
148 * which can be saved in an SWF file.
149 *
150 * \sa sswf::Action::ACTION_max
151 *
152 * <hr>
153 */
154
155
156 /** \var sswf::Action::ACTION_END
157 *
158 * \brief End the current list of actions.
159 *
160 * The ACTION_END is for programs execution what the '\\0' is for
161 * C string: it represents the end of actions.
162 *
163 * It is in general not necessary for your to add this action as
164 * the system takes care of that for you automatically. It
165 * usually makes it simpler not to add the ACTION_END actions.
166 *
167 * Note that this is used once to end the entire list of actions.
168 * Actions within a function or other groups of actions are not
169 * terminated by an ACTION_END. Instead they have a size in bytes
170 * to skip their body and at the same time determine the end of
171 * actions to execute as required.
172 *
173 * \sa <a href="../SWFalexref.html#action_end">SWF Alexis' Reference—End</a>
174 *
175 * <hr>
176 */
177
178
179 /** \var sswf::Action::ACTION_NEXT_FRAME
180 *
181 * \brief Skip the next Show Frame.
182 *
183 * The ACTION_NEXT_FRAME is useful whenever you stop the playback
184 * and thus the program pointer remains within one frame. This
185 * action forces the animation to move to the next frame and
186 * display it.
187 *
188 * \sa sswf::Action::ACTION_PLAY
189 * \sa sswf::Action::ACTION_STOP
190 * \sa <a href="../SWFalexref.html#action_next_frame">SWF Alexis' Reference—Next Frame</a>
191 *
192 * <hr>
193 */
194
195
196 /** \var sswf::Action::ACTION_PREVIOUS_FRAME
197 *
198 * \brief Jump back one frame; before the previous ShowFrame.
199 *
200 * The ACTION_PREVIOUS_FRAME is useful whenever you stop the playback
201 * and thus the program pointer remains within one frame. This
202 * action forces the animation to move to the previous frame and
203 * display it.
204 *
205 * \sa sswf::Action::ACTION_PLAY
206 * \sa sswf::Action::ACTION_STOP
207 * \sa <a href="../SWFalexref.html#action_previous_frame">SWF Alexis' Reference—Next Frame</a>
208 *
209 * <hr>
210 */
211
212
213 /** \var sswf::Action::ACTION_PLAY
214 *
215 * \brief Start playing the animation.
216 *
217 * The ACTION_PLAY restart the playback of an animation. It is possible
218 * stop an animation with ACTION_STOP. The last of ACTION_PLAY or
219 * ACTION_STOP encountered in a frame is the one in effect.
220 *
221 * \sa ACTION_STOP
222 * \sa <a href="../SWFalexref.html#action_play">SWF Alexis' Reference—Play</a>
223 *
224 * <hr>
225 */
226
227
228 /** \var sswf::Action::ACTION_STOP
229 *
230 * \brief Start playing the animation.
231 *
232 * The ACTION_STOP stops the playback of an animation. It is possible
233 * restart an animation with ACTION_PLAY. The last of ACTION_PLAY or
234 * ACTION_STOP encountered in a frame is the one in effect.
235 *
236 * When a movie is marked as stopped, its current frame is displayed
237 * but no script is played. To restart the animation, you either have
238 * a button or another \e thread (i.e. a sprite) still running.
239 *
240 * Each sprite has its own loop and thus they can be considered threads
241 * thought each one's script will be executed serially.
242 *
243 * \sa ACTION_PLAY
244 * \sa <a href="../SWFalexref.html#action_stop">SWF Alexis' Reference—Stop</a>
245 *
246 * <hr>
247 */
248
249
250 /** \var sswf::Action::ACTION_TOGGLE_QUALITY
251 *
252 * \brief Switch between low and high quality rendering.
253 *
254 * The ACTION_TOGGLE_QUALITY is used to switch between the different
255 * quality modes available. In general, you shouldn't do that. However,
256 * if you detect that the realtime frame rate is much lower than it
257 * should be, you can request the quality to drop in order to increase
258 * the frame rate to reasonable levels.
259 *
260 * This tag should not be used anymore since you cannot know exactly
261 * what you are doing without first querying for the quality. Instead
262 * you can use a function call.
263 *
264 * \sa sswf::Action::ACTION_CALL_FUNCTION
265 * \sa <a href="../SWFalexref.html#action_toggle_quality">SWF Alexis' Reference—ToggleQuality</a>
266 *
267 * <hr>
268 */
269
270
271 /** \var sswf::Action::ACTION_STOP_SOUND
272 *
273 * \brief Stop play sounds.
274 *
275 * The ACTION_STOP_SOUND requests that the player stops playing any
276 * sound in the current movie. This means used in a sprite, it stops
277 * the sounds of that sprite and not the entire animation.
278 *
279 * \sa sswf::Action::ACTION_CALL_FUNCTION
280 * \sa <a href="../SWFalexref.html#action_stop_sound">SWF Alexis' Reference—StopSound</a>
281 *
282 * <hr>
283 */
284
285
286 /** \var sswf::Action::ACTION_ADD
287 *
288 * \brief Add two values on the stack.
289 *
290 * The ACTION_ADD pops two values from the stack, add them together
291 * and pushes the result back onto the stack.
292 *
293 * \note
294 * This action should not be used anymore. It was deprecated. Instead, you should use
295 * the ACTION_ADD_TYPED action which ensures proper casting (as expected in the
296 * JavaScript reference—ECMA).
297 *
298 * \par
299 * This is particularly important if you are mixing strings and numbers.
300 *
301 * \sa sswf::Action::ACTION_ADD_TYPED
302 * \sa sswf::Action::ACTION_SUBTRACT
303 * \sa <a href="../SWFalexref.html#action_add">SWF Alexis' Reference—Add</a>
304 *
305 * <hr>
306 */
307
308
309 /** \var sswf::Action::ACTION_SUBTRACT
310 *
311 * \brief Subtract two values on the stack.
312 *
313 * The ACTION_SUBTRACT pops two values from the stack, subtract one
314 * from the other and pushes the result back onto the stack.
315 *
316 * \sa sswf::Action::ACTION_ADD
317 * \sa <a href="../SWFalexref.html#action_subtract">SWF Alexis' Reference—Subtract</a>
318 *
319 * <hr>
320 */
321
322
323 /** \var sswf::Action::ACTION_MULTIPLY
324 *
325 * \brief Multiply two values on the stack.
326 *
327 * The ACTION_MULTIPLY pops two values from the stack, multiply them
328 * together and pushes the result back onto the stack.
329 *
330 * \sa sswf::Action::ACTION_DIVIDE
331 * \sa sswf::Action::ACTION_MODULO
332 * \sa <a href="../SWFalexref.html#action_multiply">SWF Alexis' Reference—Multiply</a>
333 *
334 * <hr>
335 */
336
337
338 /** \var sswf::Action::ACTION_DIVIDE
339 *
340 * \brief Divide two values on the stack.
341 *
342 * The ACTION_DIVIDE pops two values from the stack, divide one by the
343 * other and pushes the result back onto the stack.
344 *
345 * \sa sswf::Action::ACTION_MULTIPLY
346 * \sa sswf::Action::ACTION_MODULO
347 * \sa <a href="../SWFalexref.html#action_divide">SWF Alexis' Reference—Divide</a>
348 *
349 * <hr>
350 */
351
352
353 /** \var sswf::Action::ACTION_EQUAL
354 *
355 * \brief Test whether two objects are equal.
356 *
357 * The ACTION_EQUAL pops two values from the stack, compare them for equality
358 * and pushes the result back on the stack.
359 *
360 * There is not action \e not \e equal. Instead you need to use this action and
361 * an ACTION_LOGICAL_NOT.
362 *
363 * \note
364 * This action should not be used anymore. It was deprecated. Instead, you should use
365 * the ACTION_EQUAL_TYPED action which ensures proper casting (as expected in the
366 * JavaScript reference—ECMA).
367 *
368 * \sa sswf::Action::ACTION_EQUAL_TYPED
369 * \sa sswf::Action::ACTION_STRICT_EQUAL
370 * \sa sswf::Action::ACTION_LESS_THAN
371 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
372 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
373 * \sa sswf::Action::ACTION_LOGICAL_NOT
374 * \sa sswf::Action::ACTION_LOGICAL_AND
375 * \sa sswf::Action::ACTION_LOGICAL_OR
376 * \sa <a href="../SWFalexref.html#action_equal">SWF Alexis' Reference—Equal</a>
377 *
378 * <hr>
379 */
380
381
382 /** \var sswf::Action::ACTION_LESS_THAN
383 *
384 * \brief Test whether two objects are ordered.
385 *
386 * The ACTION_LESS_THAN pops two values from the stack, compare them for order
387 * and pushes the result back on the stack.
388 *
389 * Note that in older versions you only had a \c less \c than. In new SWF versions there is a
390 * \c greater \c than which makes it simpler to compare either side. With only a \c less
391 * \c than instruction, you need to use the ACTION_SWAP and the ACTION_LOGICAL_NOT to
392 * obtain all the possible behaviors.
393 *
394 * \note
395 * This action should not be used anymore. It was deprecated. Instead, you should use
396 * the ACTION_LESS_THAN_TYPED action which ensures proper casting (as expected in the
397 * JavaScript reference—ECMA).
398 *
399 * \sa sswf::Action::ACTION_EQUAL
400 * \sa sswf::Action::ACTION_EQUAL_TYPED
401 * \sa sswf::Action::ACTION_STRICT_EQUAL
402 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
403 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
404 * \sa sswf::Action::ACTION_LOGICAL_NOT
405 * \sa sswf::Action::ACTION_LOGICAL_AND
406 * \sa sswf::Action::ACTION_LOGICAL_OR
407 * \sa <a href="../SWFalexref.html#action_less_than">SWF Alexis' Reference—Less Than</a>
408 *
409 * <hr>
410 */
411
412
413 /** \var sswf::Action::ACTION_LOGICAL_AND
414 *
415 * \brief Test whether two objects are true.
416 *
417 * The ACTION_LOGICAL_AND pops two values from the stack, casts them to a
418 * boolean value, computes the result (if both values are true, then the
419 * result is true, otherwise it is false) and pushes the result back on
420 * the stack.
421 *
422 * \sa sswf::Action::ACTION_EQUAL
423 * \sa sswf::Action::ACTION_EQUAL_TYPED
424 * \sa sswf::Action::ACTION_STRICT_EQUAL
425 * \sa sswf::Action::ACTION_LESS_THAN
426 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
427 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
428 * \sa sswf::Action::ACTION_LOGICAL_NOT
429 * \sa sswf::Action::ACTION_LOGICAL_OR
430 * \sa sswf::Action::ACTION_AND
431 * \sa sswf::Action::ACTION_OR
432 * \sa sswf::Action::ACTION_XOR
433 * \sa <a href="../SWFalexref.html#action_logical_and">SWF Alexis' Reference—Logical And</a>
434 *
435 * <hr>
436 */
437
438
439 /** \var sswf::Action::ACTION_LOGICAL_OR
440 *
441 * \brief Combines two boolean value with an OR.
442 *
443 * The ACTION_LOGICAL_OR pops two values from the stack, cast them to boolean
444 * values, compute a logical or (i.e. if at least one value is true, use true
445 * otherwise use false) and pushes the result back on the stack.
446 *
447 * \sa sswf::Action::ACTION_EQUAL
448 * \sa sswf::Action::ACTION_EQUAL_TYPED
449 * \sa sswf::Action::ACTION_STRICT_EQUAL
450 * \sa sswf::Action::ACTION_LESS_THAN
451 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
452 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
453 * \sa sswf::Action::ACTION_LOGICAL_NOT
454 * \sa sswf::Action::ACTION_LOGICAL_AND
455 * \sa sswf::Action::ACTION_AND
456 * \sa sswf::Action::ACTION_OR
457 * \sa sswf::Action::ACTION_XOR
458 * \sa <a href="../SWFalexref.html#action_logical_or">SWF Alexis' Reference—Logical Or</a>
459 *
460 * <hr>
461 */
462
463
464 /** \var sswf::Action::ACTION_LOGICAL_NOT
465 *
466 * \brief Apply a logical not to the value on the stack.
467 *
468 * The ACTION_LOGICAL_NOT pops one object from the stack, cast it to a boolean
469 * value if necessary, then pushes \c true on the stack when the value is \c false
470 * and vice versa.
471 *
472 * This action is particularly useful when branching since SWF
473 * only supports a <i>branch if true</i> action (i.e. no <i>branch
474 * if false</i> action!)
475 *
476 * \sa sswf::Action::ACTION_BRANCH_IF_TRUE
477 * \sa sswf::Action::ACTION_EQUAL
478 * \sa sswf::Action::ACTION_EQUAL_TYPED
479 * \sa sswf::Action::ACTION_STRICT_EQUAL
480 * \sa sswf::Action::ACTION_LESS_THAN
481 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
482 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
483 * \sa sswf::Action::ACTION_LOGICAL_AND
484 * \sa sswf::Action::ACTION_LOGICAL_OR
485 * \sa sswf::Action::ACTION_AND
486 * \sa sswf::Action::ACTION_OR
487 * \sa sswf::Action::ACTION_XOR
488 * \sa <a href="../SWFalexref.html#action_logical_not">SWF Alexis' Reference—Logical Not</a>
489 *
490 * <hr>
491 */
492
493
494 /** \var sswf::Action::ACTION_STRING_EQUAL
495 *
496 * \brief Test whether two strings are equal.
497 *
498 * The ACTION_STRING_EQUAL pops two strings from the stack, compare them for equality
499 * and pushes the result back on the stack.
500 *
501 * This action will ensure that two strings which represent numbers are still compared
502 * as strings and not numbers.
503 *
504 * \note
505 * This action should not be used anymore. It was deprecated. Instead, you should use
506 * the ACTION_EQUAL_TYPED action which ensures proper casting (as expected in the
507 * JavaScript reference—ECMA).
508 *
509 * \sa sswf::Action::ACTION_EQUAL_TYPED
510 * \sa sswf::Action::ACTION_STRICT_EQUAL
511 * \sa sswf::Action::ACTION_STRING_LESS_THAN
512 * \sa sswf::Action::ACTION_STRING_GREATER_THAN
513 * \sa <a href="../SWFalexref.html#action_string_equal">SWF Alexis' Reference—String Equal</a>
514 *
515 * <hr>
516 */
517
518
519 /** \var sswf::Action::ACTION_STRING_LENGTH
520 *
521 * \brief Compute the length of a string in characters.
522 *
523 * The ACTION_STRING_LENGTH pops one string, counts the number of characters
524 * and pushes the result back on the stack.
525 *
526 * \note
527 * This action should not be used anymore. It was deprecated. Instead, you should use
528 * the ACTION_MBSTRING_LENGTH action which ensures the proper length for a UTF-8 string.
529 *
530 * \sa sswf::Action::ACTION_MBSTRING_LENGTH
531 * \sa <a href="../SWFalexref.html#action_string_length">SWF Alexis' Reference—String Length</a>
532 *
533 * <hr>
534 */
535
536
537 /** \var sswf::Action::ACTION_SUB_STRING
538 *
539 * \brief Retrieve part of a string.
540 *
541 * The ACTION_SUB_STRING pops one string and two numbers: one position
542 * and one length; then it generates a new string from the sub-string
543 * starting at that position and for that many characters; this is the
544 * result which is pushed backed on the stack.
545 *
546 * \note
547 * This action should not be used anymore. It was deprecated. Instead, you should use
548 * the ACTION_SUB_MBSTRING action which ensures the proper position and length for a
549 * UTF-8 string.
550 *
551 * \sa sswf::Action::ACTION_SUB_MBSTRING
552 * \sa <a href="../SWFalexref.html#action_substring">SWF Alexis' Reference—SubString</a>
553 *
554 * <hr>
555 */
556
557
558 /** \var sswf::Action::ACTION_POP
559 *
560 * \brief Pop one element from the stack.
561 *
562 * The ACTION_POP action is used to \e forget about the result of a function
563 * call.
564 *
565 * \sa sswf::Action::ACTION_DUPLICATE
566 * \sa sswf::Action::ACTION_SWAP
567 * \sa <a href="../SWFalexref.html#action_pop">SWF Alexis' Reference—Pop</a>
568 *
569 * <hr>
570 */
571
572
573 /** \var sswf::Action::ACTION_INTEGRAL_PART
574 *
575 * \brief Remove the fractional part of a float.
576 *
577 * The ACTION_INTEGRAL_PART action is used on a floating point to remove the
578 * fractional part.
579 *
580 * This action does not round the input. It only removes the fractional part.
581 * To get a rounding effect, add 0.5 to the float first.
582 *
583 * This is the equivalent of the floor() function in the C/C++ math library.
584 *
585 * One can use the modulo action with 1.0 to extract the fractional part.
586 *
587 * \sa sswf::Action::ACTION_MODULO
588 * \sa <a href="../SWFalexref.html#action_integral_part">SWF Alexis' Reference—Integral Part</a>
589 *
590 * <hr>
591 */
592
593
594 /** \var sswf::Action::ACTION_GET_VARIABLE
595 *
596 * \brief Read a variable.
597 *
598 * The ACTION_GET_VARIABLE action reads the content of a variable and puts it
599 * on the stack. The name of the variable is taken from the stack.
600 *
601 * The name can be a full path.
602 *
603 * \sa sswf::Action::ACTION_SET_VARIABLE
604 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
605 * \sa sswf::Action::ACTION_GET_PROPERTY
606 * \sa sswf::Action::ACTION_SET_PROPERTY
607 * \sa sswf::Action::ACTION_GET_MEMBER
608 * \sa sswf::Action::ACTION_SET_MEMBER
609 * \sa sswf::Action::ACTION_DELETE
610 * \sa <a href="../SWFalexref.html#action_get_variable">SWF Alexis' Reference—Get Variable</a>
611 *
612 * <hr>
613 */
614
615
616 /** \var sswf::Action::ACTION_SET_VARIABLE
617 *
618 * \brief Read a variable.
619 *
620 * The ACTION_SET_VARIABLE action reads the content of a variable and puts it
621 * on the stack. The new value for the variable is pop first from the stack,
622 * then the name of the variable.
623 *
624 * The name can be a full path.
625 *
626 * \sa sswf::Action::ACTION_GET_VARIABLE
627 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
628 * \sa sswf::Action::ACTION_GET_PROPERTY
629 * \sa sswf::Action::ACTION_SET_PROPERTY
630 * \sa sswf::Action::ACTION_GET_MEMBER
631 * \sa sswf::Action::ACTION_SET_MEMBER
632 * \sa sswf::Action::ACTION_DELETE
633 * \sa <a href="../SWFalexref.html#action_set_variable">SWF Alexis' Reference—Set Variable</a>
634 *
635 * <hr>
636 */
637
638
639 /** \var sswf::Action::ACTION_SET_TARGET2
640 *
641 * \brief Set an object as current.
642 *
643 * The ACTION_SET_TARGET2 action retreives one string from the stack. The string
644 * must be either the empty string (to cancel a previous set target) or the name
645 * of an existing object (sprite, movie).
646 *
647 * Actions such as ACTION_SET_PROPERTY and ACTION_GET_PROPERTY following a set
648 * target apply to the current object. In other words, when an empty string is
649 * specified, the actions apply to the main object, otherwise to the specified
650 * object.
651 *
652 * \sa sswf::Action::ACTION_GET_TARGET
653 * \sa sswf::Action::ACTION_SET_TARGET
654 * \sa sswf::Action::ACTION_WITH
655 * \sa <a href="../SWFalexref.html#action_set_target_dynamic">SWF Alexis' Reference—Set Target <i>(dynamic)</i></a>
656 *
657 * <hr>
658 */
659
660
661 /** \var sswf::Action::ACTION_CONCATENATE
662 *
663 * \brief Concatenate two strings together.
664 *
665 * The ACTION_CONCATENATE action retrieves two strings from the stack, concatenate
666 * them together and push the result back on the stack.
667 *
668 * If one of the input is not a string, the \c toString() function is called on the
669 * object. If not available, an empty string is used or the SWF throws (depending
670 * on the version and setup.)
671 *
672 * Newer versions should make use of the ACTION_ADD_TYPED instead. The add will
673 * concatenate strings properly as expected unless both operands are numbers in
674 * which case the usual addition is applied.
675 *
676 * \sa sswf::Action::ACTION_STRING_ADD_TYPED
677 * \sa sswf::Action::ACTION_STRING_EQUAL
678 * \sa sswf::Action::ACTION_STRICT_EQUAL
679 * \sa sswf::Action::ACTION_STRING_LENGTH
680 * \sa <a href="../SWFalexref.html#action_concatenate">SWF Alexis' Reference—Concatenate</a>
681 *
682 * <hr>
683 */
684
685
686 /** \var sswf::Action::ACTION_GET_PROPERTY
687 *
688 * \brief Read from an object property.
689 *
690 * The ACTION_GET_PROPERTY action reads the content of the specified property
691 * of the specified object (sprite, movie) and puts it on the stack. The \e name
692 * of the property is taken from the stack as a number.
693 *
694 * The \e name of a property is represented by a number. The number can be either
695 * an integer or a floating point, though it has been a rule to use floating points.
696 *
697 * In general, this is used by a compiler as an optimization. Otherwise, it is
698 * recommended to use the ACTION_GET_MEMBER with the name of the property in
699 * a string. Some of these numeric properties may be removed in future versions
700 * of SWF.
701 *
702 * \sa sswf::Action::ACTION_SET_PROPERTY
703 * \sa sswf::Action::ACTION_GET_VARIABLE
704 * \sa sswf::Action::ACTION_SET_VARIABLE
705 * \sa sswf::Action::ACTION_GET_MEMBER
706 * \sa sswf::Action::ACTION_SET_MEMBER
707 * \sa sswf::Action::ACTION_DELETE
708 * \sa <a href="../SWFalexref.html#action_get_property">SWF Alexis' Reference—Get Property</a>
709 *
710 * <hr>
711 */
712
713
714 /** \var sswf::Action::ACTION_SET_PROPERTY
715 *
716 * \brief Write to an object property.
717 *
718 * The ACTION_SET_PROPERTY action gets the new property value, the \e name of
719 * the property (as a number) and the name of the object (as a string) from
720 * the stack and saves the new property value in that object property.
721 *
722 * The \e name of a property is represented by a number. The number can be either
723 * an integer or a floating point, though it has been a rule to use floating points.
724 *
725 * In general, this is used by a compiler as an optimization. Otherwise, it is
726 * recommended to use the ACTION_SET_MEMBER with the name of the property in
727 * a string. Some of these numeric properties may be removed in future versions
728 * of SWF.
729 *
730 * \sa sswf::Action::ACTION_GET_PROPERTY
731 * \sa sswf::Action::ACTION_GET_VARIABLE
732 * \sa sswf::Action::ACTION_SET_VARIABLE
733 * \sa sswf::Action::ACTION_GET_MEMBER
734 * \sa sswf::Action::ACTION_SET_MEMBER
735 * \sa sswf::Action::ACTION_DELETE
736 * \sa <a href="../SWFalexref.html#action_set_property">SWF Alexis' Reference—Set Property</a>
737 *
738 * <hr>
739 */
740
741
742 /** \var sswf::Action::ACTION_DUPLICATE_SPRITE
743 *
744 * \brief Create a new sprite from an existing sprite.
745 *
746 * The ACTION_DUPLICATE_SPRITE action creates a duplicate of an existing
747 * sprite. The new way to do so is to use the ACTION_NEW which represents
748 * the ActionScript new operator.
749 *
750 * The new operator is somewhat different since it will also call the
751 * constructor, though some people may still want to use this action instead.
752 *
753 * \sa sswf::Action::ACTION_REMOVE_SPRITE
754 * \sa sswf::Action::ACTION_NEW
755 * \sa <a href="../SWFalexref.html#action_duplicate_sprite">SWF Alexis' Reference—Duplicate Sprite</a>
756 *
757 * <hr>
758 */
759
760
761 /** \var sswf::Action::ACTION_REMOVE_SPRITE
762 *
763 * \brief Remove an existing sprite from the display list.
764 *
765 * The ACTION_REMOVE_SPRITE action searches for the specified sprite and
766 * remove it from the display list. Once removed, the sprite is also
767 * deleted and cannot be reused.
768 *
769 * This action should be used whenever a sprite was created with the
770 * ACTION_DUPLICATE_SPRITE.
771 *
772 * Objects created with the ACTION_NEW operator need to be deleted with
773 * the ACTION_DELETE operator.
774 *
775 * \sa sswf::Action::ACTION_DUPLICATE_SPRITE
776 * \sa sswf::Action::ACTION_NEW
777 * \sa <a href="../SWFalexref.html#action_remove_sprite">SWF Alexis' Reference—Remove Sprite</a>
778 *
779 * <hr>
780 */
781
782
783 /** \var sswf::Action::ACTION_TRACE
784 *
785 * \brief Turn on TRACE mode.
786 *
787 * This is a Macromedia Flash internal action caught by the debugger.
788 *
789 * Whenever encountered, it starts tracing the execution of your code.
790 *
791 * In the player, it has no effect.
792 *
793 * \sa <a href="../SWFalexref.html#action_trace">SWF Alexis' Reference—Trace</a>
794 *
795 * <hr>
796 */
797
798
799 /** \var sswf::Action::ACTION_START_DRAG
800 *
801 * \brief Start dragging an object.
802 *
803 * This action has the effect of attaching an object to the user's mouse.
804 *
805 * The following movements of the mouse will move the object until the
806 * ACTION_STOP_DRAG is used.
807 *
808 * This action is often executed after an sswf::Event::EVENT_POINTER_DOWN.
809 *
810 * \sa sswf::Event::EVENT_POINTER_DOWN
811 * \sa sswf::Event::EVENT_POINTER_DRAG_ENTER
812 * \sa sswf::Event::EVENT_POINTER_DRAG_LEAVE
813 * \sa sswf::Action::ACTION_STOP_DRAG
814 * \sa <a href="../SWFalexref.html#action_start_drag">SWF Alexis' Reference—Start Drag</a>
815 *
816 * <hr>
817 */
818
819
820 /** \var sswf::Action::ACTION_STOP_DRAG
821 *
822 * \brief Stop dragging the dragged object.
823 *
824 * This action must be called once the drag action is over. This breaks
825 * the effect of having an object follow the user's mouse all over the
826 * place.
827 *
828 * This action is often executed after an sswf::Event::EVENT_POINTER_UP.
829 *
830 * \sa sswf::Event::EVENT_POINTER_UP
831 * \sa sswf::Event::EVENT_POINTER_DRAG_ENTER
832 * \sa sswf::Event::EVENT_POINTER_DRAG_LEAVE
833 * \sa sswf::Action::ACTION_STOP_DRAG
834 * \sa <a href="../SWFalexref.html#action_stop_drag">SWF Alexis' Reference—Stop Drag</a>
835 *
836 * <hr>
837 */
838
839
840 /** \var sswf::Action::ACTION_STRING_LESS_THAN
841 *
842 * \brief Test whether two strings are ordered.
843 *
844 * The ACTION_STRING_LESS_THAN pops two strings from the stack, compare them for order
845 * and pushes the result back on the stack.
846 *
847 * This action will ensure that two strings which represent numbers are still compared
848 * as strings and not numbers.
849 *
850 * \note
851 * This action should not be used anymore. It was deprecated. Instead, you should use
852 * the ACTION_LESS_THAN_TYPED action which ensures proper casting (as expected in the
853 * JavaScript reference—ECMA).
854 *
855 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
856 * \sa sswf::Action::ACTION_STRING_EQUAL
857 * \sa sswf::Action::ACTION_STRICT_EQUAL
858 * \sa sswf::Action::ACTION_STRING_GREATER_THAN
859 * \sa <a href="../SWFalexref.html#action_string_less_than">SWF Alexis' Reference—String Less Than</a>
860 *
861 * <hr>
862 */
863
864
865 /** \var sswf::Action::ACTION_THROW
866 *
867 * \brief Throw an exception.
868 *
869 * The ACTION_THROW pops one element from the stack and generates an
870 * exception of that type.
871 *
872 * One can use a try/catch/finaly block to manage exceptions.
873 *
874 * \sa sswf::Action::ACTION_TRY
875 * \sa <a href="../SWFalexref.html#action_throw">SWF Alexis' Reference—Throw</a>
876 *
877 * <hr>
878 */
879
880
881 /** \var sswf::Action::ACTION_CAST_OBJECT
882 *
883 * \brief Cast from one type to another.
884 *
885 * The ACTION_CAST_OBJECT action transform an object reference
886 * from one time to another. Really, in Javascript, this means
887 * making sure that an object is of a specified type. If not,
888 * you get NULL. Otherwise the action has no effect.
889 *
890 * This is similar to sswf::Action::ACTION_INSTANCE_OF except
891 * that it returns a reference to the object instead of a
892 * boolean value which often is more practical.
893 *
894 * \sa sswf::Action::ACTION_INSTANCE_OF
895 * \sa sswf::Action::ACTION_TYPE_OF
896 * \sa <a href="../SWFalexref.html#action_cast_object">SWF Alexis' Reference—Cast Object</a>
897 *
898 * <hr>
899 */
900
901
902 /** \var sswf::Action::ACTION_IMPLEMENTS
903 *
904 * \brief Define a list of interfaces that an object implements.
905 *
906 * The ACTION_IMPLEMENTS is used to mark an object as a derivation
907 * of one or more objects. These other objects are expected to be
908 * interfaces. This means they should only define abstract functions.
909 *
910 * \sa sswf::Action::ACTION_EXTENDS
911 * \sa <a href="../SWFalexref.html#action_implements">SWF Alexis' Reference—Implements</a>
912 *
913 * <hr>
914 */
915
916
917 /** \var sswf::Action::ACTION_FSCOMMAND2
918 *
919 * \brief Dynamic "Foreign Script Command".
920 *
921 * The ACTION_FSCOMMAND2 action pops an integer which is the number of
922 * strings to pop next. The first string popped is the name of the
923 * command to execute and the following strings are its parameters.
924 *
925 * FS in this action name means Foreign Script. In other words, not
926 * an ActionScript command, but a javascript command from within the
927 * browser.
928 *
929 * In order to execute dynamic ActionScript code, use the eval()
930 * function instead. Note that the SWF implementation of eval() is
931 * quite limited. So don't expect too much out of it.
932 *
933 * \sa sswf::Action::ACTION_DECLARE_FUNCTION
934 * \sa sswf::Action::ACTION_DECLARE_FUNCTION2
935 * \sa <a href="../SWFalexref.html#action_fscommand2">SWF Alexis' Reference—FSCommand2</a>
936 *
937 * <hr>
938 */
939
940
941 /** \var sswf::Action::ACTION_RANDOM
942 *
943 * \brief Generates a random value.
944 *
945 * The ACTION_RANDOM action pops one number from the stack and
946 * generates a random value between 0 and that number (the number
947 * not included.)
948 *
949 * The random value is not very good in older SWF players.
950 *
951 * It is suggested you use the Math.Random() function instead,
952 * which returns a value between 0.0 and 1.0.
953 *
954 * \sa sswf::Action::ACTION_CALL_METHOD
955 * \sa <a href="../SWFalexref.html#action_random">SWF Alexis' Reference—Random</a>
956 *
957 * <hr>
958 */
959
960
961 /** \var sswf::Action::ACTION_MBSTRING_LENGTH
962 *
963 * \brief Compute the length of a UTF-8 string in characters.
964 *
965 * The ACTION_MBSTRING_LENGTH pops one string, counts the number of characters
966 * and pushes the result back on the stack. The string is assumed to be defined
967 * in UTF-8.
968 *
969 * \sa sswf::Action::ACTION_STRING_LENGTH
970 * \sa <a href="../SWFalexref.html#action_string_length_mb">SWF Alexis' Reference—String Length</a> <i>(multi-bytes)</i>
971 *
972 * <hr>
973 */
974
975
976 /** \var sswf::Action::ACTION_ORD
977 *
978 * \brief Transform a character in the corresponding integer.
979 *
980 * The ACTION_ORD action pops one string and transform the first
981 * character in a number and push that number on the stack.
982 *
983 * This action can only deal with ASCII strings. Use the
984 * sswf::Action::ACTION_MBORD for international strings.
985 *
986 * \sa sswf::Action::ACTION_MBORD
987 * \sa sswf::Action::ACTION_CHR
988 * \sa sswf::Action::ACTION_MBCHR
989 * \sa <a href="../SWFalexref.html#action_ord">SWF Alexis' Reference—Ord</a>
990 *
991 * <hr>
992 */
993
994
995 /** \var sswf::Action::ACTION_CHR
996 *
997 * \brief Transform a number in the corresponding character.
998 *
999 * The ACTION_CHR action pops one number and transform it in a
1000 * character, then it pushes a string composed of that character
1001 * on the stack.
1002 *
1003 * This action can only deal with ASCII characters. Use the
1004 * sswf::Action::ACTION_MBCHR for international characters.
1005 *
1006 * \sa sswf::Action::ACTION_MBCHR
1007 * \sa sswf::Action::ACTION_ORD
1008 * \sa sswf::Action::ACTION_MBORD
1009 * \sa <a href="../SWFalexref.html#action_chr">SWF Alexis' Reference—Chr</a>
1010 *
1011 * <hr>
1012 */
1013
1014
1015 /** \var sswf::Action::ACTION_GET_TIMER
1016 *
1017 * \brief Push the current frame number on the stack.
1018 *
1019 * The ACTION_GET_TIMER action gets the frame counter and push it on the stack.
1020 * This is the main frame counter for the main SWF movie.
1021 *
1022 * In the newer versions of SWF you have access to a similar function on each
1023 * movie (I think it is called GetFrame(), but I'd have to verify...)
1024 *
1025 * \sa <a href="../SWFalexref.html#action_get_timer">SWF Alexis' Reference—Get Timer</a>
1026 *
1027 * <hr>
1028 */
1029
1030
1031 /** \var sswf::Action::ACTION_SUB_MBSTRING
1032 *
1033 * \brief Retrieve part of a string.
1034 *
1035 * The ACTION_SUB_MBSTRING pops one string and two numbers: one position
1036 * and one length; then it generates a new string from the sub-string
1037 * starting at that position and for that many characters; this is the
1038 * result which is pushed backed on the stack. This action views the
1039 * input string as a UTF-8 encoded string.
1040 *
1041 * \sa sswf::Action::ACTION_SUB_STRING
1042 * \sa <a href="../SWFalexref.html#action_substring">SWF Alexis' Reference—SubString</a>
1043 *
1044 * <hr>
1045 */
1046
1047
1048 /** \var sswf::Action::ACTION_MBORD
1049 *
1050 * \brief Transform a character in the corresponding integer.
1051 *
1052 * The ACTION_MBORD action pops one string and transform the first
1053 * character in a number and push that number on the stack.
1054 *
1055 * This action deals with any character (yet SWF is limited to
1056 * 16 bits characters or UCS-2).
1057 *
1058 * \sa sswf::Action::ACTION_ORD
1059 * \sa sswf::Action::ACTION_CHR
1060 * \sa sswf::Action::ACTION_MBCHR
1061 * \sa <a href="../SWFalexref.html#action_ord_mb">SWF Alexis' Reference—Ord <i>(multibyte)</i></a>
1062 *
1063 * <hr>
1064 */
1065
1066
1067 /** \var sswf::Action::ACTION_MBCHR
1068 *
1069 * \brief Transform a number in the corresponding character.
1070 *
1071 * The ACTION_MBCHR action pops one number and transform it in a
1072 * character, then it pushes a string composed of that character
1073 * on the stack.
1074 *
1075 * This action can deal with any international characters
1076 * (yet SWF is limited to 16 bits characters or UCS-2.)
1077 *
1078 * \sa sswf::Action::ACTION_CHR
1079 * \sa sswf::Action::ACTION_ORD
1080 * \sa sswf::Action::ACTION_MBORD
1081 * \sa <a href="../SWFalexref.html#action_chr_mb">SWF Alexis' Reference—Chr <i>(multibyte)</i></a>
1082 *
1083 * <hr>
1084 */
1085
1086
1087 /** \var sswf::Action::ACTION_DELETE
1088 *
1089 * \brief Delete an object.
1090 *
1091 * The ACTION_DELETE action pops an object and a string to delete
1092 * a property in an object. Note that an object does not need to
1093 * be deleted. If all references to that object disappear, then
1094 * the object is automatically deleted.
1095 *
1096 * It is possible to delete a global variable by pushing <b>undefined</b>
1097 * on the stack instead of an object.
1098 *
1099 * \sa sswf::Action::ACTION_NEW
1100 * \sa sswf::Action::ACTION_GET_VARIABLE
1101 * \sa sswf::Action::ACTION_SET_VARIABLE
1102 * \sa sswf::Action::ACTION_GET_MEMBER
1103 * \sa sswf::Action::ACTION_SET_MEMBER
1104 * \sa sswf::Action::ACTION_GET_PROPERTY
1105 * \sa sswf::Action::ACTION_SET_PROPERTY
1106 * \sa <a href="../SWFalexref.html#action_delete">SWF Alexis' Reference—Delete</a>
1107 *
1108 * <hr>
1109 */
1110
1111
1112 /** \var sswf::Action::ACTION_SET_LOCAL_VAR
1113 *
1114 * \brief Same as sswf::Action::ACTION_SET_LOCAL_VARIABLE.
1115 *
1116 * <hr>
1117 */
1118
1119
1120 /** \var sswf::Action::ACTION_SET_LOCAL_VARIABLE
1121 *
1122 * \brief Set a variable local to the function being executed.
1123 *
1124 * When running within a function, it is possible to create
1125 * a variable within this function. This is very useful to
1126 * avoid clashes between variable names between the different
1127 * functions you write.
1128 *
1129 * To get a local variable, use the sswf::Action::ACTION_GET_VARIABLE
1130 * action.
1131 *
1132 * See also the sswf::Action::ACTION_DECLARE_LOCAL_VARIABLE.
1133 *
1134 * \sa sswf::Action::ACTION_DECLARE_LOCAL_VARIABLE
1135 * \sa sswf::Action::ACTION_GET_VARIABLE
1136 * \sa sswf::Action::ACTION_SET_VARIABLE
1137 * \sa sswf::Action::ACTION_GET_PROPERTY
1138 * \sa sswf::Action::ACTION_SET_PROPERTY
1139 * \sa sswf::Action::ACTION_GET_MEMBER
1140 * \sa sswf::Action::ACTION_SET_MEMBER
1141 * \sa sswf::Action::ACTION_DELETE
1142 * \sa <a href="../SWFalexref.html#action_set_local_variable">SWF Alexis' Reference—Set Local Variable</a>
1143 *
1144 * <hr>
1145 */
1146
1147
1148 /** \var sswf::Action::ACTION_CALL_FUNCTION
1149 *
1150 * \brief Call a global function.
1151 *
1152 * This action is used to call a global or internal function.
1153 *
1154 * This action cannot be used to call a function on an object.
1155 * Use the sswf::Action::ACTION_CALL_METHOD instead.
1156 *
1157 * When a function returns, something will be on the stack.
1158 * A function declared as void in ActionScript usually
1159 * return an <b>undefined</b> entry. Just use
1160 * sswf::Action::ACTION_POP to get rid of it.
1161 * See the sswf::Action::ACTION_RETURN to see how you can
1162 * return right away from a function.
1163 *
1164 * The older versions (at least up to version 6) would return
1165 * as many things as you were pushing on the stack. I suggest
1166 * you make sure only one object is returned from your functions!
1167 *
1168 * \sa sswf::Action::ACTION_DECLARE_FUNCTION
1169 * \sa sswf::Action::ACTION_DECLARE_FUNCTION2
1170 * \sa sswf::Action::ACTION_RETURN
1171 * \sa sswf::Action::ACTION_CALL_METHOD
1172 * \sa sswf::Action::ACTION_NEW_METHOD
1173 * \sa sswf::Action::ACTION_NEW
1174 * \sa sswf::Action::ACTION_CALL_FRAME
1175 * \sa <a href="../SWFalexref.html#action_call_function">SWF Alexis' Reference—Call Function</a>
1176 *
1177 * <hr>
1178 */
1179
1180
1181 /** \var sswf::Action::ACTION_RETURN
1182 *
1183 * \brief End a function execution and return.
1184 *
1185 * The ACTION_RETURN ends a function execution.
1186 *
1187 * Whatever was last pushed on the stack is what the function
1188 * returns.
1189 *
1190 * In older versions (up to version 6 at least), the stack was not
1191 * purged meaning that you could return multiple objects on the
1192 * stack. This is supposedly fixed, but I did not test to confirm
1193 * whether this is really the case. So be careful and make sure
1194 * that you have only one object on the stack or expect the
1195 * unexpected!
1196 *
1197 * \sa sswf::Action::ACTION_CALL_FUNCTION
1198 * \sa sswf::Action::ACTION_CALL_METHOD
1199 * \sa sswf::Action::ACTION_NEW_METHOD
1200 * \sa sswf::Action::ACTION_NEW
1201 * \sa <a href="../SWFalexref.html#action_return">SWF Alexis' Reference—Return</a>
1202 *
1203 * <hr>
1204 */
1205
1206
1207 /** \var sswf::Action::ACTION_MODULO
1208 *
1209 * \brief Modulo of two values on the stack.
1210 *
1211 * The ACTION_MODULO pops two values from the stack, divide one by the
1212 * other and pushes the rest back onto the stack.
1213 *
1214 * Use this action with 1.0 to retrieve the fractional part of a floating
1215 * point value.
1216 *
1217 * \sa sswf::Action::ACTION_MULTIPLY
1218 * \sa sswf::Action::ACTION_DIVIDE
1219 * \sa sswf::Action::ACTION_INTEGRAL_PART
1220 * \sa <a href="../SWFalexref.html#action_modulo">SWF Alexis' Reference—Modulo</a>
1221 *
1222 * <hr>
1223 */
1224
1225
1226 /** \var sswf::Action::ACTION_NEW
1227 *
1228 * \brief Create a new instance of an object.
1229 *
1230 * The ACTION_NEW creates a new instance of an object. The name of the class
1231 * and the parameters used to call the constructor are taken from the stack.
1232 *
1233 * The constructor result will be discarded. The result of the ACTION_NEW
1234 * is the newly created object which in general will be saved in a variable
1235 * or a variable member (also called property.)
1236 *
1237 * To delete the object, remove all instances by deleting or reassigning
1238 * the variables holding the object.
1239 *
1240 * To call an overloaded new constructor, you need to use the
1241 * sswf::Action::ACTION_NEW_METHOD action instead.
1242 *
1243 * \sa sswf::Action::ACTION_DELETE
1244 * \sa sswf::Action::ACTION_SET_MEMBER
1245 * \sa sswf::Action::ACTION_SET_VARIABLE
1246 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
1247 * \sa sswf::Action::ACTION_CALL_FUNCTION
1248 * \sa sswf::Action::ACTION_CALL_METHOD
1249 * \sa sswf::Action::ACTION_NEW_METHOD
1250 * \sa <a href="../SWFalexref.html#action_new">SWF Alexis' Reference—New</a>
1251 *
1252 * <hr>
1253 */
1254
1255
1256 /** \var sswf::Action::ACTION_DECLARE_LOCAL_VAR
1257 *
1258 * \brief Same as sswf::Action::ACTION_DECLARE_LOCAL_VARIABLE.
1259 *
1260 * <hr>
1261 */
1262
1263
1264 /** \var sswf::Action::ACTION_DECLARE_LOCAL_VARIABLE
1265 *
1266 * \brief Declare names to be used for local variables.
1267 *
1268 * The ACTION_DECLARE_LOCAL_VARIABLE action takes an array of
1269 * strings naming all the variables that will be created in
1270 * this function and need to be created locally (i.e. not
1271 * visible outside of this function.)
1272 *
1273 * After this function, a regular sswf::Action::ACTION_SET_VARIABLE
1274 * will set a local variable if its name was specified
1275 * in the list of this ACTION_DECLARE_LOCAL_VARIABLE
1276 * array.
1277 *
1278 * This action has the side effect of setting the corresponding
1279 * variable to <b>undefined</b>. This hides any corresponding
1280 * global variables in case you try to get the variable before
1281 * setting it.
1282 *
1283 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
1284 * \sa sswf::Action::ACTION_GET_VARIABLE
1285 * \sa sswf::Action::ACTION_SET_VARIABLE
1286 * \sa <a href="../SWFalexref.html#action_declare_local_variable">SWF Alexis' Reference—Declare Local Variable</a>
1287 *
1288 * <hr>
1289 */
1290
1291
1292 /** \var sswf::Action::ACTION_DECLARE_ARRAY
1293 *
1294 * \brief Declare an array.
1295 *
1296 * The ACTION_DECLARE_ARRAY action creates an array object and
1297 * save the result on the stack.
1298 *
1299 * This action pops one number from the stack which is the number
1300 * of values pushed on the stack which will be used to initialize
1301 * the array. These values are then assigned to the array starting
1302 * at index 0. A counter of 0 means only one value is to be assigned.
1303 * A counter of 1 means 2 values are to be assigned. Etc.
1304 *
1305 * To initialize an array sporadically, use the
1306 * sswf::Action::ACTION_DECLARE_OBJECT instead.
1307 *
1308 * \sa sswf::Action::ACTION_DECLARE_OBJECT
1309 * \sa sswf::Action::ACTION_ENUMERATE
1310 * \sa <a href="../SWFalexref.html#action_declare_array">SWF Alexis' Reference—Declare Array</a>
1311 *
1312 * <hr>
1313 */
1314
1315
1316 /** \var sswf::Action::ACTION_DECLARE_OBJECT
1317 *
1318 * \brief Declare an object and its properties.
1319 *
1320 * The ACTION_DECLARE_OBJECT action creates an object and
1321 * save the result on the stack.
1322 *
1323 * This action pops the name of the new object and the number
1324 * of members defined on the stack. The stack holds the name
1325 * and the value of each pre-defined member. The value of a
1326 * member can be a function (when a function is declared
1327 * without a name, it is stacked!) Thus, in effect, you can
1328 * declare methods!
1329 *
1330 * It is possible to create an array with the ACTION_DECLARE_OBJECT
1331 * by specifying the indices as the variable member names. In this
1332 * case, you can initializes an array sporadically.
1333 *
1334 * \sa sswf::Action::ACTION_DECLARE_ARRAY
1335 * \sa sswf::Action::ACTION_ENUMERATE
1336 * \sa <a href="../SWFalexref.html#action_declare_object">SWF Alexis' Reference—Declare Object</a>
1337 *
1338 * <hr>
1339 */
1340
1341
1342 /** \var sswf::Action::ACTION_TYPE_OF
1343 *
1344 * \brief Determine the type of the data on the stack.
1345 *
1346 * The ACTION_TYPE_OF action pops one object from the stack,
1347 * determines its type, and push the name of the type back
1348 * on the stack as a string.
1349 *
1350 * It is suggested to use one of sswf::Action::ACTION_CAST_OBJECT
1351 * or sswf::Action::ACTION_INSTANCE_OF isntead.
1352 *
1353 * If you need to keep the data also, use the
1354 * sswf::Action::ACTION_DUPLICATE first.
1355 *
1356 * The possible types are:
1357 *
1358 * \code
1359 * number
1360 * boolean
1361 * string
1362 * object
1363 * movieclip
1364 * null
1365 * undefined
1366 * function
1367 * \endcode
1368 *
1369 * \sa sswf::Action::ACTION_CAST_OBJECT
1370 * \sa sswf::Action::ACTION_INSTANCE_OF
1371 * \sa <a href="../SWFalexref.html#action_type_of">SWF Alexis' Reference—Type Of</a>
1372 *
1373 * <hr>
1374 */
1375
1376
1377 /** \var sswf::Action::ACTION_GET_TARGET
1378 *
1379 * \brief Make this object the target.
1380 *
1381 * Get the path to the specified sprite and make it the
1382 * target (as with sswf::Action::ACTION_SET_TARGET2.)
1383 *
1384 * This function lets you specify a sprite instead of a
1385 * path which may be difficult to determine in some circumstances.
1386 *
1387 * \sa sswf::Action::ACTION_SET_TARGET
1388 * \sa sswf::Action::ACTION_SET_TARGET2
1389 * \sa sswf::Action::ACTION_WITH
1390 * \sa <a href="../SWFalexref.html#action_get_target">SWF Alexis' Reference—Get Target</a>
1391 *
1392 * <hr>
1393 */
1394
1395
1396 /** \var sswf::Action::ACTION_ENUMERATE
1397 *
1398 * \brief Enumerate an object or an array.
1399 *
1400 * The ACTION_ENUMERATE action pops an object, stack a NULL and
1401 * then stacks the object member names and corresponding values.
1402 *
1403 * This can be used with either an object or an array. In case
1404 * of an array, the indices replace the member names.
1405 *
1406 * Unfortunately, what is being enumerated cannot as is be used
1407 * to create a new object since there is no way to know how
1408 * many entries have been enumerated without first going through
1409 * the entire stack! Otherwise, the stack looks like what the
1410 * sswf::Action::ACTION_DECLARE_OBJECT accepts as parameters.
1411 *
1412 * \sa sswf::Action::ACTION_DECLARE_ARRAY
1413 * \sa sswf::Action::ACTION_DECLARE_OBJECT
1414 * \sa sswf::Action::ACTION_ENUMERATE_OBJECT
1415 * \sa <a href="../SWFalexref.html#action_enumerate">SWF Alexis' Reference—Enumerate</a>
1416 *
1417 * <hr>
1418 */
1419
1420
1421 /** \var sswf::Action::ACTION_ADD_TYPED
1422 *
1423 * \brief Add according to the operand types.
1424 *
1425 * The ACTION_ADD_TYPED action pops two objects and add them according
1426 * to their type. If both variables are strings, concatenate them.
1427 * If one of the variables is a floating point, convert the other
1428 * to a floating point if not already a floating point, then add them
1429 * and put the addition result back on the stack. If both are integers,
1430 * add them and put the result back on the stack.
1431 *
1432 * This is the prefered way to convert the + operator of ActionScript
1433 * since it follows the ECMA specification.
1434 *
1435 * \sa sswf::Action::ACTION_ADD
1436 * \sa sswf::Action::ACTION_SUBTRACT
1437 * \sa <a href="../SWFalexref.html#action_add_typed">SWF Alexis' Reference—Add <i>(Typed)</i></a>
1438 *
1439 * <hr>
1440 */
1441
1442
1443 /** \var sswf::Action::ACTION_LESS_THAN_TYPED
1444 *
1445 * \brief Compare according to the operand types.
1446 *
1447 * The ACTION_LESS_THAN_TYPED action pops two objects and compare
1448 * them according to their type.
1449 *
1450 * This is the prefered way to convert the < operator of ActionScript
1451 * since it follows the ECMA specification.
1452 *
1453 * \sa sswf::Action::ACTION_EQUAL
1454 * \sa sswf::Action::ACTION_EQUAL_TYPED
1455 * \sa sswf::Action::ACTION_STRICT_EQUAL
1456 * \sa sswf::Action::ACTION_LESS_THAN
1457 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
1458 * \sa sswf::Action::ACTION_LOGICAL_NOT
1459 * \sa sswf::Action::ACTION_LOGICAL_AND
1460 * \sa sswf::Action::ACTION_LOGICAL_OR
1461 * \sa <a href="../SWFalexref.html#action_less_than_typed">SWF Alexis' Reference—Less Than <i>(Typed)</i></a>
1462 *
1463 * <hr>
1464 */
1465
1466
1467 /** \var sswf::Action::ACTION_EQUAL_TYPED
1468 *
1469 * \brief Compare according to the operand types.
1470 *
1471 * The ACTION_EQUAL_TYPED action pops two objects and compare
1472 * them according to their type.
1473 *
1474 * This is the prefered way to convert the == operator of ActionScript
1475 * since it follows the ECMA specification.
1476 *
1477 * \sa sswf::Action::ACTION_EQUAL
1478 * \sa sswf::Action::ACTION_STRICT_EQUAL
1479 * \sa sswf::Action::ACTION_LESS_THAN
1480 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
1481 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
1482 * \sa sswf::Action::ACTION_LOGICAL_NOT
1483 * \sa sswf::Action::ACTION_LOGICAL_AND
1484 * \sa sswf::Action::ACTION_LOGICAL_OR
1485 * \sa <a href="../SWFalexref.html#action_equal_typed">SWF Alexis' Reference—Equal <i>(Typed)</i></a>
1486 *
1487 * <hr>
1488 */
1489
1490
1491 /** \var sswf::Action::ACTION_NUMBER
1492 *
1493 * \brief Converts an object to a number.
1494 *
1495 * The ACTION_NUMBER action calls the method valueOf() of the object
1496 * on the stack and replaces that object with a number.
1497 *
1498 * If the operation fails, <b>undefined</b> is pushed on the stack.
1499 *
1500 * This is a good way to optimize a call to the valueOf() method of
1501 * any object. Also, it works on internal types.
1502 *
1503 * \sa sswf::Action::ACTION_STRING
1504 * \sa sswf::Action::ACTION_CALL_METHOD
1505 * \sa <a href="../SWFalexref.html#action_number">SWF Alexis' Reference—Number</a>
1506 *
1507 * <hr>
1508 */
1509
1510
1511 /** \var sswf::Action::ACTION_STRING
1512 *
1513 * \brief Converts an object to a string.
1514 *
1515 * The ACTION_STRING action calls the method toString() of the object
1516 * on the stack and replaces that object with a string representing
1517 * the object.
1518 *
1519 * If the operation fails, <b>undefined</b> is pushed on the stack.
1520 *
1521 * This is a good way to optimize a call to the toString() method of
1522 * any object. Also, it works on internal types.
1523 *
1524 * \sa sswf::Action::ACTION_STRING
1525 * \sa sswf::Action::ACTION_CALL_METHOD
1526 * \sa <a href="../SWFalexref.html#action_string">SWF Alexis' Reference—String</a>
1527 *
1528 * <hr>
1529 */
1530
1531
1532 /** \var sswf::Action::ACTION_DUPLICATE
1533 *
1534 * \brief Duplicate one element on the stack.
1535 *
1536 * The ACTION_DUPLICATE action pops one element from the stack and
1537 * pushes it back twice.
1538 *
1539 * \sa sswf::Action::ACTION_POP
1540 * \sa sswf::Action::ACTION_SWAP
1541 * \sa <a href="../SWFalexref.html#action_duplicate">SWF Alexis' Reference—Duplicate</a>
1542 *
1543 * <hr>
1544 */
1545
1546
1547 /** \var sswf::Action::ACTION_SWAP
1548 *
1549 * \brief Swap the two last elements on the stack.
1550 *
1551 * The ACTION_SWAP action pops two elements from the stack and push them
1552 * back the other way around.
1553 *
1554 * \sa sswf::Action::ACTION_POP
1555 * \sa sswf::Action::ACTION_SWAP
1556 * \sa <a href="../SWFalexref.html#action_swap">SWF Alexis' Reference—Swap</a>
1557 *
1558 * <hr>
1559 */
1560
1561
1562 /** \var sswf::Action::ACTION_GET_MEMBER
1563 *
1564 * \brief Read the value of an object member.
1565 *
1566 * The ACTION_GET_MEMBER action is similar to the sswf::Action::ACTION_GET_VARIABLE
1567 * but looks within an object for the variable definition and content.
1568 *
1569 * The value of a member can be a function as well as a value.
1570 *
1571 * The member name can be an index when accessing an array.
1572 *
1573 * This action replaces the sswf::Action::ACTION_GET_PROPERTY which used a number to
1574 * access a set of predefined member names.
1575 *
1576 * \sa sswf::Action::ACTION_SET_MEMBER
1577 * \sa sswf::Action::ACTION_GET_PROPERTY
1578 * \sa sswf::Action::ACTION_SET_PROPERTY
1579 * \sa sswf::Action::ACTION_GET_VARIABLE
1580 * \sa sswf::Action::ACTION_SET_VARIABLE
1581 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
1582 * \sa sswf::Action::ACTION_DELETE
1583 * \sa <a href="../SWFalexref.html#action_get_member">SWF Alexis' Reference—Get Member</a>
1584 *
1585 * <hr>
1586 */
1587
1588
1589 /** \var sswf::Action::ACTION_SET_MEMBER
1590 *
1591 * \brief Write the value of an object member.
1592 *
1593 * The ACTION_SET_MEMBER action is similar to the sswf::Action::ACTION_SET_VARIABLE
1594 * but creates the variable inside an object and that is called a member.
1595 *
1596 * The value of a member can be a function as well as a value. In case it is a
1597 * function, it can then be called with the sswf::Action::ACTION_CALL_METHOD
1598 * action.
1599 *
1600 * The member name can be an index when accessing an array.
1601 *
1602 * To get rid of a member, use the sswf::Action::ACTION_DELETE action.
1603 *
1604 * This action replaces the sswf::Action::ACTION_SET_PROPERTY which used a number to
1605 * access a set of predefined member names.
1606 *
1607 * \sa sswf::Action::ACTION_GET_MEMBER
1608 * \sa sswf::Action::ACTION_GET_PROPERTY
1609 * \sa sswf::Action::ACTION_SET_PROPERTY
1610 * \sa sswf::Action::ACTION_GET_VARIABLE
1611 * \sa sswf::Action::ACTION_SET_VARIABLE
1612 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
1613 * \sa sswf::Action::ACTION_DELETE
1614 * \sa <a href="../SWFalexref.html#action_set_member">SWF Alexis' Reference—Set Member</a>
1615 *
1616 * <hr>
1617 */
1618
1619
1620 /** \var sswf::Action::ACTION_INCREMENT
1621 *
1622 * \brief Add 1 to the value at the top of the stack.
1623 *
1624 * The ACTION_INCREMENT action adds one to the value on the stack. The
1625 * stack is expected to be an integer or a floating point value. Another
1626 * object will be converted to a number if possible.
1627 *
1628 * \sa sswf::Action::ACTION_DECREMENT
1629 * \sa <a href="../SWFalexref.html#action_increment">SWF Alexis' Reference—Increment</a>
1630 *
1631 * <hr>
1632 */
1633
1634
1635 /** \var sswf::Action::ACTION_DECREMENT
1636 *
1637 * \brief Subtract 1 from the value at the top of the stack.
1638 *
1639 * The ACTION_DECREMENT action subtracts one to the value on the stack. The
1640 * stack is expected to be an integer or a floating point value. Another
1641 * object will be converted to a number if possible.
1642 *
1643 * \sa sswf::Action::ACTION_DECREMENT
1644 * \sa <a href="../SWFalexref.html#action_decrement">SWF Alexis' Reference—Decrement</a>
1645 *
1646 * <hr>
1647 */
1648
1649
1650 /** \var sswf::Action::ACTION_CALL_METHOD
1651 *
1652 * \brief Call a method on an object.
1653 *
1654 * The ACTION_CALL_METHOD action calls the named method of an object
1655 * with the specified parameters.
1656 *
1657 * This is similar to the sswf::Action::ACTION_CALL_FUNCTION but
1658 * it calls the function defined within an object instead. This means
1659 * that the 'this' parameter will be defined in that function and it
1660 * can be used to access the members of the object.
1661 *
1662 * A call always returns a value. If the method is declared as a
1663 * function returning void (a procedure in effect), the function
1664 * returns <b>undefined</b>.
1665 *
1666 * \sa sswf::Action::ACTION_CALL_FUNCTION
1667 * \sa sswf::Action::ACTION_NEW_METHOD
1668 * \sa sswf::Action::ACTION_NEW
1669 * \sa sswf::Action::ACTION_RETURN
1670 * \sa <a href="../SWFalexref.html#action_call_method">SWF Alexis' Reference—Call Method</a>
1671 *
1672 * <hr>
1673 */
1674
1675
1676 /** \var sswf::Action::ACTION_NEW_METHOD
1677 *
1678 * \brief Create an object and call a constructor.
1679 *
1680 * The ACTION_NEW_METHOD action creates a new instance of an object
1681 * and then initializes it by calling a constructor depending on
1682 * its parameters (constructors can be overloaded in this case.)
1683 *
1684 * This is similar to the ACTION_NEW except that the proper overloaded
1685 * constructor is called automatically.
1686 *
1687 * \sa sswf::Action::ACTION_CALL_FUNCTION
1688 * \sa sswf::Action::ACTION_NEW_METHOD
1689 * \sa sswf::Action::ACTION_NEW
1690 * \sa sswf::Action::ACTION_RETURN
1691 * \sa <a href="../SWFalexref.html#action_new_method">SWF Alexis' Reference—New Method</a>
1692 *
1693 * <hr>
1694 */
1695
1696
1697 /** \var sswf::Action::ACTION_INSTANCE_OF
1698 *
1699 * \brief Check wether an object of an instance of a specified class.
1700 *
1701 * The ACTION_INSTANCE_OF action checks whether a given object was created
1702 * from a given class. Since everything in SWF is an object (including a
1703 * classes, interfaces, etc.), I'm not too sure how this works. I suppose
1704 * they can keep a link to the original object used to create another and
1705 * each object has a set of inheritance in case of multiple inheritance
1706 * (which should only happen with interfaces.)
1707 *
1708 * \sa sswf::Action::ACTION_CAST_OBJECT
1709 * \sa sswf::Action::ACTION_TYPE_OF
1710 * \sa <a href="../SWFalexref.html#action_instance_of">SWF Alexis' Reference—Instance Of</a>
1711 *
1712 * <hr>
1713 */
1714
1715
1716 /** \var sswf::Action::ACTION_ENUMERATE_OBJECT
1717 *
1718 * \brief Enumerate an object or an array.
1719 *
1720 * The ACTION_ENUMERATE_OBJECT action pops an object, stacks a NULL
1721 * and then stacks the object member names on the stack.
1722 *
1723 * This can be used with either an object or an array. In case
1724 * of an array, the indices replace the member names.
1725 *
1726 * \sa sswf::Action::ACTION_DECLARE_ARRAY
1727 * \sa sswf::Action::ACTION_DECLARE_OBJECT
1728 * \sa sswf::Action::ACTION_ENUMERATE
1729 * \sa <a href="../SWFalexref.html#action_enumerate_object">SWF Alexis' Reference—Enumerate Object</a>
1730 *
1731 * <hr>
1732 */
1733
1734
1735 /** \var sswf::Action::ACTION_AND
1736 *
1737 * \brief Apply a bitwise AND between two numbers.
1738 *
1739 * The ACTION_AND action applies a bitwise AND between two integer numbers.
1740 *
1741 * The SWF player does not support bitwise AND between floating points.
1742 *
1743 * This is the & operator in ActionScript.
1744 *
1745 * \sa sswf::Action::ACTION_LOGICAL_AND
1746 * \sa sswf::Action::ACTION_LOGICAL_OR
1747 * \sa sswf::Action::ACTION_LOGICAL_NOT
1748 * \sa sswf::Action::ACTION_OR
1749 * \sa sswf::Action::ACTION_XOR
1750 * \sa <a href="../SWFalexref.html#action_and">SWF Alexis' Reference—And</a>
1751 *
1752 * <hr>
1753 */
1754
1755
1756 /** \var sswf::Action::ACTION_OR
1757 *
1758 * \brief Apply a bitwise OR between two numbers.
1759 *
1760 * The ACTION_OR action applies a bitwise OR between two integer numbers.
1761 *
1762 * The SWF player does not support bitwise OR between floating points.
1763 *
1764 * This is the | operator in ActionScript.
1765 *
1766 * \sa sswf::Action::ACTION_LOGICAL_AND
1767 * \sa sswf::Action::ACTION_LOGICAL_OR
1768 * \sa sswf::Action::ACTION_LOGICAL_NOT
1769 * \sa sswf::Action::ACTION_AND
1770 * \sa sswf::Action::ACTION_XOR
1771 * \sa <a href="../SWFalexref.html#action_or">SWF Alexis' Reference—Or</a>
1772 *
1773 * <hr>
1774 */
1775
1776
1777 /** \var sswf::Action::ACTION_XOR
1778 *
1779 * \brief Apply a bitwise XOR between two numbers.
1780 *
1781 * The ACTION_XOR action applies a bitwise XOR between two integer numbers.
1782 *
1783 * The SWF player does not support bitwise XOR between floating points.
1784 *
1785 * This is the ^ operator in ActionScript.
1786 *
1787 * \sa sswf::Action::ACTION_LOGICAL_AND
1788 * \sa sswf::Action::ACTION_LOGICAL_OR
1789 * \sa sswf::Action::ACTION_LOGICAL_NOT
1790 * \sa sswf::Action::ACTION_AND
1791 * \sa sswf::Action::ACTION_OR
1792 * \sa <a href="../SWFalexref.html#action_xor">SWF Alexis' Reference—XOr</a>
1793 *
1794 * <hr>
1795 */
1796
1797
1798 /** \var sswf::Action::ACTION_SHIFT_LEFT
1799 *
1800 * \brief Shift bits to the left.
1801 *
1802 * The ACTION_SHIFT_LEFT action shifts the bits of an integer to the left.
1803 *
1804 * The SWF player does not support shifting floating points.
1805 *
1806 * This is the << operator in ActionScript.
1807 *
1808 * \sa sswf::Action::ACTION_SHIFT_RIGHT
1809 * \sa <a href="../SWFalexref.html#action_shift_left">SWF Alexis' Reference—Shift Left</a>
1810 *
1811 * <hr>
1812 */
1813
1814
1815 /** \var sswf::Action::ACTION_SHIFT_RIGHT
1816 *
1817 * \brief Shift bits to the right.
1818 *
1819 * The ACTION_SHIFT_RIGHT action shifts the bits of an integer to the right.
1820 *
1821 * The integer is taken as a signed integer. This means that a negative integer
1822 * remains negative and a positive integer remains positive.
1823 *
1824 * The SWF player does not support shifting floating points.
1825 *
1826 * This is the >> operator in ActionScript.
1827 *
1828 * \sa sswf::Action::ACTION_SHIFT_RIGHT
1829 * \sa <a href="../SWFalexref.html#action_shift_right">SWF Alexis' Reference—Shift Right</a>
1830 *
1831 * <hr>
1832 */
1833
1834
1835 /** \var sswf::Action::ACTION_SHIFT_RIGHT_UNSIGNED
1836 *
1837 * \brief Shift bits to the right.
1838 *
1839 * The ACTION_SHIFT_RIGHT_UNSIGNED action shifts the bits of an integer to the right.
1840 *
1841 * The integer is taken as an unsigned integer. This means that the most significant
1842 * bits are cleared as the value is being shifted.
1843 *
1844 * The SWF player does not support shifting floating points.
1845 *
1846 * This is the >>> operator in ActionScript.
1847 *
1848 * \sa sswf::Action::ACTION_SHIFT_RIGHT
1849 * \sa <a href="../SWFalexref.html#action_shift_right_unsigned">SWF Alexis' Reference—Shift Right Unsigned</a>
1850 *
1851 * <hr>
1852 */
1853
1854
1855 /** \var sswf::Action::ACTION_STRICT_EQUAL
1856 *
1857 * \brief Compare two objects without conversions.
1858 *
1859 * The ACTION_STRICT_EQUAL compare two objects without trying to convert one or the
1860 * other so they match. For instance, 0 == "0" is considered true, but 0 === "0"
1861 * is not. This action represents the === operation of ActionScript.
1862 *
1863 * \sa sswf::Action::ACTION_EQUAL
1864 * \sa sswf::Action::ACTION_EQUAL_TYPED
1865 * \sa sswf::Action::ACTION_LESS_THAN
1866 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
1867 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
1868 * \sa sswf::Action::ACTION_LOGICAL_NOT
1869 * \sa sswf::Action::ACTION_LOGICAL_AND
1870 * \sa sswf::Action::ACTION_LOGICAL_OR
1871 * \sa <a href="../SWFalexref.html#action_strict_equal">SWF Alexis' Reference—Strict Equal</a>
1872 *
1873 * <hr>
1874 */
1875
1876
1877 /** \var sswf::Action::ACTION_GREATER_THAN_TYPED
1878 *
1879 * \brief Compare according to the operand types.
1880 *
1881 * The ACTION_GREATER_THAN_TYPED action pops two objects and compare
1882 * them according to their type.
1883 *
1884 * This is the prefered way to convert the > operator of ActionScript
1885 * since it follows the ECMA specification.
1886 *
1887 * \sa sswf::Action::ACTION_EQUAL
1888 * \sa sswf::Action::ACTION_EQUAL_TYPED
1889 * \sa sswf::Action::ACTION_STRICT_EQUAL
1890 * \sa sswf::Action::ACTION_LESS_THAN
1891 * \sa sswf::Action::ACTION_LESS_THAN_TYPED
1892 * \sa sswf::Action::ACTION_LOGICAL_NOT
1893 * \sa sswf::Action::ACTION_LOGICAL_AND
1894 * \sa sswf::Action::ACTION_LOGICAL_OR
1895 * \sa <a href="../SWFalexref.html#action_greater_than_typed">SWF Alexis' Reference—Greater Than <i>(Typed)</i></a>
1896 *
1897 * <hr>
1898 */
1899
1900
1901 /** \var sswf::Action::ACTION_STRING_GREATER_THAN
1902 *
1903 * \brief Test whether two strings are ordered.
1904 *
1905 * The ACTION_STRING_GREATER_THAN pops two strings from the stack, compare them for order
1906 * and pushes the result back on the stack.
1907 *
1908 * This action will ensure that two strings which represent numbers are still compared
1909 * as strings and not numbers.
1910 *
1911 * \note
1912 * This action should not be used anymore. It was deprecated. Instead, you should use
1913 * the ACTION_GREATER_THAN_TYPED action which ensures proper casting (as expected in the
1914 * JavaScript reference—ECMA).
1915 *
1916 * \sa sswf::Action::ACTION_GREATER_THAN_TYPED
1917 * \sa sswf::Action::ACTION_STRING_EQUAL
1918 * \sa sswf::Action::ACTION_STRICT_EQUAL
1919 * \sa sswf::Action::ACTION_STRING_LESS_THAN
1920 * \sa <a href="../SWFalexref.html#action_string_greater_than">SWF Alexis' Reference—String Greater Than</a>
1921 *
1922 * <hr>
1923 */
1924
1925
1926 /** \var sswf::Action::ACTION_EXTENDS
1927 *
1928 * \brief Mark a class as the extension of another.
1929 *
1930 * The ACTION_EXTENDS action is used to define the inheritance of a
1931 * class. It is used to implement the ActionScript:
1932 *
1933 * \code
1934 * class A { ...};
1935 * class B extends A { ... };
1936 * \endcode
1937 *
1938 * \sa sswf::Action::ACTION_IMPLEMENTS
1939 * \sa <a href="../SWFalexref.html#action_extends">SWF Alexis' Reference—Extends</a>
1940 *
1941 * <hr>
1942 */
1943
1944
1945 /** \var sswf::Action::ACTION_GOTO_FRAME
1946 *
1947 * \brief Change the frame number of the playback.
1948 *
1949 * The ACTION_GOTO_FRAME action changes the frame number of the playback.
1950 * This means the playback of the movie continues at the frame specified
1951 * by the ACTION_GOTO_FRAME. The frame is hard coded in the action so this
1952 * action is not usually very useful unless your frame number is a constant
1953 * number.
1954 *
1955 * Use the sswf::Action::ACTION_GOTO_EXPRESSION instead to be able to use
1956 * a variable frame number.
1957 *
1958 * \sa sswf::Action::ACTION_GOTO_LABEL
1959 * \sa sswf::Action::ACTION_GOTO_EXPRESSION
1960 * \sa <a href="../SWFalexref.html#action_goto_frame">SWF Alexis' Reference—Goto Frame</a>
1961 *
1962 * <hr>
1963 */
1964
1965
1966 /** \var sswf::Action::ACTION_URL
1967 *
1968 * \brief Load the specified URL.
1969 *
1970 * The ACTION_URL action loads the specified URL.
1971 *
1972 * The target specifies how the new URL should be loaded. "_level1"
1973 * means that the SWF movie is replaced. "_top" replaces the entire
1974 * window. "_blank" opens a new window. A frame name will reload that
1975 * frame.
1976 *
1977 * It is also possible to execute some Javascript code using the
1978 * javascript: protocol instead of http or https.
1979 *
1980 * \sa sswf::Action::ACTION_URL2
1981 * \sa <a href="../SWFalexref.html#action_get_url">SWF Alexis' Reference—Get URL</a>
1982 *
1983 * <hr>
1984 */
1985
1986
1987 /** \var sswf::Action::ACTION_STORE_REGISTER
1988 *
1989 * \brief Store the value currently at the top of the stack in a register.
1990 *
1991 * The ACTION_STORE_REGISTER action saves the value currently at the
1992 * top of the stack in the specified register. The value on the stack
1993 * is not popped. The maximum register number varies depending on the
1994 * version of the player and whether you are in a function or the
1995 * global space.
1996 *
1997 * A register can later be read with an sswf::Action::ACTION_PUSH_DATA.
1998 *
1999 * \sa sswf::Action::ACTION_PUSH_DATA
2000 * \sa <a href="../SWFalexref.html#action_store_register">SWF Alexis' Reference—Store Register</a>
2001 *
2002 * <hr>
2003 */
2004
2005
2006 /** \var sswf::Action::ACTION_DECLARE_DICTIONARY
2007 *
2008 * \brief Declare a special array of strings which can later be pushed on the stack.
2009 *
2010 * The ACTION_DECLARE_DICTIONARY action is a list of null terminated strings.
2011 * These strings are numbered from 0 to 65534 and can later be pushed on the
2012 * stack with an sswf::Action::ACTIO_PUSH_DATA.
2013 *
2014 * This is used to compress your movies. If the same rather long string needs to
2015 * be pushed onto the stack many times, repeating it in each Push Data would
2016 * generate a larger action script than putting it once in a dictionary and
2017 * pushing it using the special "push a dictionary entry" feature.
2018 *
2019 * The gain can be very small. You need to measure the length of the string,
2020 * the overhead of declaring a dictionary and the number of times a string is
2021 * used. If used once, no dictionary is necessary. If the string is one character,
2022 * using the dictionary will actually make you lose 1 byte per Push Data...
2023 *
2024 * \sa sswf::Action::ACTION_PUSH_DATA
2025 * \sa <a href="../SWFalexref.html#action_declare_dictionary">SWF Alexis' Reference—Declare Dictionary</a>
2026 *
2027 * <hr>
2028 */
2029
2030
2031 /** \var sswf::Action::ACTION_STRICT_MODE
2032 *
2033 * \brief Whether the ActionScript engine is strict or not.
2034 *
2035 * The ACTION_STRICT_MODE action sets the strict mode flag to true or false.
2036 *
2037 * When the strict mode is true, more checks are done to ensure that the
2038 * ActionScript running is more compliant to the ECMA specification.
2039 *
2040 * \sa sswf::Action::ACTION_PUSH_DATA
2041 * \sa <a href="../SWFalexref.html#action_strict_mode">SWF Alexis' Reference—Strict Mode</a>
2042 *
2043 * <hr>
2044 */
2045
2046
2047 /** \var sswf::Action::ACTION_WAIT_FOR_FRAME
2048 *
2049 * \brief Wait for the specified frame.
2050 *
2051 * The ACTION_WAIT_FOR_FRAME action is an old action used to wait for
2052 * a frame while loading on a slow modem and such. Thus you could know
2053 * what was loaded to know whether you could display such and such
2054 * sprite.
2055 *
2056 * Often, the actions to execute when the frame was finaly loaded is
2057 * an sswf::Action::ACTION_BRANCH_ALWAYS which skips the actions to
2058 * be executed when the frame was not yet loaded.
2059 *
2060 * There is now ways to check for the frame number and use a regular
2061 * sswf::Action::ACTION_BRANCH_IF_TRUE action instead.
2062 *
2063 * \sa sswf::Action::ACTION_PUSH_DATA
2064 * \sa <a href="../SWFalexref.html#action_wait_for_frame">SWF Alexis' Reference—Wait for Frame</a>
2065 *
2066 * <hr>
2067 */
2068
2069
2070 /** \var sswf::Action::ACTION_SET_TARGET
2071 *
2072 * \brief Apply actions to the specified sprite (or movie).
2073 *
2074 * The ACTION_SET_TARGET action is used to optimize the code or call
2075 * a sub-function which apply functions on what is considered the
2076 * current movie.
2077 *
2078 * This current movie is defined by name with this action. An empty
2079 * name refer to the main movie (the root). When the name of a
2080 * specific sprite is used, then that specific sprite functions
2081 * are called.
2082 *
2083 * \sa sswf::Action::ACTION_GET_TARGET
2084 * \sa sswf::Action::ACTION_SET_TARGET2
2085 * \sa sswf::Action::ACTION_WITH
2086 * \sa <a href="../SWFalexref.html#action_set_target">SWF Alexis' Reference—Set Target</a>
2087 *
2088 * <hr>
2089 */
2090
2091
2092 /** \var sswf::Action::ACTION_GOTO_LABEL
2093 *
2094 * \brief Change the current frame in the playback system.
2095 *
2096 * The ACTION_GOTO_LABEL action requests the current sprite to
2097 * now play starting at the named frame. A frame is named using
2098 * the <a href="../SWFalexref.html#tag_framelabel">FrameLabel</a> tag.
2099 *
2100 * \sa sswf::Action::ACTION_GOTO_EXPRESSION
2101 * \sa sswf::Action::ACTION_GOTO_FRAME
2102 * \sa <a href="../SWFalexref.html#action_goto_label">SWF Alexis' Reference—Goto Label</a>
2103 *
2104 * <hr>
2105 */
2106
2107
2108 /** \var sswf::Action::ACTION_WAIT_FOR_FRAME2
2109 *
2110 * \brief Wait for the specified frame.
2111 *
2112 * The ACTION_WAIT_FOR_FRAME2 action pops one value from the stack.
2113 * This value represents the frame it has to wait for.
2114 *
2115 * The action otherwise has a new of action it has to skip in case
2116 * the frame was not reached yet.
2117 *
2118 * \sa sswf::Action::ACTION_WAIT_FOR_FRAME
2119 * \sa <a href="../SWFalexref.html#action_wait_for_frame_dynamic">SWF Alexis' Reference—Wait for Frame <i>(dynamic)</i></a>
2120 *
2121 * <hr>
2122 */
2123
2124
2125 /** \var sswf::Action::ACTION_DECLARE_FUNCTION2
2126 *
2127 * \brief Declare a function.
2128 *
2129 * The ACTION_DECLARE_FUNCTION2 action creates a user function with
2130 * capabilities as defined in SWF version 7 (i.e. up to 255 registers
2131 * to use instead of local variables and for temporary computations.)
2132 *
2133 * These functions can also pre-define a set of registers to the
2134 * internal variables such as _root, _global and this.
2135 *
2136 * A function declared as void is not expected to return anything
2137 * on the stack. Yet the caller will get an <b>undefined</b> value.
2138 * A function not declared as void is expected to return a valid
2139 * value with the use of the sswf::Action::ACTION_RETURN action.
2140 *
2141 * \sa sswf::Action::ACTION_DECLARE_FUNCTION
2142 * \sa sswf::Action::ACTION_CALL_FUNCTION
2143 * \sa sswf::Action::ACTION_RETURN
2144 * \sa sswf::Action::ACTION_CALL_METHOD
2145 * \sa sswf::Action::ACTION_NEW_METHOD
2146 * \sa sswf::Action::ACTION_NEW
2147 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
2148 *
2149 * <hr>
2150 */
2151
2152
2153 /** \var sswf::Action::ACTION_TRY
2154 *
2155 * \brief Create a try/catch/finaly block.
2156 *
2157 * The ACTION_TRY action is used to create a block of actions to execute safely.
2158 * This means, if an exception occurs, it is possible to catch it. The entire
2159 * block is composed of one try block, zero or more catch blocks and zero or one
2160 * finaly block. There must be one catch or one finaly block. The finaly block is
2161 * always executed. A catch block is executed only if the corresponding exception
2162 * is caught.
2163 *
2164 * Note that internally, there is only one catch. Your compiler may decided to
2165 * offer you a way to catch a specific type of exception by checking the type of
2166 * the exception (see sswf::Action::ACTION_INSTANCE_OF).
2167 *
2168 * \sa sswf::Action::ACTION_THROW
2169 * \sa sswf::Action::ACTION_INSTANCE_OF
2170 * \sa <a href="../SWFalexref.html#action_try">SWF Alexis' Reference—Try</a>
2171 *
2172 * <hr>
2173 */
2174
2175
2176 /** \var sswf::Action::ACTION_WITH
2177 *
2178 * \brief Create a \e With block.
2179 *
2180 * The ACTION_WITH action is a block of actions which react to object names by
2181 * first searching the name specified by the With block.
2182 *
2183 * For instance, if you have an object named MyObject and you want to access
2184 * the field NiceField in that object, you need to use the name:
2185 *
2186 * \code
2187 * v = MyObject.NiceField
2188 * \endcode
2189 *
2190 * In general this is not a problem, but when many fields need to be accessed,
2191 * it is possible to optimize using a \e With block:
2192 *
2193 * \code
2194 * With MyObject
2195 * v = NiceField
2196 * \endcode
2197 *
2198 * In this last case, the variable NiceField is first searched as a variable
2199 * member in the MyObject object.
2200 *
2201 * Note that this technic works to read variable members and modify existing
2202 * variable members. If you need to create a new member, you will need to
2203 * specify the object name.
2204 *
2205 * \note
2206 * A \e With blocks can include another \e With block. Total there can be
2207 * 20 levels of objects defined in this way. Extraneous levels will be
2208 * ignored in V7 and earlier. It should be throwing an exception in V8
2209 * (not tested--according to Macromedia, it already throws in V7...)
2210 *
2211 * \bug
2212 * Note that can also create bugs since you may be accessing the member of
2213 * an object when you wanted to access a global variable instead.
2214 *
2215 * \sa sswf::Action::ACTION_GET_MEMBER
2216 * \sa sswf::Action::ACTION_SET_MEMBER
2217 * \sa sswf::Action::ACTION_GET_PROPERTY
2218 * \sa sswf::Action::ACTION_SET_PROPERTY
2219 * \sa sswf::Action::ACTION_GET_VARIABLE
2220 * \sa sswf::Action::ACTION_SET_VARIABLE
2221 * \sa sswf::Action::ACTION_SET_LOCAL_VARIABLE
2222 * \sa sswf::Action::ACTION_DELETE
2223 * \sa sswf::Action::ACTION_SET_TARGET
2224 * \sa sswf::Action::ACTION_SET_TARGET2
2225 * \sa <a href="../SWFalexref.html#action_with">SWF Alexis' Reference—With</a>
2226 *
2227 * <hr>
2228 */
2229
2230
2231 /** \var sswf::Action::ACTION_PUSH_DATA
2232 *
2233 * \brief Push constants and register data on the stack.
2234 *
2235 * The ACTION_PUSH_DATA action defines a block of data to push on the
2236 * stack.
2237 *
2238 * It is possible to push a constant string, boolean, integer,
2239 * floating point, null and the undefined value.
2240 *
2241 * Also, it is possible to specify a register number to load. This is
2242 * the only way you can load a register set with
2243 * sswf::Action::ACTION_STORE_REGISTER.
2244 *
2245 * To read a variable, you first push its name on the stack using
2246 * this action, then you use the sswf::Action::ACTION_GET_VARIABLE.
2247 *
2248 * \sa sswf::Action::ACTION_STORE_REGISTER
2249 * \sa sswf::Action::ACTION_GET_VARIABLE
2250 * \sa <a href="../SWFalexref.html#action_push_data">SWF Alexis' Reference—Push Data</a>
2251 *
2252 * <hr>
2253 */
2254
2255
2256 /** \var sswf::Action::ACTION_BRANCH_ALWAYS
2257 *
2258 * \brief Change the current execution pointer.
2259 *
2260 * The ACTION_BRANCH_ALWAYS action changes the execution pointer
2261 * by the specified number of bytes. The offset is a signed 16
2262 * bits value. This means the jump is limited to a 64Kb span.
2263 * Note that most ActionScripts should anyway be limited to about
2264 * 32Kb.
2265 *
2266 * \sa sswf::Action::ACTION_STORE_REGISTER
2267 * \sa sswf::Action::ACTION_GET_VARIABLE
2268 * \sa <a href="../SWFalexref.html#action_branch_always">SWF Alexis' Reference—Branch Always</a>
2269 *
2270 * <hr>
2271 */
2272
2273
2274 /** \var sswf::Action::ACTION_URL2
2275 *
2276 * \brief Load the specified URL.
2277 *
2278 * The ACTION_URL2 action loads the specified URL. This is
2279 * similar to ACTION_URL except that the URL itself is taken
2280 * from the stack and thus can dynamically be defined (i.e.
2281 * read from a variable, created using an expression, etc.)
2282 *
2283 * \sa sswf::Action::ACTION_URL
2284 * \sa <a href="../SWFalexref.html#action_get_url2">SWF Alexis' Reference—Get Url2</a>
2285 *
2286 * <hr>
2287 */
2288
2289
2290 /** \var sswf::Action::ACTION_DECLARE_FUNCTION
2291 *
2292 * \brief Declare a function.
2293 *
2294 * The ACTION_DECLARE_FUNCTION action creates a user function with
2295 * capabilities as defined in SWF version 5.
2296 *
2297 * These functions do not support pre-set registers or more than 4
2298 * registers.
2299 *
2300 * A function declared as void is not expected to return anything
2301 * on the stack. Yet the caller will get an <b>undefined</b> value.
2302 * A function not declared as void is expected to return a valid
2303 * value with the use of the sswf::Action::ACTION_RETURN action.
2304 *
2305 * \sa sswf::Action::ACTION_DECLARE_FUNCTION2
2306 * \sa sswf::Action::ACTION_CALL_FUNCTION
2307 * \sa sswf::Action::ACTION_RETURN
2308 * \sa sswf::Action::ACTION_CALL_METHOD
2309 * \sa sswf::Action::ACTION_NEW_METHOD
2310 * \sa sswf::Action::ACTION_NEW
2311 * \sa <a href="../SWFalexref.html#action_declare_function">SWF Alexis' Reference—Declare Function</a>
2312 *
2313 * <hr>
2314 */
2315
2316
2317 /** \var sswf::Action::ACTION_BRANCH_IF_TRUE
2318 *
2319 * \brief Change the current execution pointer if true.
2320 *
2321 * The ACTION_BRANCH_IF_TRUE action branches if the value it pops
2322 * from the stack represents true. A true number is a non-zero
2323 * number. A true string is a non-empty string. Other objects
2324 * may have a toBoolean() function which returns true or false
2325 * according to their type.
2326 *
2327 * The same limitations apply to this branch as for the
2328 * sswf::Action::ACTION_BRANCH_ALWAYS action.
2329 *
2330 * To branch when false, use the sswf::Action::ACTION_LOGICAL_NOT
2331 * right before this branch.
2332 *
2333 * \sa sswf::Action::ACTION_LOGICAL_NOT
2334 * \sa sswf::Action::ACTION_BRANCH_ALWAYS
2335 * \sa sswf::Action::ACTION_CALL_FUNCTION
2336 * \sa sswf::Action::ACTION_RETURN
2337 * \sa sswf::Action::ACTION_CALL_METHOD
2338 * \sa sswf::Action::ACTION_NEW_METHOD
2339 * \sa sswf::Action::ACTION_NEW
2340 * \sa <a href="../SWFalexref.html#action_branch_if_true">SWF Alexis' Reference—Branch If True</a>
2341 *
2342 * <hr>
2343 */
2344
2345
2346 /** \var sswf::Action::ACTION_CALL_FRAME
2347 *
2348 * \brief Call the actions defined in a frame.
2349 *
2350 * The ACTION_CALL_FRAME action is an early bird function definition.
2351 * You should use the sswf::Action::ACTION_DECLARE_FUNCTION and then
2352 * an sswf::Action::ACTION_CALL_FUNCTION instead. This frame calling
2353 * is nothing more than a function call, really. The name or number
2354 * if the frame to call is popped from the stack.
2355 *
2356 * \bug
2357 * This tag takes a size of 0 since it does not need any data and yet
2358 * it has a value over 127.
2359 *
2360 * \sa sswf::Action::ACTION_CALL_FUNCTION
2361 * \sa sswf::Action::ACTION_DECLARE_FUNCTION
2362 * \sa sswf::Action::ACTION_DECLARE_FUNCTION2
2363 * \sa sswf::Action::ACTION_RETURN
2364 * \sa <a href="../SWFalexref.html#action_call_frame">SWF Alexis' Reference—Call Frame</a>
2365 *
2366 * <hr>
2367 */
2368
2369
2370 /** \var sswf::Action::ACTION_GOTO_EXPRESSION
2371 *
2372 * \brief Move the display pointer to the specified frame.
2373 *
2374 * The ACTION_GOTO_EXPRESSION action pops a string or integer from
2375 * the stack and go to the frame.
2376 *
2377 * The action also specifies whether the movie should stop or play.
2378 *
2379 * \sa sswf::Action::ACTION_GOTO_FRAME
2380 * \sa sswf::Action::ACTION_GOTO_LABEL
2381 * \sa <a href="../SWFalexref.html#action_goto_expression">SWF Alexis' Reference—Goto Expression</a>
2382 *
2383 * <hr>
2384 */
2385
2386
2387 /** \var sswf::Action::ACTION_max
2388 *
2389 * \brief The very last valid action.
2390 *
2391 * The ACTION_max definition is used to clamp action numbers valid in an SWF movie.
2392 * Note that this is not the largest action number but instead the maximum action
2393 * number which can possibly be accepted at all time (until the action scheme changes!)
2394 * At this time this value is 255 which is inclusive.
2395 *
2396 * \sa sswf::Action::ACTION_min
2397 *
2398 * <hr>
2399 */
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410 /** \brief Initialize an action.
2411 *
2412 * The Action constructor is used to initialize an action object.
2413 *
2414 * Once an action was created, you cannot change its type. You cannot
2415 * copy an action with the copy constructor or the assignment operator.
2416 * You can however sswf::Action::Duplicate() an action.
2417 *
2418 * The constructor will determine the version of the action. This is
2419 * important to determine the minimum version necessary for that
2420 * action to function in the output SWF animation.
2421 *
2422 * At this time, you can add actions to any tags (but this may change!)
2423 * However, only a few set of tags really support actions:
2424 *
2425 * \li Button
2426 * \li DoAction
2427 * \li DoInitAction
2428 */
Action(TagBase * tag,action_t action)2429 Action::Action(TagBase *tag, action_t action)
2430 : f_action(action), f_tag(tag)
2431 {
2432 //
2433 // TODO: should we put FSCOMMAND2 in version 7 or 8?
2434 // (it appeared in Flash Lite 1.1)
2435 //
2436 static int action_to_version[256] = {
2437 /* 0x00-0x0F */
2438 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, -4, 4, 4, 4, -4, -4,
2439 /* 0x10-0x1F */
2440 4, 4, 4, -4, 4, 4, 0, 4, 4, 0, 0, 0, 4, 4, 0, 0,
2441 /* 0x20-0x2F */
2442 4, 4, 4, 4, 4, 4, 4, 4, 4, -4, 7, 7, 7, 8, 0, 0,
2443 /* 0x30-0x3F */
2444 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 5, 5, 5, 5, 5, 5,
2445 /* 0x40-0x4F */
2446 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2447 /* 0x50-0x5F */
2448 5, 5, 5, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2449 /* 0x60-0x6F */
2450 5, 5, 5, 5, 5, 5, 6, 6, 6, 7, 0, 0, 0, 0, 0, 0,
2451 /* 0x70-0x7F */
2452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2453 /* 0x80-0x8F */
2454 /* 1 2 3 4 5 6 7 8 9 A B C D E F */
2455 0, 1, 0, 1, 0, 0, 0, 5, 5, 6, 1, 1, 3, 4, 7, 7,
2456 /* 0x90-0x9F */
2457 0, 0, 0, 0, 5, 0, 4, 0, 0, 4, 4, 5, 0, 4, 4, 4,
2458 /* 0xA0-0xAF */
2459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2460 /* 0xB0-0xBF */
2461 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2462 /* 0xC0-0xCF */
2463 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2464 /* 0xD0-0xDF */
2465 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2466 /* 0xE0-0xEF */
2467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2468 /* 0xF0-0xFF */
2469 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2470 };
2471
2472 assert(f_tag != 0, "all actions need to have a tag attached to them");
2473 if(f_tag == 0) {
2474 throw ErrorManager::InternalErrorException();
2475 }
2476
2477 if(action == ACTION_LABEL) {
2478 f_min_version = 1;
2479 }
2480 else {
2481 assert(action >= ACTION_min && action <= ACTION_max, "trying to save an invalid action number");
2482
2483 /* I'm not too sure why I wanted the -4, I think that's because these
2484 * instructions are supposedly different in V4.x and V5.x plugins but
2485 * that doesn't seem to really be the case. Anyway, we ignore it with
2486 * the use of the labs() call below.
2487 */
2488 f_min_version = (unsigned char) labs(action_to_version[action]);
2489
2490 assert(f_min_version != 0, "unknown action #%d or undefined version -- please define the version in Action::Action()", action);
2491 }
2492 }
2493
2494
2495
2496 /** \fn sswf::Action::~Action(void)
2497 *
2498 * \brief Clean up the action.
2499 *
2500 * This function exists because the Action class defines virtual function. It
2501 * has otherwise nothing to do here.
2502 */
2503
2504
2505 #if DEBUG
Action(const Action & action)2506 Action::Action(const Action& action)
2507 : f_action(action.f_action) // required by Visual C++ because f_action is constant
2508 {
2509 }
operator =(const Action & action)2510 Action& Action::operator = (const Action& action)
2511 {
2512 return *this;
2513 }
2514 #endif
2515
2516
2517 /** \brief Retrieve the largest register number used.
2518 *
2519 * This function goes through the list of actions defined
2520 * in the Vectors array and determines what the largest
2521 * register used by any of the instructions is in that
2522 * array.
2523 *
2524 * This is necessary to determine the largest used register
2525 * in a version 7 function (See
2526 * <a href="../SWFalexref.html#action_declare_function2">Declare Function (V7)</a>.)
2527 * Before version 7, there could only be 4 registers and you
2528 * never had to determine which ones were used.
2529 *
2530 * \param[in] list A Vectors of actions
2531 *
2532 * \return The largest register number or -1 if the list of
2533 * actions does not use any register.
2534 *
2535 * \sa sswf::Action::GetMaxRegister
2536 */
GetMaximumRegister(const Vectors & list)2537 int Action::GetMaximumRegister(const Vectors& list)
2538 {
2539 Action *a;
2540 int idx, max, r, register_number;
2541 Vectors *sub_list;
2542
2543 register_number = -1;
2544 max = list.Count();
2545 for(idx = 0; idx < max; idx++) {
2546 a = dynamic_cast<Action *>(list.Get(idx));
2547 if(a->f_action >= 128) {
2548 sub_list = a->SubList();
2549 if(sub_list != 0) {
2550 // Function, With and others are nested type
2551 // of entries and they may include higher
2552 // action versions
2553 r = GetMaximumRegister(*sub_list);
2554 if(r > register_number) {
2555 register_number = r;
2556 }
2557 }
2558 }
2559 r = a->GetMaxRegister();
2560 if(r > register_number) {
2561 register_number = r;
2562 }
2563 }
2564
2565 return register_number;
2566 }
2567
2568
2569 /** \brief Retrive the minimum version required to use this list of actions.
2570 *
2571 * This function sweeps through all the actions found in an
2572 * array and determines the minimum SWF version required for the
2573 * script to run.
2574 *
2575 * For instance, the 'New Method' action requires at least a version 5
2576 * Flash Player to work.
2577 */
MinimumListVersion(const Vectors & list)2578 int Action::MinimumListVersion(const Vectors& list)
2579 {
2580 Action *a;
2581 int idx, max, v, version;
2582 Vectors *sub_list;
2583
2584 version = 1;
2585 max = list.Count();
2586 for(idx = 0; idx < max; idx++) {
2587 a = dynamic_cast<Action *>(list.Get(idx));
2588 if(a->f_action >= 128) {
2589 sub_list = a->SubList();
2590 if(sub_list != 0) {
2591 // Function, With and others are nested type
2592 // of entries and they may include higher
2593 // action versions
2594 v = MinimumListVersion(*sub_list);
2595 if(v > version) {
2596 version = v;
2597 }
2598 }
2599 }
2600 // Now Version() is a virtual function since
2601 // ActionTry has to check three sub-lists
2602 v = a->Version();
2603 if(v > version) {
2604 version = v;
2605 }
2606 }
2607
2608 return version;
2609 }
2610
2611
2612 /** \brief Save a list of actions in a Data buffer.
2613 *
2614 * This function is used to save a list of actions in a Data buffer
2615 * for output in a Flash animation.
2616 *
2617 * \param[in] list The list of actions to be saved, it can be NULL
2618 * \param[in] data The Data buffer where the result is saved
2619 * \param[in] extra Another list of actions saved after the 'list' of actions, usually is NULL
2620 *
2621 * \return 0 when no error occured, non-zero otherwise
2622 */
SaveList(const Vectors * list,Data & data,const Vectors * extra)2623 ErrorManager::error_code_t Action::SaveList(const Vectors *list, Data& data, const Vectors *extra)
2624 {
2625 Action *a;
2626 int idx, max;
2627 const Vectors *saved, *lst;
2628 bool has_end;
2629 ErrorManager::error_code_t ec;
2630
2631 saved = extra;
2632 ec = ErrorManager::ERROR_CODE_NONE;
2633
2634 has_end = false;
2635 lst = list;
2636 while(lst != 0) {
2637 max = lst->Count();
2638 for(idx = 0; idx < max; idx++) {
2639 if(has_end) {
2640 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_ENDED_ACTION_SCRIPT, "action END found before the end of your action script."));
2641 }
2642
2643 a = dynamic_cast<Action *>(lst->Get(idx));
2644
2645 //printf("Action[%d] %p: id %d, tag = %p\n", idx, a, a->f_action, a->f_tag);
2646
2647 // the offset is necessary to compute offsets of branch instructions
2648 // and also the With operator
2649 a->f_offset = data.ByteSize();
2650
2651 if(a->f_action != ACTION_LABEL) {
2652 // there is nothing to save in a label
2653 ec = ErrorManager::KeepFirst(ec, a->Save(data));
2654 if(a->f_action == ACTION_END) {
2655 has_end = true;
2656 }
2657 }
2658 }
2659 lst = extra;
2660 extra = 0;
2661 }
2662 if(!has_end) {
2663 data.PutByte(Action::ACTION_END); // end the list of actions
2664 }
2665
2666
2667 /* now we do the 2nd pass! */
2668 lst = list;
2669 while(lst != 0) {
2670 max = lst->Count();
2671 for(idx = 0; idx < max; idx++) {
2672 a = dynamic_cast<Action *>(lst->Get(idx));
2673 ec = ErrorManager::KeepFirst(ec, a->Save2ndPass(*lst, data));
2674 }
2675 lst = saved;
2676 saved = 0;
2677 }
2678
2679 return ec;
2680 }
2681
2682
2683 /** \brief Save the action in a Data buffer.
2684 *
2685 * This function saves 'this' Action in the specified Data buffer.
2686 *
2687 * Simple actions have their byte code saved and the function returns.
2688 *
2689 * Composed actions have their SaveData() virtual function called.
2690 *
2691 * Also, actions which can include sub-ations (such as a Function or
2692 * a With action) get their SubList() saved as well.
2693 *
2694 * The result in an SWF animation just looks like a long list of
2695 * byte codes. The reality is that this technique generates blocks
2696 * of actions.
2697 *
2698 * \param[in] data The data buffer where the actions need to be saved
2699 */
Save(Data & data)2700 ErrorManager::error_code_t Action::Save(Data& data)
2701 {
2702 Data sub_data, nested_data;
2703 Vectors *sub_list;
2704 ErrorManager::error_code_t ec;
2705
2706 ec = ErrorManager::ERROR_CODE_NONE;
2707
2708 data.PutByte(f_action);
2709
2710 if(f_action >= 128) {
2711 sub_list = SubList();
2712 if(sub_list != 0) { // Function & With are nested type of entries
2713 ec = SaveList(sub_list, nested_data);
2714
2715 // get rid of the ACTION_END
2716 nested_data.SetSize(nested_data.GetSize() - CHAR_BIT);
2717
2718 if(nested_data.ByteSize() >= USHRT_MAX) {
2719 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_ACTION_OVERFLOW, "too many nested instructions; length overflow."));
2720 }
2721 }
2722
2723 ec = ErrorManager::KeepFirst(ec, SaveData(sub_data, nested_data));
2724 data.PutShort((short) sub_data.ByteSize());
2725 data.Append(sub_data);
2726
2727 if(nested_data.ByteSize() > 0) {
2728 data.Append(nested_data);
2729 }
2730 }
2731
2732 return ec;
2733 }
2734
2735
2736 /** \brief Query for the Vectors of sub-actions.
2737 *
2738 * By default, this function returns a NULL pointer. Actions which support
2739 * sub-actions (such as a ActionFunction or ActionWith) will return their
2740 * array of sub-actions.
2741 *
2742 * return A pointer to a list of actions or NULL
2743 */
SubList(void)2744 Vectors *Action::SubList(void)
2745 {
2746 return 0;
2747 }
2748
2749
2750 /** \brief Save a string in a way compatible to the actions.
2751 *
2752 * This functions saves a string in the Data buffer in a way that
2753 * the SWF actions can read it.
2754 *
2755 * The function simply calls the SaveString() of the corresponding tag
2756 * thus converting the string as required for a version 5 or earlier
2757 * movie. Strings are otherwise expected to be in UTF-8.
2758 *
2759 * \param[in] data The Data buffer where the string is to be saved
2760 * \param[in] string The string to save in the Data buffer
2761 *
2762 * \return The size of the string not including the null terminator,
2763 * or -1 if the function failed
2764 */
SaveString(Data & data,const char * string)2765 ErrorManager::error_code_t Action::SaveString(Data& data, const char *string)
2766 {
2767 return f_tag->SaveString(data, string);
2768 }
2769
2770
2771 /** \brief Save extraneous data.
2772 *
2773 * All the actions having a byte code larger than 127 include extra-data.
2774 *
2775 * These actions need to overload this function and save these extraneous data
2776 * when requested to do so.
2777 *
2778 * The default function asserts.
2779 *
2780 * \note
2781 * This function is not a pure virtual because actions with a byte code of 0 to
2782 * 127 do not need to be derived.
2783 *
2784 * \param[in] data The Data buffer where the extraneous information is to be saved
2785 * \param[in] nested_data When the action supports sub-actions, the Data buffer
2786 * where these sub-actions have been saved
2787 */
SaveData(Data & data,Data & nested_data)2788 ErrorManager::error_code_t Action::SaveData(Data& data, Data& nested_data)
2789 {
2790 assert(0, "the action 0x%02X which has an action number of 128 or more needs to overload the SaveData() function", f_action);
2791 OnError(ErrorManager::ERROR_CODE_INTERNAL_ERROR, "the action 0x%02X which has an action number of 128 or more needs to overload the SaveData() function", f_action);
2792 return ErrorManager::ERROR_CODE_INTERNAL_ERROR;
2793 }
2794
2795
2796 /** \brief Last chance for an action to save itself right.
2797 *
2798 * This function is called after all the actions have been
2799 * saved in a list of actions (i.e. sswf::Action::SaveList()
2800 * calls sswf::Action::Save() on all the actions of a list
2801 * and then sswf::Action::Save2ndPass().)
2802 *
2803 * At this time, the only action which requires this second
2804 * pass is the sswf::ActionBranch. It will search for a
2805 * label and save the proper offset from itself to the
2806 * label.
2807 *
2808 * \bug
2809 * The Data buffer should not be grown by the Save2ndPass().
2810 * Instead it should be tweaked (i.e. some bytes overwritten
2811 * as required.)
2812 *
2813 * \param[in] list The list of all the actions being saved
2814 * \param[in] data The Data buffer where the actions were saved
2815 */
Save2ndPass(const Vectors & list,Data & data)2816 ErrorManager::error_code_t Action::Save2ndPass(const Vectors& list, Data& data)
2817 {
2818 /* most actions don't require a 2nd pass */
2819 return ErrorManager::ERROR_CODE_NONE;
2820 }
2821
2822
2823 /** \brief Create a clone of 'this' Action.
2824 *
2825 * This function creates a clone of 'this' Action.
2826 *
2827 * The function knows how to create a new Action which is a clone of this
2828 * Action.
2829 *
2830 * Actions with extraneous data will overwrite this function and
2831 * duplicate their extraneous data as required.
2832 *
2833 * \note
2834 * This function needs to be used instead of the copy operator
2835 * since depending on the type of action, the result will be
2836 * different.
2837 *
2838 * For example, if the action to duplicate is an ActionBranch
2839 * you would need to do a new ActionBranch and not a new Action.
2840 * The Duplicate function takes care of that for you.
2841 *
2842 * \return A new action pointer
2843 */
Duplicate(void) const2844 Action *Action::Duplicate(void) const
2845 {
2846 // errors are checked in the object which attach this action to its
2847 // memory manager
2848 return new Action(f_tag, f_action);
2849 }
2850
2851
2852 /** \fn unsigned long sswf::Action::Offset(void) const
2853 *
2854 * \brief Retrieve the offset position of this action.
2855 *
2856 * The position of an action can be used to compute different
2857 * offsets such as the ActionBranch offset to get the current
2858 * ActionScript pointer to a specific position in the
2859 * script.
2860 *
2861 * \return The offset in bytes of this action
2862 */
2863
2864
2865 /** \fn virtual unsigned char sswf::Action::Version(void) const
2866 *
2867 * \brief Retrieve the minimum version required for this action.
2868 *
2869 * The minimum version required for any action is defined on
2870 * creation of the action. The sswf::Action::Action(TagBase *tag, action_t action)
2871 * function has a table which tells it the minimum SWF version
2872 * required for such and such action to work thus you can query
2873 * this value at any time.
2874 *
2875 * \return The minimum version required for this action to work
2876 */
2877
2878
2879
2880
2881 /** \brief Send an error to the error manager.
2882 *
2883 * This function calls the
2884 * sswf::ErrorManager::OnError(error_code_t errcode, const char *message, va_list ap)
2885 * function whenever possible.
2886 *
2887 * The function will not be called if the action was not given a valid
2888 * tag object pointer on creation.
2889 *
2890 * \param[in] errcode The error code that this call represents
2891 * \param[in] message The message of this error
2892 * \param[in] ... The parameters to the message
2893 *
2894 * \return Usually the input errcode parameter
2895 */
OnError(ErrorManager::error_code_t errcode,const char * message,...) const2896 ErrorManager::error_code_t Action::OnError(ErrorManager::error_code_t errcode, const char *message, ...) const
2897 {
2898 va_list ap;
2899 va_start(ap, message);
2900 ErrorManager::error_code_t ec = f_tag->OnError(errcode, message, ap);
2901 va_end(ap);
2902
2903 return ec;
2904 }
2905
2906
2907
2908 /** \brief Search for a label within a list of actions.
2909 *
2910 * A special SSWF Action is the Label Action. The label action
2911 * is NOT saved in the output SWF animation files. However, it is
2912 * required to allow branches to jump from one place to another
2913 * without the burden of using just offsets to know where the
2914 * label would otherwise be.
2915 *
2916 * The ActionBranch will search for labels.
2917 *
2918 * \note
2919 * The SSWF implementation never allowed a branch to jump to a
2920 * label defined outside of the block of actions where it (the
2921 * branch) is defined. This conforms to version 6 of SWF.
2922 *
2923 * \param[in] list The list of actions to be searched
2924 * \param[in] label The label to be searched
2925 *
2926 * \return A pointer to an ActionLabel or NULL when not found
2927 */
FindLabel(const Vectors & list,const char * label)2928 ActionLabel *Action::FindLabel(const Vectors& list, const char *label)
2929 {
2930 Action *a;
2931 ActionLabel *l;
2932 int idx;
2933
2934 if(label == 0) {
2935 return 0;
2936 }
2937
2938 idx = list.Count();
2939 while(idx > 0) {
2940 idx--;
2941 a = dynamic_cast<Action *>(list.Get(idx));
2942 if(a->f_action == ACTION_LABEL) {
2943 l = dynamic_cast<ActionLabel *>(a);
2944 if(l->GetLabel() != 0) if(strcasecmp(l->GetLabel(), label) == 0) {
2945 return l;
2946 }
2947 }
2948 }
2949
2950 return 0;
2951 }
2952
2953
2954
2955 ////////////////////////////// Action BRANCH
2956
2957 /** \class sswf::ActionBranch
2958 *
2959 * \brief An action to change the execution pointer.
2960 *
2961 * The ActionBranch class is used to create a branch or jump from one
2962 * place to another in your ActionScript. Depending on the type of
2963 * Branch that you define, it will always be taken, or it will be
2964 * taken only when the current value on the stack is true.
2965 *
2966 * By default, if you do not specify the type of branch, it will
2967 * always branch.
2968 *
2969 * \sa <a href="../SWFalexref.html#action_branch_always">SWF Alexis' Reference—Branch Always</a>
2970 * \sa <a href="../SWFalexref.html#action_branch_if_true">SWF Alexis' Reference—Branch If True</a>
2971 */
2972
2973 /** \brief Initialize an branch action.
2974 *
2975 * This function initializes an ActionBranch object. You can specify which
2976 * action whether you want the branch to be conditional or not.
2977 *
2978 * \param[in] tag The tag in which this action is being created
2979 * \param[in] action The branch to be created, one of: ACTION_BRANCH_ALWAYS
2980 * or ACTION_BRANCH_IF_TRUE
2981 */
ActionBranch(TagBase * tag,action_t action)2982 ActionBranch::ActionBranch(TagBase *tag, action_t action)
2983 : Action(tag, action)
2984 {
2985 assert(action == ACTION_BRANCH_ALWAYS || action == ACTION_BRANCH_IF_TRUE, "The ActionBranch expects ACTION_BRANCH_ALWAYS or ACTION_BRANCH_IF_TRUE.");
2986
2987 if(action != ACTION_BRANCH_ALWAYS && action != ACTION_BRANCH_IF_TRUE) {
2988 throw ErrorManager::InternalErrorException();
2989 }
2990
2991 f_label = 0;
2992 }
2993
2994
2995 /** \brief Set the label this branch needs to branch to.
2996 *
2997 * This function defines the label this branch needs to branch to. This
2998 * label will be searched in the same block the ActionBranch is inserted
2999 * in. (note that their is no 'if' block in byte code ActionScript.)
3000 *
3001 * There should be an ActionLabel for each different label defined in
3002 * ActionBranch objects.
3003 *
3004 * \param[in] label The label to branch to
3005 */
SetLabel(const char * label)3006 void ActionBranch::SetLabel(const char *label)
3007 {
3008 MemFree(f_label);
3009 f_label = StrDup(label);
3010 }
3011
3012
3013
3014 /** \brief Duplicate an ActionBranch object.
3015 *
3016 * This function creates a new ActionBranch and copies the label from this
3017 * ActionBranch to the new one.
3018 *
3019 * \return The ActionBranch copy
3020 */
Duplicate(void) const3021 Action *ActionBranch::Duplicate(void) const
3022 {
3023 ActionBranch *a;
3024
3025 a = new ActionBranch(Tag(), f_action);
3026 if(f_label != 0) {
3027 a->SetLabel(f_label);
3028 }
3029
3030 return a;
3031 }
3032
3033
3034 /** \brief Save a branch offset placeholder.
3035 *
3036 * This function saves 2 bytes which represent the offset
3037 * where the branch needs to go.
3038 *
3039 * Since at this time we cannot be sure of the exact offset
3040 * (forward offset are not yet known), we just save an offset
3041 * of zero. The Save2ndPass() will save the real offset.
3042 *
3043 * \param[in] data The Data buffer where the offset is saved
3044 * \param[in] nested_data Branches have no nested data
3045 */
SaveData(Data & data,Data & nested_data)3046 ErrorManager::error_code_t ActionBranch::SaveData(Data& data, Data& nested_data)
3047 {
3048 data.PutShort(0); // unknown offset yet (we do it on the 2nd pass)
3049 return ErrorManager::ERROR_CODE_NONE;
3050 }
3051
3052
3053 /** \brief Save the real branch offset.
3054 *
3055 * This function searches the whole list of actions for the label
3056 * specified in the branch. If the label cannot be found, this is an
3057 * error and the function fails.
3058 *
3059 * When the label is found, the offset to that label is read and
3060 * used to compute the offset we need to save in the branch byte codes.
3061 *
3062 * If the branch cannot be generated because the offset is out of bounds
3063 * (i.e. smaller than 0x8000 or larger than 0x7FFF) then an error is
3064 * generated and the function fails.
3065 *
3066 * \param[in] list The list of actions where the label is searched
3067 * \param[in] data The Data buffer where the resulting offset is saved
3068 */
Save2ndPass(const Vectors & list,Data & data)3069 ErrorManager::error_code_t ActionBranch::Save2ndPass(const Vectors& list, Data& data)
3070 {
3071 ActionLabel *l;
3072 long offset;
3073
3074 // look for that label...
3075 l = FindLabel(list, f_label);
3076 if(l == 0) {
3077 return OnError(ErrorManager::ERROR_CODE_LABEL_NOT_FOUND, "could not find label \"%s\" in the list of actions.", f_label);
3078 }
3079
3080 // NOTE: the result is a signed value!
3081 offset = l->Offset() - f_offset - 1 - 2 - 2;
3082 data.OverwriteShort(f_offset + 1 + 2, (short) offset);
3083
3084 if(offset < (short) 0x8000 || offset > (short) 0x7FFF) {
3085 return OnError(ErrorManager::ERROR_CODE_LABEL_OVERFLOW, "label \"%s\" is out of bounds.", f_label);
3086 }
3087
3088 return ErrorManager::ERROR_CODE_NONE;
3089 }
3090
3091
3092 /** \fn virtual int sswf::Action::GetMaxRegister(void) const
3093 *
3094 * \brief Retrieve the largest register used by this action.
3095 *
3096 * This function goes through all the list and sub-lists of
3097 * actions and retrieve the largest register currently in use.
3098 *
3099 * \note
3100 * Objects with sub-lists accessible with the sswf::Action::SubList(void)
3101 * function do not need to implement this GetMaxRegister() function.
3102 *
3103 * \sa sswf::Action::GetMaximumRegister(const Vectors& list)
3104 */
3105
3106
3107 /** \fn TagBase *sswf::Action::Tag(void) const
3108 *
3109 * \brief Get the tag in which this action resides.
3110 *
3111 * This function returns the pointer to the tag this action
3112 * was created in (see the constructor!).
3113 *
3114 * \return The pointer of the tag this action was created in
3115 *
3116 * \sa sswf::Action::Action(TagBase *tag, action_t action);
3117 */
3118
3119
3120 /** \var const action_t sswf::Action::f_action;
3121 *
3122 * \brief This action code (ACTION_...).
3123 *
3124 * This variable member holds the action code of this action.
3125 * It is currently read-only since changing it would require
3126 * changes to the minimum version and size information.
3127 */
3128
3129 /** \var unsigned long sswf::Action::f_offset;
3130 *
3131 * \brief The byte position of this action in its list.
3132 *
3133 * This offset defines the position at which the action was
3134 * inserted in the Data buffer while in the sswf::Action::Save() function.
3135 *
3136 * \bug
3137 * This offset is not defined until the sswf::Action::Save() function reaches
3138 * this specific action in its list of actions.
3139 * This is why there is a sswf::Action::Save2ndPass() so the ActionBranch
3140 * action can properly calculate forward references.
3141 */
3142
3143
3144
3145
3146
3147
3148
3149 ////////////////////////////// Action CALL FRAME
3150
3151 /** \class sswf::ActionCallFrame
3152 *
3153 * \brief Change the SWF pointer to the specified frame.
3154 *
3155 * This tag was improperly given a number larger than 127. It actually
3156 * uses no immediate data, instead it uses the current number on the
3157 * stack.
3158 *
3159 * None-the-less, I had to create a specific Action for this tag
3160 * in order to overload the SaveData() function which would otherwise
3161 * generate an assert.
3162 *
3163 * \sa <a href="../SWFalexref.html#action_call_frame">SWF Alexis' Reference—Call Frame</a>
3164 */
ActionCallFrame(TagBase * tag)3165 ActionCallFrame::ActionCallFrame(TagBase *tag)
3166 : Action(tag, ACTION_CALL_FRAME)
3167 {
3168 }
3169
3170
3171 /** \brief A do nothing function.
3172 *
3173 * This function is used to prevent the default SaveData() from generating
3174 * an assert. This is an error from Macromedia which should have created
3175 * a code byte smaller than 128 for this action and did not.
3176 *
3177 * This function just returns right away.
3178 *
3179 * \param[in] data The Data buffer to save extraneous data (i.e. ignored)
3180 * \param[in] nested_data The pre-saved sub-actions (i.e. ignored)
3181 */
SaveData(Data & data,Data & nested_data)3182 ErrorManager::error_code_t ActionCallFrame::SaveData(Data& data, Data& nested_data)
3183 {
3184 // it is necessary to have a SaveData() function
3185 // but there isn't any need for us to have anything
3186 // there since the call frame data is always empty
3187 return ErrorManager::ERROR_CODE_NONE;
3188 }
3189
3190
3191 ////////////////////////////// Action DICTIONARY
3192
3193 /** \class sswf::ActionDictionary
3194 *
3195 * \brief Create a dictionary action.
3196 *
3197 * This action holds pre-defined string constants. These can later be retrieved
3198 * using a query in a ActionPushData action.
3199 *
3200 * Note that too small a string will not benefit from being saved in a dictionary.
3201 * Similarly, if the dictionary is used for only one string, it usually won't help.
3202 *
3203 * Note that there should be only one single dictionary per Action list. The
3204 * dictionary is visible through all the different blocks/level that an Action
3205 * list represents. The consequences of saving more than one ActionDictionary
3206 * in the same list are undefined.
3207 *
3208 * \sa <a href="../SWFalexref.html#action_declare_dictionary">SWF Alexis' Reference—Declare Dictionary</a>
3209 */
3210
3211 /** \brief Initializes the dictionary.
3212 *
3213 * Create an empty tag of type ACTION_DECLARE_DICTIONARY.
3214 */
ActionDictionary(TagBase * tag)3215 ActionDictionary::ActionDictionary(TagBase *tag)
3216 : Action(tag, ACTION_DECLARE_DICTIONARY)
3217 {
3218 }
3219
3220
3221 /** \brief Add a string to a dictionary.
3222 *
3223 * This function adds the specified string to the dictionary.
3224 *
3225 * There is no limit to the string or the number of string one
3226 * can add to a dictionary, except for the total size of an
3227 * action block.
3228 *
3229 * \param[in] string The string to append
3230 */
AddString(const char * string)3231 void ActionDictionary::AddString(const char *string)
3232 {
3233 string_t *str;
3234
3235 str = new string_t;
3236 MemAttach(str, sizeof(string_t), "ActionDictionary::AddString() -- adding a string to the dictionary");
3237 str->f_string = StrDup(string);
3238 f_strings.Set(-1, str);
3239 }
3240
3241
3242
3243 /** \brief Duplicate a dictionary.
3244 *
3245 * This function creates a new ActionDictionary and then copy all the
3246 * strings from 'this' dictionary to the new dictionary.
3247 *
3248 * \return A pointer to the new dictionary.
3249 */
Duplicate(void) const3250 Action *ActionDictionary::Duplicate(void) const
3251 {
3252 string_t *str;
3253 ActionDictionary *d;
3254 int max, idx;
3255
3256 d = new ActionDictionary(Tag());
3257 max = f_strings.Count();
3258 for(idx = 0; idx < max; idx++) {
3259 str = dynamic_cast<string_t *>(f_strings.Get(idx));
3260 d->AddString(str->f_string);
3261 }
3262
3263 return d;
3264 }
3265
3266
3267
3268 /** \brief Save the dictionary strings.
3269 *
3270 * This function is used to save the dictionary strings
3271 * in the specified Data buffer.
3272 *
3273 * \param[in] data The Data buffer where the strings are to be saved
3274 * \param[in] nested_data The sub-actions of the dictionary (i.e. none)
3275 */
SaveData(Data & data,Data & nested_data)3276 ErrorManager::error_code_t ActionDictionary::SaveData(Data& data, Data& nested_data)
3277 {
3278 string_t *str;
3279 int max, idx;
3280 ErrorManager::error_code_t ec;
3281
3282 max = f_strings.Count();
3283 if(max > 256) {
3284 // we can't save more than 256 strings -- we should
3285 // warn the user somehow that there is something wrong
3286 // here!
3287 max = 256;
3288 }
3289 data.PutShort(max);
3290 for(idx = 0; idx < max; idx++) {
3291 str = dynamic_cast<string_t *>(f_strings.Get(idx));
3292 ec = SaveString(data, str->f_string);
3293 if(ec != ErrorManager::ERROR_CODE_NONE) {
3294 return ec;
3295 }
3296 }
3297
3298 return ErrorManager::ERROR_CODE_NONE;
3299 }
3300
3301
3302
3303
3304 ////////////////////////////// Action FUNCTION
3305
3306 /** \class sswf::ActionFunction
3307 *
3308 * \brief The action to hold an ActionScript function.
3309 *
3310 * This class is used to create an ActionFunction, meaning a
3311 * function to be called from within an ActionScript.
3312 *
3313 * \sa <a href="../SWFalexref.html#action_declare_function">SWF Alexis' Reference—Declare Function</a>
3314 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3315 */
3316
3317
3318 /** \enum sswf::ActionFunction::action_function_t
3319 *
3320 * \brief List the flags supported by the DeclareFunction2 tag
3321 *
3322 * These flags can be used to very much optimize ActionScripts.
3323 *
3324 * Each special variable and arguments to functions can be saved
3325 * in registers for fast retrieval.
3326 *
3327 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3328 *
3329 * <hr>
3330 */
3331
3332
3333 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_THIS
3334 *
3335 * \brief Make 'this' variable ready
3336 *
3337 * The ACTION_FUNCTION_LOAD_THIS loads a register with the value of
3338 * 'this'. The register depends on what is loaded before.
3339 *
3340 * \sa sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_THIS
3341 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3342 *
3343 * <hr>
3344 */
3345
3346
3347 /** \var sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_THIS
3348 *
3349 * \brief Don't create the 'this' variable
3350 *
3351 * The ACTION_FUNCTION_SUPPRESS_THIS can be used so 'this' variable
3352 * is not even created. This can speed things up.
3353 *
3354 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_THIS
3355 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3356 *
3357 * <hr>
3358 */
3359
3360
3361 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_ARGUMENTS
3362 *
3363 * \brief Load arguments in registers
3364 *
3365 * The ACTION_FUNCTION_LOAD_ARGUMENTS loads a register with the value of
3366 * each of the arguments specified when calling this function. The
3367 * registers depend on what is loaded before.
3368 *
3369 * \sa sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_ARGUMENTS
3370 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3371 *
3372 * <hr>
3373 */
3374
3375
3376 /** \var sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_ARGUMENTS
3377 *
3378 * \brief Ignore all arguments
3379 *
3380 * The ACTION_FUNCTION_SUPPRESS_ARGUMENTS ensures that the ActionScript
3381 * interpreter does not spend any time saving the arguments. This useful
3382 * for virtual functions support.
3383 *
3384 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_ARGUMENTS
3385 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3386 *
3387 * <hr>
3388 */
3389
3390
3391 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_SUPER
3392 *
3393 * \brief Make the 'super' variable ready
3394 *
3395 * The ACTION_FUNCTION_LOAD_SUPER loads a register with the value of
3396 * 'super'. The register depends on what is loaded before.
3397 *
3398 * \sa sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_SUPER
3399 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3400 *
3401 * <hr>
3402 */
3403
3404
3405 /** \var sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_SUPER
3406 *
3407 * \brief Don't bother creating the 'super' variable
3408 *
3409 * The ACTION_FUNCTION_SUPPRESS_SUPER asks the ActionScript interpreter
3410 * to not bother creating the super variable. This can speed things
3411 * up.
3412 *
3413 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_SUPER
3414 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3415 *
3416 * <hr>
3417 */
3418
3419
3420 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_ROOT
3421 *
3422 * \brief Make the 'root' variable ready
3423 *
3424 * The ACTION_FUNCTION_LOAD_ROOT loads a register with the value of
3425 * 'root'. The register depends on what is loaded before.
3426 *
3427 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_THIS
3428 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_PARENT
3429 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_GLOBAL
3430 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3431 *
3432 * <hr>
3433 */
3434
3435
3436 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_PARENT
3437 ACTION_FUNCTION_LOAD_PARENT = 0x0080,
3438 ACTION_FUNCTION_LOAD_GLOBAL = 0x0100
3439 *
3440 * \brief Make the 'parent' variable ready
3441 *
3442 * The ACTION_FUNCTION_LOAD_PARENT loads a register with the value of
3443 * 'parent'. The register depends on what is loaded before.
3444 *
3445 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_THIS
3446 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_ROOT
3447 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_GLOBAL
3448 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3449 *
3450 * <hr>
3451 */
3452
3453
3454 /** \var sswf::ActionFunction::ACTION_FUNCTION_LOAD_GLOBAL
3455 *
3456 * \brief Make the 'global' variable ready
3457 *
3458 * The ACTION_FUNCTION_LOAD_THIS loads a register with the value of
3459 * 'global'. The register depends on what is loaded before.
3460 *
3461 * \sa sswf::ActionFunction::ACTION_FUNCTION_SUPPRESS_THIS
3462 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_ROOT
3463 * \sa sswf::ActionFunction::ACTION_FUNCTION_LOAD_PARENT
3464 * \sa <a href="../SWFalexref.html#action_declare_function2">SWF Alexis' Reference—Declare Function (V7)</a>
3465 */
3466
3467
3468 /** \enum sswf::ActionFunction::as_set_prop_flags_t
3469 *
3470 * \brief List of flags available to call the ASSetPropFlags() function
3471 *
3472 * This undocumented function is used to change the properties of an
3473 * object variable member or function member. The properties are defined
3474 * by three flags:
3475 *
3476 * \li Is hidden—whether the member can be seen by an enumeration action
3477 * \li Can delete—whether the member can be removed
3478 * \li Can overwrite—whether the member can be modified (this does not
3479 * prevent the content of a variable member from being modified)
3480 *
3481 * \sa sswf::ActionFunction::PROP_FLAG_IS_HIDDEN
3482 * \sa sswf::ActionFunction::PROP_FLAG_CAN_DELETE
3483 * \sa sswf::ActionFunction::PROP_FLAG_CAN_OVERWRITE
3484 *
3485 * <hr>
3486 */
3487
3488
3489 /** \var sswf::ActionFunction::PROP_FLAG_IS_HIDDEN
3490 *
3491 * \brief Prevent the enumeration actions from showing this member
3492 *
3493 * The PROP_FLAG_IS_HIDDEN flag, if set, prevents the enumeration functions
3494 * from listing to corresponding member.
3495 *
3496 * \sa sswf::ActionFunction::PROP_FLAG_CAN_DELETE
3497 * \sa sswf::ActionFunction::PROP_FLAG_CAN_OVERWRITE
3498 *
3499 * <hr>
3500 */
3501
3502
3503 /** \var sswf::ActionFunction::PROP_FLAG_CAN_DELETE
3504 *
3505 * \brief Whether a member can be removed from an object
3506 *
3507 * The PROP_FLAG_CAN_DELETE flag, if set, lets the user delete requests
3508 * function. Once deleted, a member loses its property flag setup. If
3509 * the member is re-created later, it may be required to set this flag
3510 * again to delete it again.
3511 *
3512 * \sa sswf::ActionFunction::PROP_FLAG_IS_HIDDEN
3513 * \sa sswf::ActionFunction::PROP_FLAG_CAN_OVERWRITE
3514 *
3515 * <hr>
3516 */
3517
3518
3519 /** \var sswf::ActionFunction::PROP_FLAG_CAN_OVERWRITE
3520 *
3521 * \brief Whether a member can be overwritten in an object
3522 *
3523 * The PROP_FLAG_CAN_OVERWRITE flag, if set, means that the
3524 * corresponding member can be replaced (i.e. set with a
3525 * different type, or in case of a function, by a different
3526 * function.)
3527 *
3528 * This flag does not prevent a variable member from being
3529 * modified.
3530 *
3531 * \sa sswf::ActionFunction::PROP_FLAG_IS_HIDDEN
3532 * \sa sswf::ActionFunction::PROP_FLAG_CAN_DELETE
3533 */
3534
3535
3536
3537
3538 /** \brief Initializes ActionFunction objects.
3539 *
3540 * This function is used to initialize ActionFunction objects.
3541 *
3542 * In debug mode it will test that the action is valid. It has
3543 * to be set to either:
3544 *
3545 * ACTION_DECLARE_FUNCTION or ACTION_DECLARE_FUNCTION2
3546 *
3547 * The former can be used for movies version 5 or 6, the
3548 * latter for movies version 7 or more.
3549 *
3550 * \param[in] tag The tag holding this action
3551 * \param[in] action The type of function to create
3552 */
ActionFunction(TagBase * tag,action_t action)3553 ActionFunction::ActionFunction(TagBase *tag, action_t action)
3554 : Action(tag, action)
3555 {
3556 assert(action == ACTION_DECLARE_FUNCTION || action == ACTION_DECLARE_FUNCTION2, "The ActionFunction expects ACTION_DECLARE_FUNCTION or ACTION_DECLARE_FUNCTION2.");
3557 if(action != ACTION_DECLARE_FUNCTION && action != ACTION_DECLARE_FUNCTION2) {
3558 throw ErrorManager::InternalErrorException();
3559 }
3560
3561 f_name = 0;
3562 f_registers_count = 0;
3563 f_flags = 0;
3564 }
3565
3566
3567 /** \brief Define the name of the function.
3568 *
3569 * This function saves the specified name as the name of the function.
3570 *
3571 * This is the name you need to use to call the function later.
3572 *
3573 * Note that an object function member has no name.
3574 *
3575 * \param[in] name The new function name
3576 */
SetName(const char * name)3577 void ActionFunction::SetName(const char *name)
3578 {
3579 MemFree(f_name);
3580 f_name = StrDup(name);
3581 }
3582
3583
3584 /** \brief Set the maximum number of registers to use with this function.
3585 *
3586 * With an ACTION_DECLARE_FUNCTION2, you can use as many as 255 registers
3587 * in your function, otherwise you are limited to 4 as before version 7.
3588 * Also, before version 7, the parameters cannot automatically be assigned
3589 * to registers and thus this function is not necessary.
3590 *
3591 * \param[in] count The number of registers you want to use
3592 */
SetRegistersCount(unsigned int count)3593 void ActionFunction::SetRegistersCount(unsigned int count)
3594 {
3595 if(count > 255) {
3596 f_registers_count = 255;
3597 }
3598 else {
3599 f_registers_count = count;
3600 }
3601 }
3602
3603
3604 /** \brief Add a function parameter.
3605 *
3606 * This function adds a parameter to the ActionFunction.
3607 *
3608 * The name is mandatory for an
3609 * ACTION_DECLARE_FUNCTION and optional for an ACTION_DECLARE_FUNCTION2.
3610 * There are some special parameter names for an ACTION_DECLARE_FUNCTION2
3611 * to create or not system registers. The special names are as follow:
3612 *
3613 * \li this — put 'this' in a register
3614 * \li /this — do not create 'this' even when available
3615 * \li arguments — put 'arguments' in a register
3616 * \li /arguments — do not create the 'arguments' array
3617 * \li super — put 'super' in a register
3618 * \li /super — do not create 'super'
3619 * \li _root — put '_root' in a register
3620 * \li /_root — cancel the action of '_root'
3621 * \li _parent — put '_parent' in a register
3622 * \li /_parent — cancel the action of '_parent'
3623 * \li _global — put '_global' in a register
3624 * \li /_global — cancel the action of '_global'
3625 *
3626 * The register number is used only by an ACTION_DECLARE_FUNCTION2.
3627 * By default the register number is set to -1 which means that no register
3628 * is assigned to that parameter. You can use 0 to have the system automatically
3629 * assign a register number to your parameter.
3630 *
3631 * According to my testings, the register 255 cannot be used. So you are limited
3632 * to a register number from 1 to 254. However, don't forget that system parameters
3633 * must use the first few registers! If the register number you specify is larger
3634 * than the one defined by the sswf::ActionFunction::SetRegistersCount(unsigned int count)
3635 * then it is increased as required.
3636 *
3637 * \param[in] name The name of the parameter
3638 * \param[in] register_number The assigned register for that parameter
3639 */
AddParameter(const char * name,int register_number)3640 void ActionFunction::AddParameter(const char *name, int register_number)
3641 {
3642 parameter_t *param;
3643
3644 if(name != 0 && f_action == ACTION_DECLARE_FUNCTION2) {
3645 if(strcmp(name, "this") == 0) {
3646 f_flags |= ACTION_FUNCTION_LOAD_THIS;
3647 f_flags &= ~ACTION_FUNCTION_SUPPRESS_THIS;
3648 return;
3649 }
3650 if(strcmp(name, "/this") == 0) {
3651 f_flags |= ACTION_FUNCTION_SUPPRESS_THIS;
3652 f_flags &= ~ACTION_FUNCTION_LOAD_THIS;
3653 return;
3654 }
3655 if(strcmp(name, "arguments") == 0) {
3656 f_flags |= ACTION_FUNCTION_LOAD_ARGUMENTS;
3657 f_flags &= ~ACTION_FUNCTION_SUPPRESS_ARGUMENTS;
3658 return;
3659 }
3660 if(strcmp(name, "/arguments") == 0) {
3661 f_flags |= ACTION_FUNCTION_SUPPRESS_ARGUMENTS;
3662 f_flags &= ~ACTION_FUNCTION_LOAD_ARGUMENTS;
3663 return;
3664 }
3665 if(strcmp(name, "super") == 0) {
3666 f_flags |= ACTION_FUNCTION_LOAD_SUPER;
3667 f_flags &= ~ACTION_FUNCTION_SUPPRESS_SUPER;
3668 return;
3669 }
3670 if(strcmp(name, "/super") == 0) {
3671 f_flags |= ACTION_FUNCTION_SUPPRESS_SUPER;
3672 f_flags &= ~ACTION_FUNCTION_LOAD_SUPER;
3673 return;
3674 }
3675 if(strcmp(name, "_root") == 0) {
3676 f_flags |= ACTION_FUNCTION_LOAD_ROOT;
3677 return;
3678 }
3679 if(strcmp(name, "/_root") == 0) {
3680 f_flags &= ~ACTION_FUNCTION_LOAD_ROOT;
3681 return;
3682 }
3683 if(strcmp(name, "_parent") == 0) {
3684 f_flags |= ACTION_FUNCTION_LOAD_PARENT;
3685 return;
3686 }
3687 if(strcmp(name, "/_parent") == 0) {
3688 f_flags &= ~ACTION_FUNCTION_LOAD_PARENT;
3689 return;
3690 }
3691 if(strcmp(name, "_global") == 0) {
3692 f_flags |= ACTION_FUNCTION_LOAD_GLOBAL;
3693 return;
3694 }
3695 if(strcmp(name, "/_global") == 0) {
3696 f_flags &= ~ACTION_FUNCTION_LOAD_GLOBAL;
3697 return;
3698 }
3699 }
3700
3701 assert(register_number > -2 && register_number < 255, "ActionFunction::AddParameter() -- invalid register number specification for a function parameter");
3702
3703 param = new parameter_t;
3704 MemAttach(param, sizeof(parameter_t), "ActionFunction::AddParameter() -- parameter_t structure");
3705 param->f_name = StrDup(name);
3706 param->f_register_number = register_number;
3707 if((int) f_registers_count <= register_number) {
3708 f_registers_count = register_number + 1;
3709 }
3710 f_parameters.Set(-1, param);
3711 }
3712
3713
3714 /** \brief Add an action in the function.
3715 *
3716 * Most functions include a set of actions to be executed when
3717 * called. These actions are added using this functions. It is
3718 * also possible to get a pointer to the sub-actions Vectors
3719 * and directly add the actions in the Vectors object.
3720 *
3721 * These actions are seen as the function block.
3722 *
3723 * \param[in] action The action to add to this function
3724 *
3725 * \sa sswf::ActionFunction::SubList(void)
3726 */
AddAction(Action * action)3727 void ActionFunction::AddAction(Action *action)
3728 {
3729 f_actions.Set(-1, action);
3730 }
3731
3732
3733 /** \brief Duplicate the function action.
3734 *
3735 * This function duplicates a function. This includes all the
3736 * parameters and actions as well as the name and number of
3737 * registers used in the list of parameters.
3738 *
3739 * \return A pointer to a new ActionFunction object
3740 */
Duplicate(void) const3741 Action *ActionFunction::Duplicate(void) const
3742 {
3743 parameter_t *param;
3744 ActionFunction *f;
3745 Action *a;
3746 int max, idx;
3747
3748 f = new ActionFunction(Tag(), f_action);
3749 f->SetName(f_name);
3750 f->SetRegistersCount(f_registers_count);
3751 f->f_flags = f_flags; // this wouldn't be set just by duplicating the parameters
3752
3753 max = f_parameters.Count();
3754 for(idx = 0; idx < max; idx++) {
3755 param = dynamic_cast<parameter_t *>(f_parameters.Get(idx));
3756 f->AddParameter(param->f_name, param->f_register_number);
3757 }
3758
3759 max = f_actions.Count();
3760 for(idx = 0; idx < max; idx++) {
3761 a = dynamic_cast<Action *>(f_actions.Get(idx));
3762 f->AddAction(a->Duplicate());
3763 }
3764
3765 return f;
3766 }
3767
3768
3769 /** \brief Get a pointer to the Vectors of sub-actions.
3770 *
3771 * This function can be used to retrieve a pointer to the
3772 * sub-actions Vectors object. This can be used to add
3773 * actions to the function in a way similar to the main
3774 * block.
3775 *
3776 * \return A pointer to a Vectors object expecting actions
3777 */
SubList(void)3778 Vectors *ActionFunction::SubList(void)
3779 {
3780 return &f_actions;
3781 }
3782
3783
3784 /** \brief Save the function header and nested data.
3785 *
3786 * This function creates the function header which includes
3787 * its name, all the parameters, whether to create or suppress
3788 * system registers and the size of the function block.
3789 *
3790 * Note that the function block cannot be larger than about
3791 * 64Kb.
3792 *
3793 * \param[in] data The Data buffer where the function is saved
3794 * \param[in] nested_data The Data buffer holding the function
3795 * block
3796 */
SaveData(Data & data,Data & nested_data)3797 ErrorManager::error_code_t ActionFunction::SaveData(Data& data, Data& nested_data)
3798 {
3799 parameter_t *param;
3800 int max, idx, reg;
3801 char regs[256];
3802 ErrorManager::error_code_t ec;
3803
3804 ec = SaveString(data, f_name);
3805
3806 max = f_parameters.Count();
3807 data.PutShort(max);
3808
3809 if(f_action == ACTION_DECLARE_FUNCTION2) {
3810
3811 GetMaxRegister();
3812
3813 data.PutByte(f_registers_count);
3814 data.PutShort(f_flags);
3815
3816 // mark the used registers
3817 memset(regs, 0, sizeof(regs));
3818
3819 idx = 0;
3820
3821 if((f_flags & ACTION_FUNCTION_LOAD_THIS) != 0) {
3822 idx++;
3823 regs[idx] = 1;
3824 }
3825 if((f_flags & ACTION_FUNCTION_LOAD_SUPER) != 0) {
3826 idx++;
3827 regs[idx] = 1;
3828 }
3829 if((f_flags & ACTION_FUNCTION_LOAD_ROOT) != 0) {
3830 idx++;
3831 regs[idx] = 1;
3832 }
3833 if((f_flags & ACTION_FUNCTION_LOAD_PARENT) != 0) {
3834 idx++;
3835 regs[idx] = 1;
3836 }
3837 if((f_flags & ACTION_FUNCTION_LOAD_GLOBAL) != 0) {
3838 idx++;
3839 regs[idx] = 1;
3840 }
3841
3842 // TODO: we need to make sure that user registers don't
3843 // overlap with system registers
3844 for(idx = 0; idx < max; idx++) {
3845 param = dynamic_cast<parameter_t *>(f_parameters.Get(idx));
3846 if(param->f_register_number > 0 && param->f_register_number < 256) {
3847 regs[param->f_register_number] = 1;
3848 }
3849 }
3850
3851 reg = 1;
3852 for(idx = 0; idx < max; idx++) {
3853 param = dynamic_cast<parameter_t *>(f_parameters.Get(idx));
3854 if(param->f_register_number == 0) { // auto-assign register?
3855 while(reg < 255 && regs[reg] != 0) {
3856 reg++;
3857 }
3858 // TODO: should the max. by 255 instead? (TBD)
3859 if(reg >= 256) {
3860 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_REGISTER_OVERFLOW, "too many registers used in this function."));
3861 data.PutByte(0);
3862 data.PutByte(0);
3863 }
3864 else {
3865 regs[reg] = 1;
3866 data.PutByte(reg);
3867 reg++;
3868 data.PutByte(0); // no variable name
3869 }
3870 }
3871 else if(param->f_register_number > 0) { // user defined register?
3872 // TODO: we need error handling to tell whether the
3873 // same register is used multiple times
3874 data.PutByte(param->f_register_number);
3875 regs[param->f_register_number] = 1;
3876 if(*param->f_name != '\0') {
3877 ec = ErrorManager::KeepFirst(ec, SaveString(data, param->f_name));
3878 }
3879 else {
3880 data.PutByte(0); // no variable name
3881 }
3882 }
3883 else {
3884 data.PutByte(0); // no register; use variable name
3885 ec = ErrorManager::KeepFirst(ec, SaveString(data, param->f_name));
3886 }
3887 }
3888 }
3889 else {
3890 for(idx = 0; idx < max; idx++) {
3891 param = dynamic_cast<parameter_t *>(f_parameters.Get(idx));
3892 ec = ErrorManager::KeepFirst(ec, SaveString(data, param->f_name));
3893 }
3894 }
3895
3896 // the actions were already saved by the Action::Save() function!
3897 data.PutShort((unsigned short) nested_data.ByteSize());
3898
3899 return ec;
3900 }
3901
3902
3903
3904
3905 ////////////////////////////// Action GOTO
3906
3907 /** \class sswf::ActionGoto
3908 *
3909 * \brief A goto action to change the current frame.
3910 *
3911 * This action is used in ActionScripts to change the current frame
3912 * to display.
3913 *
3914 * \sa <a href="../SWFalexref.html#action_goto_expression">SWF Alexis' Reference—Goto Expression</a>
3915 * \sa <a href="../SWFalexref.html#action_goto_frame">SWF Alexis' Reference—Goto Frame</a>
3916 * \sa <a href="../SWFalexref.html#action_goto_label">SWF Alexis' Reference—Goto Label</a>
3917 */
3918
3919 /** \brief Initializes the ActionGoto action.
3920 *
3921 * This function initializes the ActionGoto. This means the frame
3922 * name is set to NULL and the playback flag is set to false
3923 * (i.e. go to that frame and stop playing.)
3924 *
3925 * The valid actions are:
3926 *
3927 * \li ACTION_GOTO_FRAME
3928 * \li ACTION_GOTO_LABEL
3929 * \li ACTION_GOTO_EXPRESSION
3930 */
ActionGoto(TagBase * tag,action_t action)3931 ActionGoto::ActionGoto(TagBase *tag, action_t action)
3932 : Action(tag, action)
3933 {
3934 assert(action == ACTION_GOTO_FRAME || action == ACTION_GOTO_LABEL || action == ACTION_GOTO_EXPRESSION,
3935 "The ActionGoto expects ACTION_GOTO_FRAME, ACTION_GOTO_LABEL or ACTION_GOTO_EXPRESSION.");
3936 if(action != ACTION_GOTO_FRAME && action != ACTION_GOTO_LABEL && action != ACTION_GOTO_EXPRESSION) {
3937 throw ErrorManager::InternalErrorException();
3938 }
3939 f_frame_name = 0;
3940 f_play = false;
3941 }
3942
3943
3944 /** \brief Set the name of the frame to go to.
3945 *
3946 * It is possible to give a name to a frame. This action can then be used
3947 * to go to that frame. You need to use an ACTION_GOTO_FRAME or ACTION_GOTO_LABEL
3948 * for this purpose. The ACTION_GOTO_EXPRESSION uses the last string on the stack
3949 * instead.
3950 *
3951 * In case of an ACTION_GOTO_FRAME, the name can actually be a frame number
3952 * in ASCII (i.e. "15"), otherwise it is the SSWF label name of a frame.
3953 *
3954 * In case of an ACTION_GOTO_LABEL, whether the label exists in the movie is not
3955 * being tested by the library.
3956 *
3957 * \param[in] frame_name The name of the frame you want to go to
3958 */
SetFrameName(const char * frame_name)3959 void ActionGoto::SetFrameName(const char *frame_name)
3960 {
3961 MemFree(f_frame_name);
3962 f_frame_name = StrDup(frame_name);
3963 }
3964
3965
3966 /** \fn void sswf::ActionGoto::SetPlay(bool play)
3967 *
3968 * \brief Set whether the animation continues to play after the goto.
3969 *
3970 * This function is used to define whether the animation should continue
3971 * to play after it jumped to the specified frame.
3972 *
3973 * By default, the action says that the animation should stop playing.
3974 *
3975 * \param[in] play The flag to tell whether it should play (true) or not (false)
3976 */
3977
3978
3979 /** \brief Create a duplicate of this action goto.
3980 *
3981 * Create a new ActionGoto object copy the frame name and whether to continue
3982 * or stop playback.
3983 *
3984 * \return The new ActionGoto object
3985 */
Duplicate(void) const3986 Action *ActionGoto::Duplicate(void) const
3987 {
3988 ActionGoto *a;
3989
3990 a = new ActionGoto(Tag(), f_action);
3991 a->SetFrameName(f_frame_name);
3992 a->SetPlay(f_play);
3993
3994 return a;
3995 }
3996
3997
3998 /** \brief Save the extraneous information of the ActionGoto.
3999 *
4000 * Save the label information of the ActionGoto object.
4001 *
4002 * \param[in] data The Data buffer where the ActionGoto is to be saved
4003 * \param[in] nested_data There is no nested data in an ActionGoto
4004 */
SaveData(Data & data,Data & nested_data)4005 ErrorManager::error_code_t ActionGoto::SaveData(Data& data, Data& nested_data)
4006 {
4007 TagBase *tag;
4008 const char *s;
4009 long no;
4010 ErrorManager::error_code_t ec;
4011
4012 ec = ErrorManager::ERROR_CODE_NONE;
4013
4014 switch(f_action) {
4015 case ACTION_GOTO_LABEL:
4016 /* in this case the user wants to use a label */
4017 ec = SaveString(data, f_frame_name);
4018 break;
4019
4020 case ACTION_GOTO_FRAME:
4021 /* here we have to find what ShowFrame is linked to this entry */
4022 no = 0;
4023 s = f_frame_name;
4024 while(*s >= '0' && *s <= '9') {
4025 no = no * 10 + *s - '0';
4026 ++s;
4027 }
4028 if(*s == '\0' && s != f_frame_name) {
4029 data.PutShort(no);
4030 }
4031 else {
4032 tag = Tag()->FindLabelledTag(f_frame_name);
4033 if(tag == 0) {
4034 /* ha! couldn't find this object... */
4035 ec = OnError(ErrorManager::ERROR_CODE_OBJECT_NOT_FOUND, "cannot find any tag labelled '%s'.", f_frame_name);
4036 data.PutShort(0); // a default, just so the file is not boggus.
4037 }
4038 else {
4039 data.PutShort(tag->WhichFrame());
4040 }
4041 }
4042 break;
4043
4044 case ACTION_GOTO_EXPRESSION:
4045 // TODO: my doc. says this is a char not a short...
4046 // we need to test to know who's right!
4047 data.PutShort(f_play);
4048 break;
4049
4050 default:
4051 assert(0, "invalid f_action for an ActionGoto() object");
4052 ec = OnError(ErrorManager::ERROR_CODE_INTERNAL_ERROR, "invalid f_action for an ActionGoto() object");
4053 break;
4054
4055 }
4056
4057 return ec;
4058 }
4059
4060
4061 ////////////////////////////// Action LABEL
4062
4063 /** \class sswf::ActionLabel
4064 *
4065 * \brief Create a label in an action script.
4066 *
4067 * An ActionLabel is an SSWF addition which is not saved in the SWF
4068 * movie. It is used to indicate where a BranchAction can branch.
4069 */
4070
4071
4072 /** \brief Initialize an ActionLabel.
4073 *
4074 * An action label is set to "no name" by default. You are expected
4075 * to call SetLabel() once initialized.
4076 *
4077 * \param[in] tag The tag including this action
4078 */
ActionLabel(TagBase * tag)4079 ActionLabel::ActionLabel(TagBase *tag)
4080 : Action(tag, ACTION_LABEL)
4081 {
4082 f_label = 0;
4083 }
4084
4085
4086 /** \brief Set the name of an ActionLabel.
4087 *
4088 * This function defines the name of an ActionLabel. The name
4089 * can be any valid string. It should not be empty.
4090 *
4091 * \param[in] label The new label name
4092 */
SetLabel(const char * label)4093 void ActionLabel::SetLabel(const char *label)
4094 {
4095 MemFree(f_label);
4096 f_label = StrDup(label);
4097 }
4098
4099
4100 /** \fn ActionLabel::GetLabel(void) const
4101 *
4102 * \brief Get the name of this label.
4103 *
4104 * This function retrieves the name of this label. It is used to search
4105 * all the labels in an array of actions.
4106 *
4107 * \return The name of this label
4108 */
4109
4110
4111 /** \brief Create a duplicate of the label.
4112 *
4113 * This function creates a new label action and copies the
4114 * label of 'this' action.
4115 *
4116 * \return The pointer to the new ActionLabel
4117 */
Duplicate(void) const4118 Action *ActionLabel::Duplicate(void) const
4119 {
4120 ActionLabel *a;
4121
4122 a = new ActionLabel(Tag());
4123 if(f_label != 0) {
4124 a->SetLabel(f_label);
4125 }
4126
4127 return a;
4128 }
4129
4130
4131 ////////////////////////////// Action PUSH DATA
4132
4133 /** \class sswf::ActionPushData
4134 *
4135 * \brief The PushData action adds data on the ActionScript stack.
4136 *
4137 * Create a PushData action each time you need some constant data
4138 * or the content of a register on the ActionScript stack.
4139 *
4140 * \sa <a href="../SWFalexref.html#action_push_data">SWF Alexis' Reference—Push Data</a>
4141 */
4142
4143
4144 /** \brief The PushData constructor initialize an ActionPushData object
4145 *
4146 * The ActionPushData constructor expects a valid parent tag (a TagHeader
4147 * or a TagSprite.) Call the Add functions to add the different values
4148 * necessary on the stack.
4149 *
4150 * \param[in] tag The tag in which this action is inserted
4151 */
ActionPushData(TagBase * tag)4152 ActionPushData::ActionPushData(TagBase *tag)
4153 : Action(tag, ACTION_PUSH_DATA)
4154 {
4155 }
4156
4157 /** \fn sswf::ActionPushData::AddEmptyString(void)
4158 *
4159 * \brief Add an empty string on the stack
4160 *
4161 * This function is the same as AddString(NULL).
4162 *
4163 * \sa sswf::ActionPushData::AddString()
4164 */
4165
4166
4167
4168 /** \fn sswf::ActionPushData::AddTrue(void)
4169 *
4170 * \brief Add the boolean value True
4171 *
4172 * This function is the same as AddBoolean(true).
4173 *
4174 * \sa sswf::ActionPushData::AddBoolean()
4175 */
4176
4177
4178
4179 /** \fn sswf::ActionPushData::AddFalse(void)
4180 *
4181 * \brief Add the boolean value False
4182 *
4183 * This function is the same as AddBoolean(false).
4184 *
4185 * \sa sswf::ActionPushData::AddBoolean()
4186 */
4187
4188
4189
4190 /** \brief Add a string to the ActionPushData.
4191 *
4192 * This function adds a string to the action.
4193 *
4194 * \sa sswf::ActionPushData::AddEmptyString()
4195 * \param[in] string The string to add to the action
4196 */
AddString(const char * string)4197 void ActionPushData::AddString(const char *string)
4198 {
4199 action_immediate_t *imm;
4200
4201 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_STRING);
4202 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddString() -- immediate data structure");
4203 if(string != 0) {
4204 imm->f_data.f_string = StrDup(string);
4205 }
4206 f_data.Set(-1, imm);
4207 }
4208
4209
4210 /** \brief Add a boolean value to the ActionPushData.
4211 *
4212 * This function adds a boolean value (true or false) to the ActionPushData.
4213 * Note that it is a good idea to use a boolean value for an ACTION_BRANCH_IF_TRUE
4214 * byte code. However, this is very similar to an integer or even a float.
4215 *
4216 * \param[in] value The boolean value (true or false)
4217 */
AddBoolean(bool value)4218 void ActionPushData::AddBoolean(bool value)
4219 {
4220 action_immediate_t *imm;
4221
4222 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_BOOLEAN);
4223 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddBoolean() -- immediate data structure");
4224 imm->f_data.f_boolean = value;
4225 f_data.Set(-1, imm);
4226 }
4227
4228
4229 /** \brief Add an integer to the ActionPushData.
4230 *
4231 * This function adds a 32 bits integer to the ActionPushData
4232 *
4233 * \param[in] value A 32 bits integer
4234 */
AddInteger(long value)4235 void ActionPushData::AddInteger(long value)
4236 {
4237 action_immediate_t *imm;
4238
4239 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_INTEGER);
4240 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddInteger() -- immediate data structure");
4241 imm->f_data.f_integer32 = value;
4242 f_data.Set(-1, imm);
4243 }
4244
4245
4246 /** \brief Add a floating point value to the ActionPushData.
4247 *
4248 * This function adds a 32 bits floating point to the ActionPushData object.
4249 *
4250 * \param[in] value A 32 bits floating point value
4251 */
AddFloat(float value)4252 void ActionPushData::AddFloat(float value)
4253 {
4254 action_immediate_t *imm;
4255
4256 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_FLOAT);
4257 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddDouble() -- immediate data structure");
4258 imm->f_data.f_float32 = value;
4259 f_data.Set(-1, imm);
4260 }
4261
4262
4263 /** \brief Add a floating point to the ActionPushData.
4264 *
4265 * This function adds a 64 bits floating point value to the ActionPushData object
4266 *
4267 * \param[in] value The 64 bits floating point value
4268 */
AddDouble(double value)4269 void ActionPushData::AddDouble(double value)
4270 {
4271 action_immediate_t *imm;
4272
4273 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_DOUBLE);
4274 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddDouble() -- immediate data structure");
4275 imm->f_data.f_float64 = value;
4276 f_data.Set(-1, imm);
4277 }
4278
4279
4280 /** \brief Add the special value NULL to the ActionPushData.
4281 *
4282 * This function is used to add the special value NULL to an
4283 * ActionPushData. This value is also called Nil in some
4284 * ActionScripts. It represents a "no object reference".
4285 */
AddNull(void)4286 void ActionPushData::AddNull(void)
4287 {
4288 action_immediate_t *imm;
4289
4290 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_NULL);
4291 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddNull() -- immediate data structure");
4292 f_data.Set(-1, imm);
4293 }
4294
4295
4296 /** \brief Add the undefined value to the ActionPushData.
4297 *
4298 * This function is used to add the special value Undefined to
4299 * an ActionPushData. This is value is used to test whether
4300 * some object, function, variable is defined or not.
4301 *
4302 * It can also be used to pass as a parameter to a function
4303 * which requires a parameter you cannot define.
4304 */
AddUndefined(void)4305 void ActionPushData::AddUndefined(void)
4306 {
4307 action_immediate_t *imm;
4308
4309 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_UNDEFINED);
4310 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddUndefined() -- immediate data structure");
4311 f_data.Set(-1, imm);
4312 }
4313
4314
4315 /** \brief Add a string from the dictionary.
4316 *
4317 * This function adds a string to the ActionPushData object. The index
4318 * is the string index in this ActionScript dictionary.
4319 *
4320 * Don't forget that you can have only one dictionary within one tag.
4321 *
4322 * \param[in] index The index of the string to be added on the stack
4323 */
AddLookup(unsigned short index)4324 void ActionPushData::AddLookup(unsigned short index)
4325 {
4326 action_immediate_t *imm;
4327
4328 imm = new action_immediate_t(index >= 256 ? ACTION_IMMEDIATE_TYPE_LOOKUP_LARGE : ACTION_IMMEDIATE_TYPE_LOOKUP);
4329 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddLookup() -- immediate data structure");
4330 imm->f_data.f_lookup = index;
4331 f_data.Set(-1, imm);
4332 }
4333
4334
4335 /** \brief Add the content of a register.
4336 *
4337 * This function adds the content of the specified register. This is particularly
4338 * useful for version 7+ functions which can save all their parameters in registers.
4339 * Then you avoid an ActionGetVariable.
4340 *
4341 * The register index is limited to 0, 1, 2 and 3 for the main script and any scripts
4342 * before version 7. Since version 7, registers can be set from 0 to 254 within a
4343 * function 2 declaration.
4344 *
4345 * \param[in] reg_index The index of the register to read
4346 */
AddRegister(unsigned char reg_index)4347 void ActionPushData::AddRegister(unsigned char reg_index)
4348 {
4349 action_immediate_t *imm;
4350
4351 // we would need to know whether we're in a function
4352 // (limit outside a function is 0..3 and in a function 0..255 or 254)
4353 //assert(reg_index < 256, "invalid register index, limited to the range 0..3 inclusive");
4354
4355 imm = new action_immediate_t(ACTION_IMMEDIATE_TYPE_REGISTER);
4356 MemAttach(imm, sizeof(action_immediate_t), "ActionPushData::AddRegister() -- immediate data structure");
4357 imm->f_data.f_register = reg_index;
4358 f_data.Set(-1, imm);
4359 }
4360
4361
4362
4363
4364 /** \brief Duplicate an ActionPushData.
4365 *
4366 * This function creates a new ActionPushData object and copies
4367 * 'this' ActionPushData in it.
4368 *
4369 * The function copies all the data which was added to the
4370 * ActionPushData.
4371 *
4372 * \return The new ActionPushData pointer
4373 */
Duplicate(void) const4374 Action *ActionPushData::Duplicate(void) const
4375 {
4376 ActionPushData *a;
4377 action_immediate_t *imm;
4378 int i, max;
4379
4380 a = new ActionPushData(Tag());
4381
4382 max = f_data.Count();
4383 for(i = 0; i < max; i++) {
4384 imm = dynamic_cast<action_immediate_t *>(f_data.Get(i));
4385 switch(imm->f_type) {
4386 case ACTION_IMMEDIATE_TYPE_STRING:
4387 a->AddString(imm->f_data.f_string);
4388 break;
4389
4390 case ACTION_IMMEDIATE_TYPE_FLOAT:
4391 a->AddFloat(imm->f_data.f_float32);
4392 break;
4393
4394 case ACTION_IMMEDIATE_TYPE_BOOLEAN:
4395 a->AddBoolean(imm->f_data.f_boolean);
4396 break;
4397
4398 case ACTION_IMMEDIATE_TYPE_DOUBLE:
4399 a->AddDouble(imm->f_data.f_float64);
4400 break;
4401
4402 case ACTION_IMMEDIATE_TYPE_INTEGER:
4403 a->AddInteger(imm->f_data.f_integer32);
4404 break;
4405
4406 case ACTION_IMMEDIATE_TYPE_LOOKUP:
4407 case ACTION_IMMEDIATE_TYPE_LOOKUP_LARGE:
4408 a->AddLookup(imm->f_data.f_lookup);
4409 break;
4410
4411 case ACTION_IMMEDIATE_TYPE_REGISTER:
4412 a->AddRegister(imm->f_data.f_register);
4413 break;
4414
4415 case ACTION_IMMEDIATE_TYPE_NULL:
4416 a->AddNull();
4417 break;
4418
4419 case ACTION_IMMEDIATE_TYPE_UNDEFINED:
4420 a->AddUndefined();
4421 break;
4422
4423 default:
4424 assert(0, "unknown immediate data type");
4425 /*NOTREACHED*/
4426
4427 }
4428 }
4429
4430 return a;
4431 }
4432
4433
4434 /** \brief Search the action for registers and return the largest number.
4435 *
4436 * This function defines what the largest register is in this
4437 * ActionPushData.
4438 *
4439 * \return The largest register used in this ActionPushData
4440 */
GetMaxRegister(void) const4441 int ActionPushData::GetMaxRegister(void) const
4442 {
4443 action_immediate_t *imm;
4444 int register_number;
4445 int i;
4446
4447 register_number = -1;
4448
4449 i = f_data.Count();
4450 while(i > 0) {
4451 i--;
4452 imm = dynamic_cast<action_immediate_t *>(f_data.Get(i));
4453 switch(imm->f_type) {
4454 case ACTION_IMMEDIATE_TYPE_STRING:
4455 case ACTION_IMMEDIATE_TYPE_FLOAT:
4456 case ACTION_IMMEDIATE_TYPE_BOOLEAN:
4457 case ACTION_IMMEDIATE_TYPE_DOUBLE:
4458 case ACTION_IMMEDIATE_TYPE_INTEGER:
4459 case ACTION_IMMEDIATE_TYPE_NULL:
4460 case ACTION_IMMEDIATE_TYPE_UNDEFINED:
4461 break;
4462
4463 case ACTION_IMMEDIATE_TYPE_LOOKUP:
4464 case ACTION_IMMEDIATE_TYPE_LOOKUP_LARGE:
4465 // here we would need to check in the dictionary
4466 // to know whether the dictionary is itself defining
4467 // a register...
4468 break;
4469
4470 case ACTION_IMMEDIATE_TYPE_REGISTER:
4471 if((int) imm->f_data.f_register > register_number) {
4472 register_number = imm->f_data.f_register;
4473 }
4474 break;
4475
4476 default:
4477 assert(0, "unknown immediate data type");
4478 /*NOTREACHED*/
4479
4480 }
4481 }
4482
4483 return register_number;
4484 }
4485
4486
4487 /** \brief Save the ActionPushData data.
4488 *
4489 * This function is used to save the actual data of the ActionPushData
4490 * in the Data buffer.
4491 *
4492 * \param[in] data The Data buffer where the ActionPushData is saved
4493 * \param[in] nested_data There is no nested data in an ActionPushData
4494 */
SaveData(Data & data,Data & nested_data)4495 ErrorManager::error_code_t ActionPushData::SaveData(Data& data, Data& nested_data)
4496 {
4497 action_immediate_t *imm;
4498 int32_t *ptr;
4499 int i, max;
4500 ErrorManager::error_code_t ec;
4501
4502 ec = ErrorManager::ERROR_CODE_NONE;
4503
4504 max = f_data.Count();
4505 i = 0;
4506 while(i < max) {
4507 imm = dynamic_cast<action_immediate_t *>(f_data.Get(i));
4508 data.PutByte(imm->f_type);
4509 switch(imm->f_type) {
4510 case ACTION_IMMEDIATE_TYPE_STRING:
4511 ec = ErrorManager::KeepFirst(ec, SaveString(data, imm->f_data.f_string));
4512 break;
4513
4514 case ACTION_IMMEDIATE_TYPE_FLOAT:
4515 ptr = (int32_t *) &imm->f_data; // .f_float32
4516 data.PutLong(*ptr);
4517 break;
4518
4519 case ACTION_IMMEDIATE_TYPE_BOOLEAN:
4520 data.PutByte(imm->f_data.f_boolean);
4521 break;
4522
4523 case ACTION_IMMEDIATE_TYPE_DOUBLE:
4524 ptr = (int32_t *) &imm->f_data; // .f_float64
4525 #if BYTE_ORDER == LITTLE_ENDIAN
4526 // AMD/Intel like
4527 data.PutLong(ptr[1]);
4528 data.PutLong(ptr[0]);
4529 #else
4530 // RISC like
4531 data.PutLong(ptr[0]);
4532 data.PutLong(ptr[1]);
4533 #endif
4534 break;
4535
4536 case ACTION_IMMEDIATE_TYPE_INTEGER:
4537 data.PutLong(imm->f_data.f_integer32);
4538 break;
4539
4540 case ACTION_IMMEDIATE_TYPE_REGISTER:
4541 data.PutByte(imm->f_data.f_register);
4542 break;
4543
4544 case ACTION_IMMEDIATE_TYPE_LOOKUP:
4545 // in this case we know that f_lookup < 256
4546 data.PutByte((unsigned char) imm->f_data.f_lookup);
4547 break;
4548
4549 case ACTION_IMMEDIATE_TYPE_LOOKUP_LARGE:
4550 data.PutShort(imm->f_data.f_lookup);
4551 break;
4552
4553 case ACTION_IMMEDIATE_TYPE_NULL:
4554 case ACTION_IMMEDIATE_TYPE_UNDEFINED:
4555 break;
4556
4557 default:
4558 assert(0, "unknown immediate data type");
4559 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_INTERNAL_ERROR, "unknown immediate data type"));
4560 break;
4561
4562 }
4563 i++;
4564 }
4565
4566 return ec;
4567 }
4568
4569
4570
4571 ////////////////////////////// Action SET TARGET
4572
4573 /** \class sswf::ActionSetTarget
4574 *
4575 * \brief This class is used to define the sprite on which the actions apply.
4576 *
4577 * Before becoming fully object oriented, ActionScript used this
4578 * action to define the name of the Sprite on which the actions
4579 * had an effect.
4580 *
4581 * Using an empty name would reset the ActionScript to its default
4582 * behavior.
4583 *
4584 * \sa <a href="../SWFalexref.html#action_set_target">SWF Alexis' Reference—Set Target</a>
4585 * \sa <a href="../SWFalexref.html#action_set_target_dynamic">SWF Alexis' Reference—Set Target <i>(dynamic)</i></a>
4586 */
4587
4588 /** \brief Initializes the ActionSetTarget.
4589 *
4590 * By default, the constructor creates an action target with no
4591 * name (i.e. reset to normal default behavior).
4592 *
4593 * Use the sswf::ActionSetTarget::SetTarget() function to define
4594 * which sprite should be affected.
4595 *
4596 * \param[in] tag The tag in which this action is saved.
4597 */
ActionSetTarget(TagBase * tag)4598 ActionSetTarget::ActionSetTarget(TagBase *tag)
4599 : Action(tag, ACTION_SET_TARGET)
4600 {
4601 f_target = 0;
4602 }
4603
4604
4605 /** \brief Set the name of the Sprite to affect.
4606 *
4607 * This function should be called with the name of the Sprite
4608 * which needs to be affected by the following actions.
4609 *
4610 * Set the name to NULL or an empty string to cancel a
4611 * previous ActionSetTarget (this is the default so you
4612 * do not have to do so.)
4613 */
SetTarget(const char * target)4614 void ActionSetTarget::SetTarget(const char *target)
4615 {
4616 MemFree(f_target);
4617 f_target = StrDup(target);
4618 }
4619
4620
4621 /** \brief Create a duplicate of this action.
4622 *
4623 * This function creates a new ActionSetTarget and copy the
4624 * target name of 'this' SetTarget and return the result.
4625 *
4626 * \return The pointer to the new ActionSetTarget
4627 */
Duplicate(void) const4628 Action *ActionSetTarget::Duplicate(void) const
4629 {
4630 ActionSetTarget *a;
4631
4632 a = new ActionSetTarget(Tag());
4633 a->SetTarget(f_target);
4634
4635 return a;
4636 }
4637
4638
4639 /** \brief Save the extra data of the ActionSetTarget.
4640 *
4641 * This function saves the name of the target as expected
4642 * by this function.
4643 *
4644 * \param[in] data The Data buffer where the target name is saved
4645 * \param[in] nested_data The ActionSetTarget has no nested data
4646 */
SaveData(Data & data,Data & nested_data)4647 ErrorManager::error_code_t ActionSetTarget::SaveData(Data& data, Data& nested_data)
4648 {
4649 return SaveString(data, f_target);
4650 }
4651
4652
4653
4654
4655
4656 ////////////////////////////// Action STORE REGISTER
4657
4658 /** \class sswf::ActionStoreRegister
4659 *
4660 * \brief Store the top stack value in a register.
4661 *
4662 * This action is used to save the current content of the stack
4663 * in a register. Later, you can read the register with an
4664 * sswf::ActionPushData action.
4665 *
4666 * \sa <a href="../SWFalexref.html#action_store_register">SWF Alexis' Reference—Store Register</a>
4667 */
4668
4669 /** \brief Initialize the ActionStoreRegister.
4670 *
4671 * Initialize the ActionStoreRegister by setting the register
4672 * number to zero. Use the SetRegister() function to change
4673 * the default.
4674 *
4675 * \param[in] tag The tag in which this action is being added
4676 */
ActionStoreRegister(TagBase * tag)4677 ActionStoreRegister::ActionStoreRegister(TagBase *tag)
4678 : Action(tag, ACTION_STORE_REGISTER)
4679 {
4680 f_reg = 0;
4681 }
4682
4683
4684 /** \brief Defines which register will hold the stack content.
4685 *
4686 * This function can be used to define the register number
4687 * to hold the current stack content.
4688 *
4689 * Outside a function, only registers 0 to 3 are acceptable.
4690 *
4691 * Inside a function (DeclareFunction2--Version 7 of SWF),
4692 * all registers from 0 to 254 are acceptable. (from my
4693 * testing it seems that register 255 does not work.)
4694 *
4695 * \param[in] reg The new register to assign to this action
4696 */
SetRegister(unsigned char reg)4697 void ActionStoreRegister::SetRegister(unsigned char reg)
4698 {
4699 f_reg = reg;
4700 }
4701
4702
4703 /** \brief Create a clone of this action.
4704 *
4705 * This function allocates a new ActionStoreRegister object,
4706 * it copies the register number and returns the pointer of
4707 * the new action.
4708 *
4709 * \return The action clone pointer
4710 */
Duplicate(void) const4711 Action *ActionStoreRegister::Duplicate(void) const
4712 {
4713 ActionStoreRegister *a;
4714
4715 a = new ActionStoreRegister(Tag());
4716 a->SetRegister(f_reg);
4717
4718 return a;
4719 }
4720
4721
4722 /** \brief Get the maximum register number in use.
4723 *
4724 * This function gets the larger register number in
4725 * use by this action. This is actually equal to the
4726 * register you defined with SetRegister() or zero.
4727 *
4728 * \return The largest register number in use by this action
4729 */
GetMaxRegister(void) const4730 int ActionStoreRegister::GetMaxRegister(void) const
4731 {
4732 return f_reg;
4733 }
4734
4735
4736 /** \brief Save the extraneous data for this action.
4737 *
4738 * This means saving one byte with the register number.
4739 *
4740 * \param[in] data The Data buffer where the register number is to be saved
4741 * \param[in] nested_data The ActionStoreRegister does not support nested data
4742 */
SaveData(Data & data,Data & nested_data)4743 ErrorManager::error_code_t ActionStoreRegister::SaveData(Data& data, Data& nested_data)
4744 {
4745 data.PutByte(f_reg);
4746
4747 return ErrorManager::ERROR_CODE_NONE;
4748 }
4749
4750
4751
4752
4753
4754 ////////////////////////////// Action STRICT MODE
4755
4756 /** \class sswf::ActionStrictMode
4757 *
4758 * \brief This action is used to define the current scripting mode.
4759 *
4760 * It can be strict (i.e. follows JavaScript specification
4761 * to the letter) or lazy (i.e. accepts old ActionScript
4762 * commands).
4763 *
4764 * \sa <a href="../SWFalexref.html#action_strict_mode">SWF Alexis' Reference—Strict Mode</a>
4765 */
4766
4767 /** \brief Initialize the ActionStrictMode object.
4768 *
4769 * This constructor marks the mode as <i>not strict</i>.
4770 *
4771 * Use the SetStrict() function to change the mode.
4772 *
4773 * \param[in] tag The tag in which this action is being created
4774 */
ActionStrictMode(TagBase * tag)4775 ActionStrictMode::ActionStrictMode(TagBase *tag)
4776 : Action(tag, ACTION_STRICT_MODE)
4777 {
4778 f_strict = false;
4779 }
4780
4781
4782 /** \brief Change the mode as required.
4783 *
4784 * This function lets you change the mode from strict (true)
4785 * to lazy (false).
4786 *
4787 * \param[in] strict Set to 'true' to enter strict mode
4788 */
SetStrict(bool strict)4789 void ActionStrictMode::SetStrict(bool strict)
4790 {
4791 f_strict = strict;
4792 }
4793
4794
4795 /** \brief Create a clone of this ActionStrictMode object.
4796 *
4797 * This function creates a new ActionStringMode object; it
4798 * copies 'this' strict mode in the new action and then
4799 * it returns the pointer of the new action.
4800 *
4801 * \return The pointer to the new action
4802 */
Duplicate(void) const4803 Action *ActionStrictMode::Duplicate(void) const
4804 {
4805 ActionStrictMode *a;
4806
4807 a = new ActionStrictMode(Tag());
4808 a->SetStrict(f_strict);
4809
4810 return a;
4811 }
4812
4813
4814 /** \brief Save the mode in the Data buffer.
4815 *
4816 * This function saves the strict mode in the Data buffer passed in.
4817 *
4818 * \param[in] data The Data buffer where the strict mode is saved
4819 * \param[in] nested_data The ActionStrictMode has no nested_data
4820 */
SaveData(Data & data,Data & nested_data)4821 ErrorManager::error_code_t ActionStrictMode::SaveData(Data& data, Data& nested_data)
4822 {
4823 data.PutByte(f_strict);
4824
4825 return ErrorManager::ERROR_CODE_NONE;
4826 }
4827
4828
4829
4830
4831
4832 ////////////////////////////// Action TRY
4833
4834 /** \class sswf::ActionTry
4835 *
4836 * \brief This action encompasses the Try, Catch and Finally actions.
4837 *
4838 * This action creates two or three blocks of sub-actions. The first
4839 * block (the 'try' block) is protected, meaning that if an error occurs
4840 * within that block code, it will not break execution. Instead it will
4841 * continue with the 'catch' block if present and terminate the 'finally'
4842 * block if it exists.
4843 *
4844 * It is necessary to at least have one of the 'catch' or 'finally' blocks.
4845 * The 'try' block is mandatory.
4846 *
4847 * \sa <a href="../SWFalexref.html#action_try">SWF Alexis' Reference—Try</a>
4848 */
4849
4850 /** \brief Initialize the ActionTry action.
4851 *
4852 * This constructor marks the Try action as not having any catch or
4853 * finally blocks, no name and no register.
4854 *
4855 * Use the AddTryAction() or SubListTry() to add actions to the try block.
4856 *
4857 * Use the AddCatchAction() or SubListCatch() to add actions to the
4858 * catch block.
4859 *
4860 * Use the AddFinallyAction() or SubListFinally() to add actions to
4861 * the finally block.
4862 *
4863 * Use the SetIdentifier(int register_number) function with an integer
4864 * to define a register number for the catch variable.
4865 *
4866 * Use the SetIdentifier(const char *name) function with a string to
4867 * define the name of a variable to use as the catch variable.
4868 *
4869 * \param[in] tag The tag in which this action is inserted
4870 */
ActionTry(TagBase * tag)4871 ActionTry::ActionTry(TagBase *tag)
4872 : Action(tag, ACTION_TRY)
4873 {
4874 f_register = -1;
4875 f_variable_name = 0;
4876 f_has_catch = false;
4877 f_has_finally = false;
4878 }
4879
4880
4881 /** \brief Add an action to the try block.
4882 *
4883 * This function adds the specified action to the try block. There should
4884 * be at least one action in the try block.
4885 *
4886 * The action is not duplicated.
4887 *
4888 * \param[in] action The pointer to the action to add to the try block or NULL
4889 */
AddTryAction(Action * action)4890 void ActionTry::AddTryAction(Action *action)
4891 {
4892 if(action != 0) {
4893 f_actions_try.Set(-1, action);
4894 }
4895 }
4896
4897
4898 /** \brief Add an action to the catch block.
4899 *
4900 * This function adds the specified action to the catch block. The catch
4901 * block can be empty, in which case you must have a non-empty finally block.
4902 *
4903 * The action passed is not duplicated.
4904 *
4905 * This function has the side effect of marking the action as having
4906 * a catch block, unless the pointer is null.
4907 *
4908 * \param[in] action The pointer to the action to add to the catch block or NULL
4909 */
AddCatchAction(Action * action)4910 void ActionTry::AddCatchAction(Action *action)
4911 {
4912 if(action != 0) {
4913 f_has_catch = true;
4914 f_actions_catch.Set(-1, action);
4915 }
4916 }
4917
4918
4919 /** \brief Add an action to the finally block.
4920 *
4921 * This function adds the specified action to the finally block. The finally
4922 * block can be empty, in which case you must have a non-empty catch block.
4923 *
4924 * The action passed is not duplicated.
4925 *
4926 * This function has the side effect of marking the action as having
4927 * a finally block, unless the pointer is null.
4928 *
4929 * \param[in] action The pointer to the action to add to the finally block or NULL
4930 */
AddFinallyAction(Action * action)4931 void ActionTry::AddFinallyAction(Action *action)
4932 {
4933 if(action != 0) {
4934 f_has_finally = true;
4935 f_actions_finally.Set(-1, action);
4936 }
4937 }
4938
4939
4940 /** \brief Request the error to be saved in a register.
4941 *
4942 * The catch block, when called, receives an error variable.
4943 * This variable can be saved in a register. To archive this,
4944 * set the register number that you want to use for this catch
4945 * block.
4946 *
4947 * This function has priority over the SetIdentifier(const char *name)
4948 * function. This means the register number will be used instead of
4949 * the register name if defined.
4950 *
4951 * The register number can be any number between 0 and 254.
4952 *
4953 * If the register number is set to -1, then it is ignored.
4954 *
4955 * \param[in] register_number The register to use in the catch block to access the error
4956 */
SetIdentifier(int register_number)4957 void ActionTry::SetIdentifier(int register_number)
4958 {
4959 f_register = register_number;
4960 }
4961
4962
4963 /** \brief Request the error to be saved in a named variable.
4964 *
4965 * This function defines the name to use as the catch variable.
4966 * When a register number from 0 to 254 was defined with SetIdentifier(),
4967 * this variable name is ignored.
4968 *
4969 * \param[in] name The name of the variable to use within the catch block to access the error
4970 */
SetIdentifier(const char * name)4971 void ActionTry::SetIdentifier(const char *name)
4972 {
4973 MemFree(f_variable_name);
4974 f_variable_name = StrDup(name);
4975 }
4976
4977
4978 /** \brief Create a clone of this action.
4979 *
4980 * This function creates a new ActionTry object, it copies the register
4981 * number, variable name, has catch & finally flags and then copy the
4982 * lists of actions (try, catch and finally blocks.)
4983 *
4984 * \return The pointer to the new action
4985 */
Duplicate(void) const4986 Action *ActionTry::Duplicate(void) const
4987 {
4988 ActionTry *t;
4989 Action *a;
4990 int max, idx;
4991
4992 t = new ActionTry(Tag());
4993 t->SetIdentifier(f_register);
4994 t->SetIdentifier(f_variable_name);
4995 t->f_has_catch = f_has_catch;
4996 t->f_has_finally = f_has_finally;
4997
4998 max = f_actions_try.Count();
4999 for(idx = 0; idx < max; idx++) {
5000 a = dynamic_cast<Action *>(f_actions_try.Get(idx));
5001 t->AddTryAction(a->Duplicate());
5002 }
5003
5004 max = f_actions_catch.Count();
5005 for(idx = 0; idx < max; idx++) {
5006 a = dynamic_cast<Action *>(f_actions_catch.Get(idx));
5007 t->AddCatchAction(a->Duplicate());
5008 }
5009
5010 max = f_actions_finally.Count();
5011 for(idx = 0; idx < max; idx++) {
5012 a = dynamic_cast<Action *>(f_actions_finally.Get(idx));
5013 t->AddFinallyAction(a->Duplicate());
5014 }
5015
5016 return t;
5017 }
5018
5019
5020 /** \brief The version required to save this action.
5021 *
5022 * This function goes through all the sub-action lists to determine
5023 * the minimum version necessary to save it.
5024 *
5025 * The ActionTry itself requires version 7, but actions in the
5026 * sub-lists may require a higher version.
5027 *
5028 * \return The minimum version required to have the request work
5029 */
Version(void) const5030 unsigned char ActionTry::Version(void) const
5031 {
5032 int v, version;
5033
5034 // Until version 8, this Version() function is
5035 // useless... But that's here for forward compatibility
5036 // since when version 8 comes out I'd probably forget
5037 // to come back to it!
5038 version = 7; // the ActionTry is version 7 by itself
5039
5040 v = MinimumListVersion(f_actions_try);
5041 if(v > version) {
5042 version = v;
5043 }
5044
5045 v = MinimumListVersion(f_actions_catch);
5046 if(v > version) {
5047 version = v;
5048 }
5049
5050 v = MinimumListVersion(f_actions_finally);
5051 if(v > version) {
5052 version = v;
5053 }
5054
5055 return version;
5056 }
5057
5058
5059 /** \brief Defines the maximum register number in use.
5060 *
5061 * This function overwrites the default sswf::Action::GetMaxRegister()
5062 * function in order to retrieve the largest register in use in any
5063 * of the sub-action blocks (try, catch, finally).
5064 *
5065 * \return The largest register in use within this ActionTry object
5066 */
GetMaxRegister(void) const5067 int ActionTry::GetMaxRegister(void) const
5068 {
5069 int result, r;
5070
5071 result = GetMaximumRegister(f_actions_try);
5072
5073 r = GetMaximumRegister(f_actions_catch);
5074 if(r > result) {
5075 result = r;
5076 }
5077
5078 r = GetMaximumRegister(f_actions_finally);
5079 if(r > result) {
5080 result = r;
5081 }
5082
5083 return result;
5084 }
5085
5086
5087
5088
5089 /** \brief Retrieve the Vectors to the try action block.
5090 *
5091 * This function can be used to retrieve a direct pointer to the Vectors
5092 * holding the action block for the 'try' block.
5093 *
5094 * \return A pointer to the action list for the 'try' block
5095 */
SubListTry(void)5096 Vectors *ActionTry::SubListTry(void)
5097 {
5098 return &f_actions_try;
5099 }
5100
5101
5102 /** \brief Retrieve the Vectors to the catch action block.
5103 *
5104 * This function can be used to retrieve a direct pointer to the Vectors
5105 * holding the action block for the 'catch' block.
5106 *
5107 * \warning
5108 * This function has the side effect of setting the catch block flag
5109 * to true, meaning that the catch block exists. You should always add
5110 * at least one item in the Vectors to validate this properly.
5111 *
5112 * \return A pointer to the action list for the 'catch' block
5113 */
SubListCatch(void)5114 Vectors *ActionTry::SubListCatch(void)
5115 {
5116 f_has_catch = true;
5117 return &f_actions_catch;
5118 }
5119
5120
5121 /** \brief Retrieve the Vectors to the finally action block.
5122 *
5123 * This function can be used to retrieve a direct pointer to the Vectors
5124 * holding the action block for the 'finally' block.
5125 *
5126 * \warning
5127 * This function has the side effect of setting the finally block flag
5128 * to true, meaning that the finally block exists. You should always add
5129 * at least one item in the Vectors to validate this properly.
5130 *
5131 * \return A pointer to the action list for the 'finally' block
5132 */
SubListFinally(void)5133 Vectors *ActionTry::SubListFinally(void)
5134 {
5135 f_has_finally = true;
5136 return &f_actions_finally;
5137 }
5138
5139
5140 /** \brief Save the ActionTry extraneous data.
5141 *
5142 * The SaveData() function saves the try, catch and finally blocks in
5143 * the nested_data and the try header in the Data buffers.
5144 *
5145 * Note that the maximum size for any one sub-block is 65535 bytes.
5146 * A larger sub-block will generate an error and the save will fail.
5147 *
5148 * This function should not be called until at least one of the
5149 * catch or finally block has been created.
5150 *
5151 * \param[in] data The Data buffer where the ActionTry header is saved
5152 * \param[in] nested_data This buffer is used to save the try, catch and finally blocks
5153 */
SaveData(Data & data,Data & nested_data)5154 ErrorManager::error_code_t ActionTry::SaveData(Data& data, Data& nested_data)
5155 {
5156 Data try_data, catch_data, finally_data;
5157 unsigned long try_size, catch_size, finally_size;
5158 bool bad;
5159 ErrorManager::error_code_t ec;
5160
5161 assert(f_has_finally || f_has_catch, "an ActionTry needs at least one of CATCH or FINALLY");
5162 if(!f_has_finally && !f_has_catch) {
5163 ec = OnError(ErrorManager::ERROR_CODE_INTERNAL_ERROR, "an ActionTry needs at least one of CATCH or FINALLY");
5164 }
5165 else {
5166 ec = ErrorManager::ERROR_CODE_NONE;
5167 }
5168
5169 ec = ErrorManager::KeepFirst(ec, SaveList(&f_actions_try, try_data));
5170 ec = ErrorManager::KeepFirst(ec, SaveList(&f_actions_catch, catch_data));
5171 ec = ErrorManager::KeepFirst(ec, SaveList(&f_actions_finally, finally_data));
5172
5173 // get rid of the ACTION_END
5174 try_data.SetSize(try_data.GetSize() - CHAR_BIT);
5175 catch_data.SetSize(catch_data.GetSize() - CHAR_BIT);
5176 finally_data.SetSize(finally_data.GetSize() - CHAR_BIT);
5177
5178 try_size = try_data.ByteSize();
5179 catch_size = catch_data.ByteSize();
5180 finally_size = finally_data.ByteSize();
5181
5182 if((bad = try_size >= USHRT_MAX)) {
5183 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_ACTION_OVERFLOW, "too many nested instructions in a TRY; length overflow."));
5184 bad = true;
5185 }
5186 if(catch_size >= USHRT_MAX) {
5187 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_ACTION_OVERFLOW, "too many nested instructions in a CATCH; length overflow."));
5188 bad = true;
5189 }
5190 if(finally_size >= USHRT_MAX) {
5191 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_ACTION_OVERFLOW, "too many nested instructions in a FINALLY; length overflow."));
5192 bad = true;
5193 }
5194 if(bad) {
5195 try_size = 0;
5196 catch_size = 0;
5197 finally_size = 0;
5198 }
5199
5200 data.WriteBits(0, 5);
5201 data.WriteBits(f_register < 0 ? 0 : 1, 1);
5202 data.WriteBits(f_has_finally, 1);
5203 data.WriteBits(f_has_catch, 1);
5204 data.PutShort((short) finally_size);
5205 data.PutShort((short) catch_size);
5206 data.PutShort((short) try_size);
5207 if(f_register < 0) {
5208 ec = ErrorManager::KeepFirst(ec, SaveString(data, f_variable_name));
5209 }
5210 else {
5211 data.PutByte(f_register);
5212 }
5213 if(bad) {
5214 return ec;
5215 }
5216
5217 nested_data.Append(try_data);
5218 nested_data.Append(catch_data);
5219 nested_data.Append(finally_data);
5220
5221 return ec;
5222 }
5223
5224
5225
5226
5227
5228 ////////////////////////////// Action URL
5229
5230 /** \class sswf::ActionURL
5231 *
5232 * \brief Go to a static or dynamic URL.
5233 *
5234 * The ActionURL class is used to define a URL to load in the
5235 * user browser.
5236 *
5237 * Use the SetURL() or SetMethod() functions to setup this
5238 * action appropriately.
5239 *
5240 * \note
5241 * The ACTION_URL expects a SetURL() call.
5242 *
5243 * The ACTION_URL2 expects a SetMethod() call.
5244 *
5245 * If the ActionURL does not automatically choose which of the
5246 * ACTION_URL or ACTION_URL2 to save it is because the former
5247 * does not use the stack whereas the latter does. Thus this
5248 * action by itself cannot know which action to save.
5249 *
5250 * \sa <a href="../SWFalexref.html#action_get_url">SWF Alexis' Reference—Get URL</a>
5251 * \sa <a href="../SWFalexref.html#action_get_url2">SWF Alexis' Reference—Get URL 2</a>
5252 */
5253
5254
5255 /** \enum sswf::ActionURL::url_method_t
5256 *
5257 * \brief The different methods which can be used with the ActionURL
5258 *
5259 * The ActionURL can pass the data to the server with a GET, a POST
5260 * or with no variable.
5261 *
5262 * \sa sswf::ActionURL::URL_METHOD_UNDEFINED
5263 * \sa sswf::ActionURL::URL_METHOD_NOVARIABLE
5264 * \sa sswf::ActionURL::URL_METHOD_NOVARIABLES
5265 * \sa sswf::ActionURL::URL_METHOD_GET
5266 * \sa sswf::ActionURL::URL_METHOD_POST
5267 *
5268 * <hr>
5269 */
5270
5271
5272 /** \var sswf::ActionURL::URL_METHOD_UNDEFINED
5273 *
5274 * \brief The method is still undefined
5275 *
5276 * This is the default method value. It is required to be defined before
5277 * the action is saved in a Flash animation.
5278 *
5279 * <hr>
5280 */
5281
5282
5283 /** \var sswf::ActionURL::URL_METHOD_NOVARIABLE
5284 *
5285 * \brief Send the request without any variable
5286 *
5287 * Send the URL with no variable.
5288 *
5289 * <hr>
5290 */
5291
5292
5293 /** \var sswf::ActionURL::URL_METHOD_NOVARIABLES
5294 *
5295 * \brief Send the request without any variable
5296 *
5297 * Send the URL with no variable.
5298 *
5299 * <hr>
5300 */
5301
5302
5303 /** \var sswf::ActionURL::URL_METHOD_GET
5304 *
5305 * \brief Send the request using an HTTP GET
5306 *
5307 * Send the request as an HTTP GET with the variables
5308 * appended at the end of the URL.
5309 *
5310 * <hr>
5311 */
5312
5313
5314 /** \var sswf::ActionURL::URL_METHOD_POST
5315 *
5316 * \brief Send the request using an HTTP POST
5317 *
5318 * Send the request as an HTTP POST with the variables
5319 * sent one per line, starting on the line after the URL.
5320 */
5321
5322
5323
5324
5325 /** \brief Initialize the ActionURL action.
5326 *
5327 * The constructor defines default values to the different variable
5328 * members. It sets the URL to none, the target to none and the
5329 * method to URL_METHOD_NOVARIABLES.
5330 *
5331 * This function can be called with either ACTION_URL or
5332 * ACTION_URL2.
5333 *
5334 * \param[in] tag The tag in which this action is being added
5335 * \param[in] action The SWF action to save this action
5336 */
ActionURL(TagBase * tag,action_t action)5337 ActionURL::ActionURL(TagBase *tag, action_t action)
5338 : Action(tag, action)
5339 {
5340 assert(action == ACTION_URL || action == ACTION_URL2, "only ACTION_URL or ACTION_URL2 can be specified to the ActionURL object.");
5341 if(action != ACTION_URL && action != ACTION_URL2) {
5342 throw ErrorManager::InternalErrorException();
5343 }
5344 f_url = 0;
5345 f_target = 0;
5346 f_method = URL_METHOD_NOVARIABLES;
5347 }
5348
5349
5350 /** \brief Set the URL and target names.
5351 *
5352 * This function is used to define a valid URL and target.
5353 *
5354 * The target can be the name of a window or set to '_top'
5355 * to replace the content of the current window.
5356 *
5357 * This function assumes that you defined the action as
5358 * ACTION_URL.
5359 *
5360 * \param[in] url A standard URL (i.e. http://sswf.m2osw.com)
5361 * \param[in] target A window name or a standard HTML target
5362 */
SetURL(const char * url,const char * target)5363 void ActionURL::SetURL(const char *url, const char *target)
5364 {
5365 MemFree(f_url);
5366 MemFree(f_target);
5367 f_url = StrDup(url);
5368 f_target = StrDup(target);
5369 }
5370
5371
5372 /** \brief Set the method used to pass the URL to the browser.
5373 *
5374 * Set the method to use execute the URL, this assumes that you
5375 * defined this action as an ACTION_URL2. This is one of the
5376 * following values:
5377 *
5378 * URL_METHOD_NOVARIABLE or URL_METHOD_NOVARIABLES
5379 * URL_METHOD_GET
5380 * URL_METHOD_POST
5381 *
5382 * \param[in] method One of the available methods
5383 */
SetMethod(url_method_t method)5384 void ActionURL::SetMethod(url_method_t method)
5385 {
5386 f_method = method;
5387 }
5388
5389
5390 /** \brief Create a clone of this action.
5391 *
5392 * This function creates a new ActionURL object and copy the
5393 * URL, target and method in it. Finally, it returns the pointer
5394 * to the new action.
5395 *
5396 * \return The pointer to the clone action
5397 */
Duplicate(void) const5398 Action *ActionURL::Duplicate(void) const
5399 {
5400 ActionURL *a;
5401
5402 a = new ActionURL(Tag(), f_action);
5403 a->SetURL(f_url, f_target);
5404 a->SetMethod(f_method);
5405
5406 return a;
5407 }
5408
5409
5410 /** \brief Save the action extraneous data in the Data buffer.
5411 *
5412 * This function saves the URL/target information (ACTION_URL) or
5413 * the method (ACTION_URL2) in the the Data buffer.
5414 *
5415 * \param[in] data The Data buffer where the URL information is saved
5416 * \param[in] nested_data There is no nested data in an ActionURL
5417 */
SaveData(Data & data,Data & nested_data)5418 ErrorManager::error_code_t ActionURL::SaveData(Data& data, Data& nested_data)
5419 {
5420 if(f_action == ACTION_URL) {
5421 ErrorManager::error_code_t ec = SaveString(data, f_url);
5422 return ErrorManager::KeepFirst(ec, SaveString(data, f_target));
5423 }
5424
5425 data.PutByte(f_method);
5426
5427 return ErrorManager::ERROR_CODE_NONE;
5428 }
5429
5430
5431
5432
5433
5434
5435 ////////////////////////////// Action WAIT FOR FRAME
5436
5437 /** \class sswf::ActionWaitForFrame
5438 *
5439 * \brief Create an action used to wait for a frame to be loaded.
5440 *
5441 * This class creates an action one can use to wait for a certain
5442 * frame to be saved. As long as that frame is not loaded, the
5443 * sub-actions are skipped. Once the frame was loaded, the actions
5444 * are executed. These actions can result in the execution of the
5445 * rest of the movie.
5446 *
5447 * \warning
5448 * The WaitForFrame action uses a byte to define the number of the
5449 * sub-actions to skip. That means a maximum of 255 actions, which is
5450 * relatively small for an ActionScript. In general, you can bypass
5451 * the problem by calling a function.
5452 *
5453 * \note
5454 * This is 255 actions. Thus in bytes it can be much larger. However,
5455 * do NOT try to define a function or an object within this block.
5456 * It is likely to fail.
5457 *
5458 * \bug
5459 * It could be that the ACTION_WAIT_FOR_FRAME and ACTION_WAIT_FOR_FRAME2
5460 * should each have its own class since the dynamic version should
5461 * not be given a frame name (it is taken dynamically!). On the other
5462 * hand it could be that I could change the code and if you define a
5463 * frame name then I force the ACTION_WAIT_FOR_FRAME and by default
5464 * I would use ACTION_WAIT_FOR_FRAME2. In this latter case, I would
5465 * need a PreSave() to determine the action before to save the result.
5466 *
5467 * \sa <a href="../SWFalexref.html#action_wait_for_frame">SWF Alexis' Reference—Wait For Frame</a>
5468 * \sa <a href="../SWFalexref.html#action_wait_for_frame_dynamic">SWF Alexis' Reference—Wait For Frame <i>(dynamic)</i></a>
5469 */
5470
5471 /** \brief Initialize the ActionWaitForFrame object.
5472 *
5473 * This constructor initializes the ActionWaitForFrame object with
5474 * a frame with no name and no actions.
5475 *
5476 * The action parameter can be set to:
5477 *
5478 * ACTION_WAIT_FOR_FRAME
5479 * ACTION_WAIT_FOR_FRAME2
5480 *
5481 * \param[in] tag The tag in which this action is being added
5482 * \param[in] action One of the wait for action codes
5483 */
ActionWaitForFrame(TagBase * tag,action_t action)5484 ActionWaitForFrame::ActionWaitForFrame(TagBase *tag, action_t action)
5485 : Action(tag, action)
5486 {
5487 assert(action == ACTION_WAIT_FOR_FRAME || action == ACTION_WAIT_FOR_FRAME2, "the action of an ActionWaitForFrame needs to be ACTION_WAIT_FOR_FRAME or ACTION_WAIT_FOR_FRAME2");
5488 if(action != ACTION_WAIT_FOR_FRAME && action != ACTION_WAIT_FOR_FRAME2) {
5489 throw ErrorManager::InternalErrorException();
5490 }
5491 // f_actions = ... -- auto-init with Vectors constructor
5492 f_frame_name = 0;
5493 }
5494
5495
5496 /** \brief Set the name of the frame to wait for.
5497 *
5498 * In case you used ACTION_WAIT_FOR_FRAME, this is the name of
5499 * the frame to wait for.
5500 *
5501 * \param[in] frame_name The name of the frame to wait for
5502 */
SetFrameName(const char * frame_name)5503 void ActionWaitForFrame::SetFrameName(const char *frame_name)
5504 {
5505 MemFree(f_frame_name);
5506 f_frame_name = StrDup(frame_name);
5507 }
5508
5509
5510 /** \brief Add a sub-action to the wait frame action.
5511 *
5512 * This function adds a sub-action to execute once the movie loaded the
5513 * specified frame.
5514 *
5515 * You can also access the list of sub-actions using the
5516 * sswf::ActioWaitForFrame::SubList() function.
5517 *
5518 * Note that the total number of these actions is 255 (and not
5519 * 255 bytes!) This makes it difficult to read this action.
5520 *
5521 * \param[in] action The action to append to this wait for frame
5522 */
AddAction(Action * action)5523 void ActionWaitForFrame::AddAction(Action *action)
5524 {
5525 f_actions.Set(-1, action);
5526 }
5527
5528
5529 /** \brief Create a clone of this action.
5530 *
5531 * This function creates a new ActionWaitForFrame and copies the
5532 * frame name and all the sub-actions in it. Finally, it returns
5533 * the pointer of the new action.
5534 *
5535 * \return The pointer of the clone action
5536 */
Duplicate(void) const5537 Action *ActionWaitForFrame::Duplicate(void) const
5538 {
5539 ActionWaitForFrame *w;
5540 Action *a;
5541 int idx, max;
5542
5543 w = new ActionWaitForFrame(Tag(), f_action);
5544 w->SetFrameName(f_frame_name);
5545 max = f_actions.Count();
5546 for(idx = 0; idx < max; idx++) {
5547 a = dynamic_cast<Action *>(f_actions.Get(idx));
5548 w->AddAction(a->Duplicate());
5549 }
5550
5551 return w;
5552 }
5553
5554
5555 /** \brief Return the Vectors holding the sub-actions.
5556 *
5557 * This function is used to retrieve the pointer of the Vectors
5558 * used to register all the sub-actions of this ActionWaitForFrame
5559 * object.
5560 *
5561 * \return The Vectors pointers of the sub-actions
5562 */
SubList(void)5563 Vectors *ActionWaitForFrame::SubList(void)
5564 {
5565 return &f_actions;
5566 }
5567
5568
5569 /** \brief Save the extraneous data of the ActionWaitForFrame object.
5570 *
5571 * This function saves the frame number (ACTION_WAIT_FOR_FRAME) and
5572 * the number of nested actions.
5573 *
5574 * If the specified frame is not found or no frame name is specified
5575 * for an ACTION_WAIT_FOR_FRAME, then an error results.
5576 *
5577 * \param[in] data The Data buffer where the information is saved
5578 * \param[in] nested_data The Action::Save() function defines this buffer,
5579 * this function does not need it since the size is not
5580 * what is saved in these actions
5581 */
SaveData(Data & data,Data & nested_data)5582 ErrorManager::error_code_t ActionWaitForFrame::SaveData(Data& data, Data& nested_data)
5583 {
5584 TagBase *tag;
5585 ErrorManager::error_code_t ec;
5586
5587 ec = ErrorManager::ERROR_CODE_NONE;
5588
5589 if(f_actions.Count() > 255) {
5590 ec = OnError(ErrorManager::ERROR_CODE_ACTION_OVERFLOW, "too many actions within a WaitForFrame; please, use branches as may be required.");
5591 }
5592
5593 if(f_action == ACTION_WAIT_FOR_FRAME) {
5594 if(f_frame_name == 0 || *f_frame_name == '\0') {
5595 // we save the frame name within the tag in this case
5596 // so we actually need it!
5597 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_MISSING_FRAME_NAME, "a frame name was expected for action WaitForFrame."));
5598 data.PutShort(0); // a default, just so the file is not boggus.
5599 }
5600 else {
5601 tag = Tag()->FindLabelledTag(f_frame_name);
5602 if(tag == 0) {
5603 /* ha! couldn't find this object... */
5604 ec = ErrorManager::KeepFirst(ec, OnError(ErrorManager::ERROR_CODE_OBJECT_NOT_FOUND, "cannot find any tag labelled '%s'.", f_frame_name));
5605 data.PutShort(0); // a default, just so the file is not boggus.
5606 }
5607 else {
5608 data.PutShort(tag->WhichFrame());
5609 }
5610 }
5611 }
5612
5613 data.PutByte(f_actions.Count());
5614
5615 return ec;
5616 }
5617
5618
5619 ////////////////////////////// Action WITH
5620
5621 /** \class sswf::ActionWith
5622 *
5623 * \brief Block including variable member names refering to the With object.
5624 *
5625 * This action is supposed to be useful to optimize JavaScript code by
5626 * not having to fully qualify variables by their respective object name.
5627 *
5628 * For instance, the following code:
5629 *
5630 * \code
5631 * obj.a = 1;
5632 * obj.b = 2;
5633 * obj.c = 3;
5634 * obj.d = 4;
5635 * obj.e = 5;
5636 * \endcode
5637 *
5638 * can be simplified using a 'with' instruction as follow:
5639 *
5640 * \code
5641 * with obj {
5642 * a = 1;
5643 * b = 2;
5644 * c = 3;
5645 * d = 4;
5646 * e = 5;
5647 * }
5648 * \endcode
5649 *
5650 * \sa <a href="../SWFalexref.html#action_with">SWF Alexis' Reference—With</a>
5651 */
5652
5653 /** \brief Initialize the ActionWith object.
5654 *
5655 * This function initialize the 'with' object by making the 'with' block
5656 * empty.
5657 *
5658 * \param[in] tag The tag where the With is inserted
5659 */
ActionWith(TagBase * tag)5660 ActionWith::ActionWith(TagBase *tag)
5661 : Action(tag, ACTION_WITH)
5662 {
5663 }
5664
5665
5666 /** \brief Add an action to the 'with' block.
5667 *
5668 * The 'with' block is a list of actions which can be grown using this
5669 * function. Note that you can have several levels of 'with' (i.e. within
5670 * a 'with' block you can have another 'with' block to a depth of 7 up to
5671 * version 5 of SWF, and 15 in version 6 of SWF.)
5672 *
5673 * Of course, it can be quite tedious to know what variable reference
5674 * which object when all the objects have variable and function members
5675 * of the same name (it should be the inner most object which has a match.)
5676 *
5677 * Note that the action being added is not duplicated.
5678 *
5679 * \param[in] action The pointer to the action to add to this ActionWith
5680 */
AddAction(Action * action)5681 void ActionWith::AddAction(Action *action)
5682 {
5683 f_actions.Set(-1, action);
5684 }
5685
5686
5687 /** \brief Create a clone of this ActionWith object.
5688 *
5689 * This function creates a new ActionWith object and copies all the
5690 * actions of 'this' ActionWith in it. Finally, it returns a pointer
5691 * to the newly allocated object.
5692 *
5693 * \return The newly allocated action pointer
5694 */
Duplicate(void) const5695 Action *ActionWith::Duplicate(void) const
5696 {
5697 ActionWith *w;
5698 Action *a;
5699 int max, idx;
5700
5701 w = new ActionWith(Tag());
5702 max = f_actions.Count();
5703 for(idx = 0; idx < max; idx++) {
5704 a = dynamic_cast<Action *>(f_actions.Get(idx));
5705 w->AddAction(a->Duplicate());
5706 }
5707
5708 return w;
5709 }
5710
5711
5712 /** \brief The sub-list of actions of this ActionWith.
5713 *
5714 * This function returns a direct pointer to the Vectors of this
5715 * ActioWith object. This Vectors array holds all the actions to
5716 * execute once the specified frame was loaded.
5717 *
5718 * Do not forget that the actions are limited to a byte size of
5719 * 65535 in the outer most ActionWith object.
5720 *
5721 * \return A Vectors pointer to fill with actions
5722 */
SubList(void)5723 Vectors *ActionWith::SubList(void)
5724 {
5725 return &f_actions;
5726 }
5727
5728
5729 /** \brief Save the byte size of the nested data.
5730 *
5731 * This function saves the extraneous data for an ActionWith object
5732 * which is the size of the nested data buffer in bytes.
5733 *
5734 * \param[in] data The Data buffer where the size is to be saved
5735 * \param[in] nested_data The Data buffer which holds the sub-actions
5736 */
SaveData(Data & data,Data & nested_data)5737 ErrorManager::error_code_t ActionWith::SaveData(Data& data, Data& nested_data)
5738 {
5739 // the actions were already saved by the Action::Save() function!
5740 data.PutShort((unsigned short) nested_data.ByteSize());
5741
5742 return ErrorManager::ERROR_CODE_NONE;
5743 }
5744
5745
5746
5747 /* The following options fold the documentation; use 'zi' to turn on and off
5748 *
5749 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
5750 */
5751