Source code: com/anotherbigidea/flash/writers/ActionWriter.java
1 /****************************************************************
2 * Copyright (c) 2001, David N. Main, All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the
6 * following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * 3. The name of the author may not be used to endorse or
18 * promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ****************************************************************/
34 package com.anotherbigidea.flash.writers;
35
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.util.Enumeration;
39 import java.util.Hashtable;
40 import java.util.Stack;
41 import java.util.Vector;
42
43 import com.anotherbigidea.flash.SWFActionCodes;
44 import com.anotherbigidea.flash.SWFConstants;
45 import com.anotherbigidea.flash.interfaces.SWFActions;
46 import com.anotherbigidea.io.OutStream;
47
48 /**
49 * A writer that implements the SWFActions interface and writes
50 * action bytes to an OutStream
51 */
52 public class ActionWriter implements SWFActions, SWFActionCodes
53 {
54 protected TagWriter tagWriter;
55 protected OutStream out;
56 protected ByteArrayOutputStream bout;
57 protected int count;
58 protected int flashVersion;
59 protected String mStringEncoding;
60
61 protected Vector pushValues;
62
63 protected Hashtable labels;
64 protected Vector jumps;
65 protected Vector skips;
66
67 //--for fixing up functions and WITH blocks..
68 protected Vector blocks;
69 protected Stack blockStack;
70
71 public ActionWriter( TagWriter tagWriter, int flashVersion )
72 {
73 this.flashVersion = flashVersion;
74 this.tagWriter = tagWriter;
75
76 mStringEncoding = ( flashVersion >= SWFConstants.FLASH_MX_VERSION ) ?
77 SWFConstants.STRING_ENCODING_MX :
78 SWFConstants.STRING_ENCODING_PRE_MX;
79 }
80
81 /**
82 * @return the code count
83 */
84 protected int writeCode( int code ) throws IOException
85 {
86 if( pushValues.size() > 0 ) flushPushValues();
87 out.writeUI8( code );
88 count++;
89 return count;
90 }
91
92 /**
93 * SWFActions interface
94 */
95 public void start( int conditions ) throws IOException
96 {
97 //ignore conditions
98
99 count = 0;
100 bout = new ByteArrayOutputStream();
101 out = new OutStream( bout );
102 pushValues = new Vector();
103 labels = null;
104 jumps = null;
105 skips = null;
106 blocks = null;
107 blockStack = null;
108 }
109
110 /**
111 * SWFActions interface
112 */
113 public void end() throws IOException
114 {
115 writeCode( 0 );
116 out.flush();
117 byte[] bytes = bout.toByteArray();
118
119 //--Fix up jumps and skips
120 if( labels != null )
121 {
122 if( jumps != null ) fixupJumps(bytes);
123 if( skips != null ) fixupSkips(bytes);
124 }
125
126 if( blocks != null ) fixupBlocks(bytes);
127
128 writeBytes( bytes );
129 }
130
131 /**
132 * Pass through a blob of actions
133 */
134 public void blob( byte[] blob ) throws IOException
135 {
136 writeBytes( blob );
137 }
138
139 protected void writeBytes( byte[] bytes ) throws IOException
140 {
141 tagWriter.getOutStream().write( bytes );
142 }
143
144 /**
145 * SWFActions interface
146 */
147 public void done() throws IOException
148 {
149 tagWriter.completeTag();
150 }
151
152 protected void fixupBlocks( byte[] bytes )
153 {
154 for( Enumeration enum = blocks.elements(); enum.hasMoreElements(); )
155 {
156 int[] info = (int[])enum.nextElement();
157
158 int codeSize = info[1];
159 int offset = info[0];
160 byte[] sizeBytes = OutStream.sintTo2Bytes( codeSize );
161
162 bytes[ offset ] = sizeBytes[0];
163 bytes[ offset + 1 ] = sizeBytes[1];
164 }
165 }
166
167 protected void fixupJumps( byte[] bytes )
168 {
169 for( Enumeration enum = jumps.elements(); enum.hasMoreElements(); )
170 {
171 Object[] obja = (Object[])enum.nextElement();
172 String label = (String)obja[0];
173 int target = ((Integer)obja[1]).intValue();
174
175 int[] labelInfo = (int[])labels.get( label );
176
177 if( labelInfo == null )
178 {
179 System.out.println( "Missing label '" + label + "' in action code" );
180 continue;
181 }
182
183 int absolute = labelInfo[0]; //offset of the label
184 int relative = absolute - ( target + 2 ); //relative jump
185
186 byte[] val = OutStream.sintTo2Bytes( relative );
187 bytes[target ] = val[0];
188 bytes[target+1] = val[1];
189 }
190 }
191
192 protected void fixupSkips( byte[] bytes )
193 {
194 for( Enumeration enum = skips.elements(); enum.hasMoreElements(); )
195 {
196 Object[] obja = (Object[])enum.nextElement();
197 String label = (String)obja[0];
198
199 int[] skipInfo = (int[])obja[1];
200 int skipIndex = skipInfo[0];
201 int skipLoc = skipInfo[1];
202
203 int[] labelInfo = (int[])labels.get( label );
204
205 if( labelInfo == null )
206 {
207 System.out.println( "Missing label '" + label + "' in action code" );
208 continue;
209 }
210
211 int labelIndex = labelInfo[1]; //index of the labelled action
212 int skip = labelIndex - skipIndex - 1;
213
214 byte val = OutStream.uintToByte( skip );
215 bytes[skipLoc] = val;
216 }
217 }
218
219 /**
220 * SWFActions interface
221 */
222 public void comment( String comment ) throws IOException
223 {
224 //ignore comments
225 }
226
227 /**
228 * SWFActions interface
229 */
230 public void unknown( int code, byte[] data ) throws IOException
231 {
232 writeCode( code );
233
234 int length = (data != null) ? data.length : 0;
235
236 if( code >= 0x80 || length > 0 )
237 {
238 out.writeUI16( length );
239 }
240
241 if( length > 0 ) out.write( data );
242 }
243
244 /**
245 * SWFActions interface
246 */
247 public void initArray() throws IOException
248 {
249 writeCode( INIT_ARRAY );
250 }
251
252 /**
253 * SWFActions interface
254 */
255 public void jumpLabel( String label ) throws IOException
256 {
257 if( pushValues.size() > 0 ) flushPushValues();
258
259 int offset = (int)out.getCount();
260
261 if( labels == null ) labels = new Hashtable();
262 labels.put( label, new int[] { offset, count + 1 } );
263 }
264
265 /**
266 * SWFActions interface
267 */
268 public void gotoFrame( int frameNumber ) throws IOException
269 {
270 writeCode( GOTO_FRAME );
271 out.writeUI16( 2 );
272 out.writeUI16( frameNumber );
273 }
274
275 /**
276 * SWFActions interface
277 */
278 public void gotoFrame( String label ) throws IOException
279 {
280 writeCode( GOTO_LABEL );
281 out.writeUI16 ( OutStream.getStringLength( label ) );
282 out.writeString( label, mStringEncoding );
283 }
284
285 /**
286 * SWFActions interface
287 */
288 public void getURL( String url, String target ) throws IOException
289 {
290 writeCode( GET_URL );
291 out.writeUI16 ( OutStream.getStringLength(url) + OutStream.getStringLength(target) );
292 out.writeString( url, mStringEncoding );
293 out.writeString( target, mStringEncoding );
294 }
295
296 /**
297 * SWFActions interface
298 */
299 public void nextFrame() throws IOException
300 {
301 writeCode( NEXT_FRAME );
302 }
303
304 /**
305 * SWFActions interface
306 */
307 public void prevFrame() throws IOException
308 {
309 writeCode( PREVIOUS_FRAME );
310 }
311
312 /**
313 * SWFActions interface
314 */
315 public void play() throws IOException
316 {
317 writeCode( PLAY );
318 }
319
320 /**
321 * SWFActions interface
322 */
323 public void stop() throws IOException
324 {
325 writeCode( STOP );
326 }
327
328 /**
329 * SWFActions interface
330 */
331 public void toggleQuality() throws IOException
332 {
333 writeCode( TOGGLE_QUALITY );
334 }
335
336 /**
337 * SWFActions interface
338 */
339 public void stopSounds() throws IOException
340 {
341 writeCode( STOP_SOUNDS );
342 }
343
344 /**
345 * SWFActions interface
346 */
347 public void setTarget( String target ) throws IOException
348 {
349 writeCode( SET_TARGET );
350 out.writeUI16 ( OutStream.getStringLength( target ) );
351 out.writeString( target, mStringEncoding );
352 }
353
354 protected void writeJump( String label, int code ) throws IOException
355 {
356 writeCode( code );
357 out.writeUI16( 2 );
358
359 int here = (int)out.getCount();
360 out.writeUI16( 0 ); //will be fixed up later
361
362 //--save jump info for later fix-up logic
363 if( jumps == null ) jumps = new Vector();
364 jumps.addElement( new Object[] { label, new Integer( here ) } );
365 }
366
367 /**
368 * SWFActions interface
369 */
370 public void jump( String jumpLabel ) throws IOException
371 {
372 writeJump( jumpLabel, JUMP );
373 }
374
375 /**
376 * SWFActions interface
377 */
378 public void ifJump( String jumpLabel ) throws IOException
379 {
380 writeJump( jumpLabel, IF );
381 }
382
383 /**
384 * SWFActions interface
385 */
386 public void waitForFrame( int frameNumber, String jumpLabel ) throws IOException
387 {
388 writeCode( WAIT_FOR_FRAME );
389 out.writeUI16( 3 );
390 out.writeUI16( frameNumber );
391
392 int here = (int)out.getCount();
393 out.writeUI8 ( 0 ); //will be fixed up later
394
395 //--save skip info for later fix-up logic
396 if( skips == null ) skips = new Vector();
397 skips.addElement( new Object[] { jumpLabel, new int[] { count, here }} );
398 }
399
400 /**
401 * SWFActions interface
402 */
403 public void waitForFrame( String jumpLabel ) throws IOException
404 {
405 writeCode( WAIT_FOR_FRAME_2 );
406 out.writeUI16( 1 );
407
408 int here = (int)out.getCount();
409 out.writeUI8 ( 0 ); //will be fixed up later
410
411 //--save skip info for later fix-up logic
412 if( skips == null ) skips = new Vector();
413 skips.addElement( new Object[] { jumpLabel, new int[] { count, here }} );
414 }
415
416 /**
417 * SWFActions interface
418 */
419 public void pop() throws IOException
420 {
421 writeCode( POP );
422 }
423
424 /**
425 * SWFActions interface
426 */
427 public void add() throws IOException
428 {
429 writeCode( ADD );
430 }
431
432 /**
433 * SWFActions interface
434 */
435 public void substract() throws IOException
436 {
437 writeCode( SUBTRACT );
438 }
439
440 /**
441 * SWFActions interface
442 */
443 public void multiply() throws IOException
444 {
445 writeCode( MULTIPLY );
446 }
447
448 /**
449 * SWFActions interface
450 */
451 public void divide() throws IOException
452 {
453 writeCode( DIVIDE );
454 }
455
456 /**
457 * SWFActions interface
458 */
459 public void equals() throws IOException
460 {
461 writeCode( EQUALS );
462 }
463
464 /**
465 * SWFActions interface
466 */
467 public void lessThan() throws IOException
468 {
469 writeCode( LESS );
470 }
471
472 /**
473 * SWFActions interface
474 */
475 public void and() throws IOException
476 {
477 writeCode( AND );
478 }
479
480 /**
481 * SWFActions interface
482 */
483 public void or() throws IOException
484 {
485 writeCode( OR );
486 }
487
488 /**
489 * SWFActions interface
490 */
491 public void not() throws IOException
492 {
493 writeCode( NOT );
494 }
495
496 /**
497 * SWFActions interface
498 */
499 public void stringEquals() throws IOException
500 {
501 writeCode( STRING_EQUALS );
502 }
503
504 /**
505 * SWFActions interface
506 */
507 public void stringLength() throws IOException
508 {
509 writeCode( STRING_LENGTH );
510 }
511
512 /**
513 * SWFActions interface
514 */
515 public void concat() throws IOException
516 {
517 writeCode( STRING_ADD );
518 }
519
520 /**
521 * SWFActions interface
522 */
523 public void substring() throws IOException
524 {
525 writeCode( STRING_EXTRACT );
526 }
527
528 /**
529 * SWFActions interface
530 */
531 public void stringLessThan() throws IOException
532 {
533 writeCode( STRING_LESS );
534 }
535
536 /**
537 * SWFActions interface
538 */
539 public void stringLengthMB() throws IOException
540 {
541 writeCode( MB_STRING_LENGTH );
542 }
543
544 /**
545 * SWFActions interface
546 */
547 public void substringMB() throws IOException
548 {
549 writeCode( MB_STRING_EXTRACT );
550 }
551
552 /**
553 * SWFActions interface
554 */
555 public void toInteger() throws IOException
556 {
557 writeCode( TO_INTEGER );
558 }
559
560 /**
561 * SWFActions interface
562 */
563 public void charToAscii() throws IOException
564 {
565 writeCode( CHAR_TO_ASCII );
566 }
567
568 /**
569 * SWFActions interface
570 */
571 public void asciiToChar() throws IOException
572 {
573 writeCode( ASCII_TO_CHAR );
574 }
575
576 /**
577 * SWFActions interface
578 */
579 public void charMBToAscii() throws IOException
580 {
581 writeCode( MB_CHAR_TO_ASCII );
582 }
583
584 /**
585 * SWFActions interface
586 */
587 public void asciiToCharMB() throws IOException
588 {
589 writeCode( MB_ASCII_TO_CHAR );
590 }
591
592 /**
593 * SWFActions interface
594 */
595 public void call() throws IOException
596 {
597 writeCode( CALL );
598 out.writeUI16( 0 ); //SWF File Format anomaly
599 }
600
601 /**
602 * SWFActions interface
603 */
604 public void getVariable() throws IOException
605 {
606 writeCode( GET_VARIABLE );
607 }
608
609 /**
610 * SWFActions interface
611 */
612 public void setVariable() throws IOException
613 {
614 writeCode( SET_VARIABLE );
615 }
616
617 /**
618 * SWFActions interface
619 */
620 public void getURL( int sendVars, int loadMode ) throws IOException
621 {
622 writeCode( GET_URL_2 );
623 out.writeUI16( 1 );
624
625 int flags = 0;
626
627 String sendVars_ = null;
628 switch( sendVars )
629 {
630 case GET_URL_SEND_VARS_GET: flags = 1; break;
631 case GET_URL_SEND_VARS_POST: flags = 2; break;
632
633 case GET_URL_SEND_VARS_NONE:
634 default: break;
635 }
636
637 String mode = null;
638 switch( loadMode )
639 {
640 case GET_URL_MODE_LOAD_MOVIE_INTO_LEVEL: break;
641 case GET_URL_MODE_LOAD_MOVIE_INTO_SPRITE: flags |= 0x40; break;
642 case GET_URL_MODE_LOAD_VARS_INTO_LEVEL : flags |= 0x80; break;
643 case GET_URL_MODE_LOAD_VARS_INTO_SPRITE: flags |= 0xC0; break;
644 default: break;
645 }
646
647 out.writeUI8( flags );
648 }
649
650
651 /**
652 * SWFActions interface
653 */
654 public void gotoFrame( boolean play ) throws IOException
655 {
656 writeCode( GOTO_FRAME_2 );
657 out.writeUI16( 1 );
658 out.writeUI8( play ? 1 : 0 );
659 }
660
661 /**
662 * SWFActions interface
663 */
664 public void setTarget() throws IOException
665 {
666 writeCode( SET_TARGET_2 );
667 }
668
669 /**
670 * SWFActions interface
671 */
672 public void getProperty() throws IOException
673 {
674 writeCode( GET_PROPERTY );
675 }
676
677 /**
678 * SWFActions interface
679 */
680 public void setProperty() throws IOException
681 {
682 writeCode( SET_PROPERTY );
683 }
684
685 /**
686 * SWFActions interface
687 */
688 public void cloneSprite() throws IOException
689 {
690 writeCode( CLONE_SPRITE );
691 }
692
693 /**
694 * SWFActions interface
695 */
696 public void removeSprite() throws IOException
697 {
698 writeCode( REMOVE_SPRITE );
699 }
700
701 /**
702 * SWFActions interface
703 */
704 public void startDrag() throws IOException
705 {
706 writeCode( START_DRAG );
707 }
708
709 /**
710 * SWFActions interface
711 */
712 public void endDrag() throws IOException
713 {
714 writeCode( END_DRAG );
715 }
716
717 /**
718 * SWFActions interface
719 */
720 public void trace() throws IOException
721 {
722 writeCode( TRACE );
723 }
724
725 /**
726 * SWFActions interface
727 */
728 public void getTime() throws IOException
729 {
730 writeCode( GET_TIME );
731 }
732
733 /**
734 * SWFActions interface
735 */
736 public void randomNumber() throws IOException
737 {
738 writeCode( RANDOM_NUMBER );
739 }
740
741 /**
742 * SWFActions interface
743 */
744 public void lookupTable( String[] values ) throws IOException
745 {
746 writeCode( LOOKUP_TABLE );
747
748 ByteArrayOutputStream baout = new ByteArrayOutputStream();
749 OutStream bout = new OutStream( baout );
750
751 bout.writeUI16( values.length );
752
753 for( int i = 0; i < values.length; i++ )
754 {
755 bout.writeString( values[i], mStringEncoding );
756 }
757
758 bout.flush();
759 byte[] data = baout.toByteArray();
760 out.writeUI16( data.length );
761 out.write( data );
762 }
763
764 /**
765 * SWFActions interface
766 */
767 public void callFunction() throws IOException
768 {
769 writeCode( CALL_FUNCTION );
770 }
771
772 /**
773 * SWFActions interface
774 */
775 public void callMethod() throws IOException
776 {
777 writeCode( CALL_METHOD );
778 }
779
780 /**
781 * SWFActions interface
782 */
783 public void startFunction( String name, String[] paramNames ) throws IOException
784 {
785 if( blockStack == null ) blockStack = new Stack();
786
787 writeCode( DEFINE_FUNCTION );
788
789 ByteArrayOutputStream baout = new ByteArrayOutputStream();
790 OutStream bout = new OutStream( baout );
791
792 bout.writeString( name, mStringEncoding );
793 bout.writeUI16( paramNames.length );
794
795 for( int i = 0; i < paramNames.length; i++ )
796 {
797 bout.writeString( paramNames[i], mStringEncoding );
798 }
799
800 bout.writeUI16( 0 ); //code size - will be fixed up later
801
802 bout.flush();
803 byte[] data = baout.toByteArray();
804 out.writeUI16( data.length );
805 out.write( data );
806
807 blockStack.push( new int[]{ (int)out.getCount(), 0 } );
808 }
809
810 /**
811 * SWFActions interface
812 */
813 public void endBlock() throws IOException
814 {
815 if( blockStack == null || blockStack.isEmpty() ) return; //nothing to do
816 int[] blockInfo = (int[])blockStack.pop();
817
818 if( blocks == null ) blocks = new Vector();
819
820 int offset = blockInfo[0];
821 int codeSize = ((int)out.getCount()) - offset;
822
823 //--store this info for later fix-up
824 blockInfo[0] = offset - 2;
825 blockInfo[1] = codeSize;
826 blocks.addElement( blockInfo );
827 }
828
829 /**
830 * SWFActions interface
831 */
832 public void defineLocalValue() throws IOException
833 {
834 writeCode( DEFINE_LOCAL_VAL );
835 }
836
837 /**
838 * SWFActions interface
839 */
840 public void defineLocal() throws IOException
841 {
842 writeCode( DEFINE_LOCAL );
843 }
844
845 /**
846 * SWFActions interface
847 */
848 public void deleteProperty() throws IOException
849 {
850 writeCode( DEL_VAR );
851 }
852
853 /**
854 * SWFActions interface
855 */
856 public void deleteThreadVars() throws IOException
857 {
858 writeCode( DEL_THREAD_VARS );
859 }
860
861 /**
862 * SWFActions interface
863 */
864 public void enumerate() throws IOException
865 {
866 writeCode( ENUMERATE );
867 }
868
869 /**
870 * SWFActions interface
871 */
872 public void typedEquals() throws IOException
873 {
874 writeCode( TYPED_EQUALS );
875 }
876
877 /**
878 * SWFActions interface
879 */
880 public void getMember() throws IOException
881 {
882 writeCode( GET_MEMBER );
883 }
884
885 /**
886 * SWFActions interface
887 */
888 public void initObject() throws IOException
889 {
890 writeCode( INIT_OBJECT );
891 }
892
893 /**
894 * SWFActions interface
895 */
896 public void newMethod() throws IOException
897 {
898 writeCode( CALL_NEW_METHOD );
899 }
900
901 /**
902 * SWFActions interface
903 */
904 public void newObject() throws IOException
905 {
906 writeCode( NEW_OBJECT );
907 }
908
909 /**
910 * SWFActions interface
911 */
912 public void setMember() throws IOException
913 {
914 writeCode( SET_MEMBER );
915 }
916
917 /**
918 * SWFActions interface
919 */
920 public void getTargetPath() throws IOException
921 {
922 writeCode( GET_TARGET_PATH );
923 }
924
925 /**
926 * SWFActions interface
927 */
928 public void startWith() throws IOException
929 {
930 writeCode( WITH );
931 out.writeUI16( 2 );
932 out.writeUI16( 0 ); //codeSize - will be fixed up later
933
934 //--push the block start info
935 if( blockStack == null ) blockStack = new Stack();
936 blockStack.push( new int[]{ (int)out.getCount(), 0 } );
937 }
938
939 /**
940 * SWFActions interface
941 */
942 public void duplicate() throws IOException
943 {
944 writeCode( DUPLICATE );
945 }
946
947 /**
948 * SWFActions interface
949 */
950 public void returnValue() throws IOException
951 {
952 writeCode( RETURN );
953 }
954
955 /**
956 * SWFActions interface
957 */
958 public void swap() throws IOException
959 {
960 writeCode( SWAP );
961 }
962
963 /**
964 * SWFActions interface
965 */
966 public void storeInRegister( int registerNumber ) throws IOException
967 {
968 writeCode( REGISTER );
969 out.writeUI16( 1 );
970 out.writeUI8( registerNumber );
971 }
972
973 /**
974 * SWFActions interface
975 */
976 public void convertToNumber() throws IOException
977 {
978 writeCode( CONVERT_TO_NUMBER );
979 }
980
981 /**
982 * SWFActions interface
983 */
984 public void convertToString() throws IOException
985 {
986 writeCode( CONVERT_TO_STRING );
987 }
988
989 /**
990 * SWFActions interface
991 */
992 public void typeOf() throws IOException
993 {
994 writeCode( TYPEOF );
995 }
996
997 /**
998 * SWFActions interface
999 */
1000 public void typedAdd() throws IOException
1001 {
1002 writeCode( TYPED_ADD );
1003 }
1004
1005 /**
1006 * SWFActions interface
1007 */
1008 public void typedLessThan() throws IOException
1009 {
1010 writeCode( TYPED_LESS_THAN );
1011 }
1012
1013 /**
1014 * SWFActions interface
1015 */
1016 public void modulo() throws IOException
1017 {
1018 writeCode( MODULO );
1019 }
1020
1021 /**
1022 * SWFActions interface
1023 */
1024 public void bitAnd() throws IOException
1025 {
1026 writeCode( BIT_AND );
1027 }
1028
1029 /**
1030 * SWFActions interface
1031 */
1032 public void bitOr() throws IOException
1033 {
1034 writeCode( BIT_OR );
1035 }
1036
1037 /**
1038 * SWFActions interface
1039 */
1040 public void bitXor() throws IOException
1041 {
1042 writeCode( BIT_XOR );
1043 }
1044
1045 /**
1046 * SWFActions interface
1047 */
1048 public void shiftLeft() throws IOException
1049 {
1050 writeCode( SHIFT_LEFT );
1051 }
1052
1053 /**
1054 * SWFActions interface
1055 */
1056 public void shiftRight() throws IOException
1057 {
1058 writeCode( SHIFT_RIGHT );
1059 }
1060
1061 /**
1062 * SWFActions interface
1063 */
1064 public void shiftRightUnsigned() throws IOException
1065 {
1066 writeCode( SHIFT_UNSIGNED );
1067 }
1068
1069 /**
1070 * SWFActions interface
1071 */
1072 public void decrement() throws IOException
1073 {
1074 writeCode( DECREMENT );
1075 }
1076
1077 /**
1078 * SWFActions interface
1079 */
1080 public void increment() throws IOException
1081 {
1082 writeCode( INCREMENT );
1083 }
1084
1085 protected void flushPushValues() throws IOException
1086 {
1087 out.writeUI8( PUSH );
1088 count++;
1089
1090 ByteArrayOutputStream baout = new ByteArrayOutputStream();
1091 OutStream bout = new OutStream( baout );
1092
1093 for( Enumeration enum = pushValues.elements(); enum.hasMoreElements(); )
1094 {
1095 Object value = enum.nextElement();
1096
1097 if( value instanceof String )
1098 {
1099 bout.writeUI8( PUSHTYPE_STRING );
1100 bout.writeString( value.toString(), mStringEncoding );
1101 }
1102 else if( value instanceof Boolean )
1103 {
1104 bout.writeUI8( PUSHTYPE_BOOLEAN );
1105 bout.writeUI8( ((Boolean)value).booleanValue() ? 1 : 0 );
1106 }
1107 else if( value instanceof Integer )
1108 {
1109 bout.writeUI8( PUSHTYPE_INTEGER );
1110 bout.writeSI32( ((Integer)value).intValue() );
1111 }
1112 else if( value instanceof Short )
1113 {
1114 bout.writeUI8( PUSHTYPE_LOOKUP );
1115 bout.writeUI8( ((Short)value).intValue() );
1116 }
1117 else if( value instanceof Byte )
1118 {
1119 bout.writeUI8( PUSHTYPE_REGISTER );
1120 bout.writeUI8( ((Byte)value).intValue() );
1121 }
1122 else if( value instanceof Float )
1123 {
1124 bout.writeUI8( PUSHTYPE_FLOAT );
1125 bout.writeFloat( ((Float)value).floatValue() );
1126 }
1127 else if( value instanceof Double )
1128 {
1129 bout.writeUI8( PUSHTYPE_DOUBLE );
1130 bout.writeDouble( ((Double)value).doubleValue() );
1131 }
1132 else
1133 {
1134 bout.writeUI8( PUSHTYPE_NULL );
1135 }
1136 }
1137
1138 pushValues.removeAllElements();
1139
1140 bout.flush();
1141 byte[] data = baout.toByteArray();
1142 out.writeUI16( data.length );
1143 out.write( data );
1144 }
1145
1146 /**
1147 * SWFActions interface
1148 */
1149 public void push( String value ) throws IOException
1150 {
1151 pushValues.addElement( value );
1152 if( flashVersion < 5 ) flushPushValues();
1153 }
1154
1155 /**
1156 * SWFActions interface
1157 */
1158 public void push( float value ) throws IOException
1159 {
1160 pushValues.addElement( new Float( value ) );
1161 if( flashVersion < 5 ) flushPushValues();
1162 }
1163
1164 /**
1165 * SWFActions interface
1166 */
1167 public void push( double value ) throws IOException
1168 {
1169 pushValues.addElement( new Double( value ) );
1170 if( flashVersion < 5 ) flushPushValues();
1171 }
1172
1173 /**
1174 * SWFActions interface
1175 */
1176 public void pushNull() throws IOException
1177 {
1178 pushValues.addElement( new Object() );
1179 if( flashVersion < 5 ) flushPushValues();
1180 }
1181
1182 /**
1183 * SWFActions interface
1184 */
1185 public void pushRegister( int registerNumber ) throws IOException
1186 {
1187 pushValues.addElement( new Byte( (byte)registerNumber ) );
1188 if( flashVersion < 5 ) flushPushValues();
1189 }
1190
1191 /**
1192 * SWFActions interface
1193 */
1194 public void push( boolean value ) throws IOException
1195 {
1196 pushValues.addElement( new Boolean( value ) );
1197 if( flashVersion < 5 ) flushPushValues();
1198 }
1199
1200 /**
1201 * SWFActions interface
1202 */
1203 public void push( int value ) throws IOException
1204 {
1205 pushValues.addElement( new Integer( value ) );
1206 if( flashVersion < 5 ) flushPushValues();
1207 }
1208
1209 /**
1210 * SWFActions interface
1211 */
1212 public void lookup( int dictionaryIndex ) throws IOException
1213 {
1214 pushValues.addElement( new Short( (short)dictionaryIndex ) );
1215 if( flashVersion < 5 ) flushPushValues();
1216 }
1217
1218 /**
1219 * @see com.anotherbigidea.flash.interfaces.SWFActions#enumerateObject()
1220 */
1221 public void enumerateObject() throws IOException {
1222 writeCode( ENUMERATE_OBJECT );
1223 }
1224
1225 /**
1226 * @see com.anotherbigidea.flash.interfaces.SWFActions#greaterThan()
1227 */
1228 public void greaterThan() throws IOException {
1229 writeCode( GREATER );
1230 }
1231
1232 /**
1233 * @see com.anotherbigidea.flash.interfaces.SWFActions#instanceOf()
1234 */
1235 public void instanceOf() throws IOException {
1236 writeCode( INSTANCE_OF );
1237 }
1238
1239 /**
1240 * @see com.anotherbigidea.flash.interfaces.SWFActions#strictEquals()
1241 */
1242 public void strictEquals() throws IOException {
1243 writeCode( STRICT_EQUALS );
1244 }
1245
1246 /**
1247 * @see com.anotherbigidea.flash.interfaces.SWFActions#stringGreaterThan()
1248 */
1249 public void stringGreaterThan() throws IOException {
1250 writeCode( STRING_GREATER );
1251 }
1252
1253}