source: trunk/src/org/expeditee/actions/Simple.java@ 87

Last change on this file since 87 was 87, checked in by ra33, 16 years ago

Fixed some stuff with the SIMPLE debugger
Refactored the way the interpretor works to make it easier to give better error messages.

File size: 83.3 KB
Line 
1package org.expeditee.actions;
2
3import java.awt.Color;
4import java.awt.Point;
5import java.awt.event.InputEvent;
6import java.io.BufferedReader;
7import java.io.InputStreamReader;
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.HashMap;
11import java.util.LinkedList;
12import java.util.List;
13import java.util.Map;
14import java.util.Random;
15
16import org.expeditee.agents.DefaultAgent;
17import org.expeditee.agents.DisplayTree;
18import org.expeditee.agents.WriteTree;
19import org.expeditee.gui.AttributeUtils;
20import org.expeditee.gui.DisplayIO;
21import org.expeditee.gui.Frame;
22import org.expeditee.gui.FrameGraphics;
23import org.expeditee.gui.FrameIO;
24import org.expeditee.gui.FrameKeyboardActions;
25import org.expeditee.gui.FrameMouseActions;
26import org.expeditee.gui.FrameUtils;
27import org.expeditee.io.Conversion;
28import org.expeditee.items.Dot;
29import org.expeditee.items.Item;
30import org.expeditee.items.ItemUtils;
31import org.expeditee.items.Line;
32import org.expeditee.items.Text;
33import org.expeditee.items.Item.SelectedMode;
34import org.expeditee.simple.AboveMaxParametreCountException;
35import org.expeditee.simple.BelowMinParametreCountException;
36import org.expeditee.simple.Context;
37import org.expeditee.simple.IncorrectParametreCountException;
38import org.expeditee.simple.IncorrectTypeException;
39import org.expeditee.simple.Pointers;
40import org.expeditee.simple.Primitives;
41import org.expeditee.simple.SBoolean;
42import org.expeditee.simple.SCharacter;
43import org.expeditee.simple.SInteger;
44import org.expeditee.simple.SPointer;
45import org.expeditee.simple.SPrimitive;
46import org.expeditee.simple.SReal;
47import org.expeditee.simple.SString;
48import org.expeditee.simple.SVariable;
49import org.expeditee.simple.UnitTestFailedException;
50import org.expeditee.stats.AgentStats;
51import org.expeditee.stats.SessionStats;
52
53public class Simple implements Runnable {
54
55 private static final String DEFAULT_STRING = "$s.";
56
57 private static final String DEFAULT_BOOLEAN = "$b.";
58
59 private static final String DEFAULT_CHAR = "$c.";
60
61 private static final String DEFAULT_INTEGER = "$i.";
62
63 private static final String DEFAULT_REAL = "$r.";
64
65 private static final String DEFAULT_ITEM = "$ip.";
66
67 private static final String DEFAULT_FRAME = "$fp.";
68
69 private static final String DEFAULT_ASSOCIATION = "$ap.";
70
71 private static final String EXIT_TEXT = "exitall";
72
73 private static enum Status {
74 Exit, OK, Break, Continue, Return, TrueIf, FalseIf;
75 };
76
77 private static final String BREAK2_TEXT = "exitrepeat";
78
79 private static final String BREAK_TEXT = "break";
80
81 private static final String CONTINUE2_TEXT = "nextrepeat";
82
83 private static final String CONTINUE_TEXT = "continue";
84
85 private static final String RETURN_TEXT = "return";
86
87 private static final String LOOP_TEXT = "repeat";
88
89 private static final String TOKEN_SEPARATOR = " +";
90
91 public static final String RUN_FRAME_ACTION = "runframe";
92
93 public static final String DEBUG_FRAME_ACTION = "debugframe";
94
95 /**
96 * Keeps track of how many simple programs are running. Used to check if
97 * simple should read in keyboard input. Or if the keyboard input should be
98 * handled normally by Expeditee.
99 */
100 private static int _programsRunning = 0;
101
102 /**
103 * This flag is set to true if Simple should hijack keyboard input from
104 * Expeditee
105 */
106 private static boolean _consumeKeyboardInput = false;
107
108 public static void ProgramFinished() {
109 _programsRunning--;
110 _stop = false;
111 }
112
113 private static LinkedList<Character> _KeyStrokes = new LinkedList<Character>();
114
115 private static boolean _stop;
116
117 private static boolean _step;
118
119 private static int _stepPause = -1;
120
121 private static Color _stepColor;
122
123 private static boolean _nextStatement;
124
125 public static void KeyStroke(char c) {
126 _KeyStrokes.add(c);
127 }
128
129 public static boolean isProgramRunning() {
130 return _programsRunning > 0;
131 }
132
133 public static boolean consumeKeyboardInput() {
134 return _consumeKeyboardInput && _programsRunning > 0;
135 }
136
137 public static void NewSimpleTest() {
138 Frame newSimpleTest = FrameIO.CreateFrame(DisplayIO.getCurrentFrame()
139 .getFramesetName(), "Test", null);
140 List<String> actions = new ArrayList<String>();
141 actions.add(RUN_FRAME_ACTION);
142 newSimpleTest.getTitleItem().setActions(actions);
143 FrameUtils.DisplayFrame(newSimpleTest, true);
144 FrameGraphics.DisplayMessage("New test created");
145 }
146
147 public static void NextTest() {
148 Frame next = DisplayIO.getCurrentFrame();
149 do {
150 next = FrameIO.LoadNext(next);
151 } while (next != null && next.isTestFrame());
152 FrameUtils.DisplayFrame(next, true);
153 }
154
155 public static void PreviousTest() {
156 Frame prev = DisplayIO.getCurrentFrame();
157 do {
158 prev = FrameIO.LoadPrevious(prev);
159 } while (prev != null && prev.isTestFrame());
160
161 FrameUtils.DisplayFrame(prev, true);
162 }
163
164 public static void LastTest() {
165 Frame next = FrameIO.LoadLast();
166 Frame lastTest = null;
167 do {
168 // check if its a test frame
169 if (next != null && next.isTestFrame()) {
170 lastTest = next;
171 break;
172 }
173
174 next = FrameIO.LoadPrevious(next);
175 } while (next != null);
176
177 FrameUtils.DisplayFrame(lastTest, true);
178 }
179
180 public static void RunSimpleTests(String frameset) {
181 RunSimpleTests(frameset, false, true);
182 }
183
184 public static void RunSimpleTestsVerbose(String frameset) {
185 RunSimpleTests(frameset, true, true);
186 }
187
188 private String _frameset;
189
190 private boolean _verbose;
191
192 public Simple(String frameset, boolean verbose) {
193 _frameset = frameset;
194 _verbose = verbose;
195 }
196
197 public void run() {
198 runSuite();
199 }
200
201 public boolean runSuite() {
202 int testsPassed = 0;
203 int testsFailed = 0;
204
205 FrameIO.SaveFrame(DisplayIO.getCurrentFrame(), false);
206 FrameGraphics.DisplayMessage("Starting test suite: " + _frameset,
207 Color.CYAN);
208
209 // Get the next number in the inf file for the _frameset
210 int lastFrameNo = FrameIO.getLastNumber(_frameset);
211
212 // Loop through all the valid frames in the _frameset
213 for (int i = 1; i <= lastFrameNo; i++) {
214 String nextFrameName = _frameset + i;
215 Frame nextFrame = FrameIO.LoadFrame(nextFrameName);
216 if (nextFrame == null)
217 continue;
218 Item frameTitle = nextFrame.getTitleItem();
219 if (frameTitle == null)
220 continue;
221 // Run the frames with the RunFrame action on the title
222 Item title = frameTitle.copy();
223 List<String> actions = title.getAction();
224 if (actions == null || title.isAnnotation())
225 continue;
226 if (actions.get(0).toLowerCase().equals("runframe")) {
227 boolean passed = true;
228 String errorMessage = null;
229 try {
230 title.setLink(nextFrameName);
231 // TODO add the ability to run a setup frame
232 // which sets up variables to be used in all
233 // tests
234 AgentStats.reset();
235 _KeyStrokes.clear();
236 _programsRunning++;
237 RunFrameAndReportError(title, new Context());
238 _programsRunning--;
239 // if the throws exception annotation is on the frame then
240 // it passes only if an exception is thrown
241 if (title.getParentOrCurrentFrame().getThrowsException()) {
242 errorMessage = "Expected exception " + title.toString();
243 passed = false;
244 }
245 } catch (Exception e) {
246 _programsRunning--;
247 if (!title.getParentOrCurrentFrame().getThrowsException()) {
248 errorMessage = e.getMessage();
249 passed = false;
250 }
251 }
252 if (passed) {
253 if (_verbose)
254 FrameGraphics.DisplayMessage("Test passed: "
255 + title.toString(), Item.GREEN);
256 testsPassed++;
257 } else {
258 testsFailed++;
259 // Print out the reason for failed tests
260 FrameGraphics.LinkedErrorMessage(errorMessage);
261 if (Simple._stop) {
262 Simple._stop = false;
263 return false;
264 }
265 }
266 }
267 }
268 // The statement below assumes there are no other programs running at
269 // the same time
270 assert (_programsRunning == 0);
271 // Report the number of test passed and failed
272 FrameGraphics.DisplayMessage("Total tests: "
273 + (testsPassed + testsFailed), Color.CYAN);
274 if (testsPassed > 0)
275 FrameGraphics.DisplayMessage("Passed: " + testsPassed, Item.GREEN);
276 if (testsFailed > 0)
277 FrameGraphics.DisplayMessage("Failed: " + testsFailed, Color.RED);
278 // Remove items from the cursor...
279 Frame.FreeItems.clear();
280
281 return testsFailed == 0;
282 }
283
284 /**
285 * Runs a suite of tests stored in a given frameset.
286 *
287 * @param frameset
288 * @param verbose
289 * @param newThread
290 * false if tests should be run on the current frame
291 */
292 public static void RunSimpleTests(String frameset, boolean verbose,
293 boolean newThread) {
294 _stop = false;
295 Simple testSuite = new Simple(frameset, verbose);
296 if (newThread) {
297 Thread t = new Thread(testSuite);
298 t.setPriority(Thread.MIN_PRIORITY);
299 t.start();
300 } else {
301 assert (testSuite.runSuite());
302 }
303
304 }
305
306 private static void RunFrame(Item current, boolean acceptKeyboardInput,
307 boolean step, int pause, Color color) {
308 try {
309 DisplayIO.addToBack(current.getParent());
310
311 _stepColor = color == null ? Color.green : color;
312 _stepColor = new Color(_stepColor.getRed(), _stepColor.getGreen(),
313 _stepColor.getBlue(), 50);
314 _stepPause = pause;
315 _step = step;
316 _consumeKeyboardInput = acceptKeyboardInput;
317 FrameIO.SaveFrame(DisplayIO.getCurrentFrame(), true);
318
319 // an item without a link signals to run the current frame
320 if (current.getLink() == null) {
321 current = current.copy();
322 current.setLink(DisplayIO.getCurrentFrame().getName());
323 }
324
325 _KeyStrokes.clear();
326
327 Thread t = new Thread(current);
328 t.setPriority(Thread.MIN_PRIORITY);
329 t.start();
330 } catch (Exception e) {
331 }
332 }
333
334 public static void RunFrame(Item current, boolean acceptKeyboardInput) {
335 RunFrame(current, acceptKeyboardInput, false, 0, null);
336 }
337
338 public static void RunFrame(Item current) {
339 RunFrame(current, false);
340 }
341
342 /**
343 * At present programs which accept keyboard input can not be debugged.
344 *
345 * @param current
346 * @param pause
347 */
348 public static void DebugFrame(Item current, double pause, Color color) {
349 RunFrame(current, false, true, (int) (pause * 1000 + 0.5), color);
350 }
351
352 /**
353 * At present programs which accept keyboard input can not be debugged.
354 *
355 * @param current
356 * @param pause
357 * the time to pause between
358 */
359 public static void DebugFrame(Item current, double pause) {
360 DebugFrame(current, pause, null);
361 }
362
363 public static void DebugFrame(Item current) {
364 DebugFrame(current, -1.0, null);
365 }
366
367 private static void FlagError(Item item) {
368 FrameUtils.DisplayFrame(item.getParent().getName(), true);
369 item.setSelectedMode(SelectedMode.Normal);
370 item.setSelectionColor(Color.CYAN);
371 FrameIO.SaveFrame(item.getParent());
372 }
373
374 /**
375 * Runs a simple code begining on a frame linked to by the specified item
376 * parametre.
377 *
378 * @param current
379 * the item that is linked to the frame to be run.
380 */
381 public static Status RunFrameAndReportError(Item current, Context context)
382 throws Exception {
383 // the item must link to a frame
384 if (current.getLink() == null) {
385 throw new Exception("Could not run unlinked item: "
386 + current.toString());
387 }
388
389 Frame child = FrameIO.LoadFrame(current.getAbsoluteLink());
390
391 if (_step) {
392 DisplayIO.setCurrentFrame(child);
393 DisplayIO.addToBack(child);
394 }
395
396 AgentStats.FrameExecuted();
397
398 // if the frame could not be loaded
399 if (child == null) {
400 throw new Exception("Could not load item link: "
401 + current.toString());
402 }
403
404 // loop through non-title, non-name, text items
405 List<Text> body = child.getBodyTextItems(true);
406
407 // if no item was found
408 if (body.size() == 0)
409 throw new Exception("No code to be executed: " + current.toString());
410
411 Status lastItemStatus = Status.OK;
412 for (Text item : body) {
413 AgentStats.ItemExecuted();
414 try {
415 Color oldColor = item.getBackgroundColor();
416 if (_step) {
417 if (item.getLink() != null) {
418 pause(item);
419 item.setSelectedMode(Item.SelectedMode.Normal,
420 _stepColor);
421 } else {
422 item.setBackgroundColor(_stepColor);
423 }
424 FrameGraphics.Repaint();
425 }
426 lastItemStatus = RunItem(item, context, lastItemStatus);
427 if (_step) {
428 if (item.getLink() == null) {
429 item.setBackgroundColor(oldColor);
430 pause(item);
431 } else {
432 item.setSelectedMode(Item.SelectedMode.None);
433 }
434 }
435
436 if (lastItemStatus != Status.OK) {
437 if (lastItemStatus != Status.TrueIf
438 && lastItemStatus != Status.FalseIf) {
439 return lastItemStatus;
440 }
441 }
442 } catch (ArrayIndexOutOfBoundsException e) {
443 FlagError(item);
444 throw new Exception("Too few parametres: " + item.toString());
445 } catch (NullPointerException e) {
446 FlagError(item);
447 throw new Exception("Null pointer exception: "
448 + item.toString());
449 } catch (RuntimeException e) {
450 FlagError(item);
451 throw new Exception(e.getMessage() + " " + item.toString());
452 } catch (Exception e) {
453 throw new Exception(e.getMessage());
454 }
455 }
456
457 if (_step) {
458 DisplayIO.setCurrentFrame(current.getParent());
459 DisplayIO.removeFromBack();
460 }
461
462 return Status.OK;
463 }
464
465 /**
466 * @param item
467 * @param oldColor
468 * @throws Exception
469 * @throws InterruptedException
470 */
471 private static void pause(Text item) throws Exception, InterruptedException {
472 if (!_step)
473 return;
474
475 Color oldColor = item.getBackgroundColor();
476 item.setBackgroundColor(_stepColor);
477 item.setSelectedMode(Item.SelectedMode.None);
478
479 // Make sure we are on the frame with this item
480 Frame parent = item.getParentOrCurrentFrame();
481 if (!parent.equals(DisplayIO.getCurrentFrame())) {
482 DisplayIO.setCurrentFrame(parent);
483 }
484
485 FrameGraphics.Repaint();
486
487 int timeRemaining;
488 if (_stepPause < 0)
489 timeRemaining = Integer.MAX_VALUE;
490 else
491 timeRemaining = _stepPause;
492
493 while (timeRemaining > 0 && !_nextStatement) {
494 if (_stop) {
495 item.setBackgroundColor(oldColor);
496 item.setSelectedMode(SelectedMode.Normal, _stepColor);
497 throw new Exception("Program terminated");
498 }
499 Thread.sleep(DefaultAgent.TIMER_RESOLUTION);
500 timeRemaining -= DefaultAgent.TIMER_RESOLUTION;
501 }
502 _nextStatement = false;
503 // Turn off the highlighting
504 item.setBackgroundColor(oldColor);
505 }
506
507 private static void pause(double time) throws Exception {
508 for (int i = 0; i < time * 10; i++) {
509 if (_stop) {
510 throw new Exception("Program terminated");
511 }
512 Thread.yield();
513 Thread.sleep(100);
514 }
515 }
516
517 /**
518 * This method should be modified to parse strings correctly
519 *
520 * @param statement
521 * @return
522 */
523 private static String[] parseStatement(Text code) throws Exception {
524 String statement = code.getText().trim();
525 ArrayList<String> tokens = new ArrayList<String>();
526
527 // Check special annotation tags for programs
528 if (statement.length() > 0 && statement.charAt(0) == '@') {
529 statement = statement.toLowerCase();
530 // Flags the next unit test as being required to throw an exception
531 if (statement.equals("@throwsexception")) {
532 code.getParentOrCurrentFrame().setThrowsException(true);
533 }
534 return null;
535 }
536
537 for (int i = 0; i < statement.length(); i++) {
538 char c = statement.charAt(i);
539 // ignore spaces
540 if (c != ' ') {
541 int startOfToken = i;
542 if (c == '\"') {
543 int endOfToken = statement.length() - 1;
544 // find the end of the string literal
545 while (statement.charAt(endOfToken) != '\"')
546 endOfToken--;
547 if (endOfToken > startOfToken) {
548 tokens.add(statement.substring(startOfToken,
549 endOfToken + 1));
550 } else {
551 throw new RuntimeException("Expected matching \" ");
552 }
553 break;
554 } else if (c == '#' || c == '/') {
555 break;
556 } else {
557 // read in a normal token
558 while (++i < statement.length()
559 && statement.charAt(i) != ' ')
560 ;
561 tokens.add(statement.substring(startOfToken, i)
562 .toLowerCase());
563 }
564 }
565 }
566
567 String[] a = new String[tokens.size()];
568 a = tokens.toArray(a);
569 code.setProcessedCode(a);
570 return a;
571 }
572
573 /**
574 * Runs a SIMPLE procedure statement.
575 *
576 * @param tokens
577 * the parsed Call statement.
578 * @param code
579 * the expeditee item containing the procedure call and the link
580 * to the frame with the procedure code.
581 * @param context
582 * the current context from which the procedure call is being
583 * made.
584 * @throws Exception
585 * when errors occur in running the procedure.
586 */
587 private static Status Call(String[] tokens, Item code, Context context)
588 throws Exception {
589 // Check that the call statement is linked
590 if (code.getLink() == null)
591 throw new Exception("Unlinked call statement: " + code.toString());
592
593 Frame procedure = FrameIO.LoadFrame(code.getAbsoluteLink());
594
595 // Add call to the start of the title if it doesnt exist
596 // This makes the call and signature tokens counts match
597 String procedureTitle = procedure.getTitleItem().getFirstLine();
598 if (!procedureTitle.toLowerCase().startsWith("call "))
599 procedureTitle = "call " + procedureTitle;
600
601 // Check that the calling statement matches the procedure
602 // signature
603 String[] procedureSignature = procedureTitle.split(TOKEN_SEPARATOR);
604
605 // Check for the right amount of parametres
606 if (procedureSignature.length < tokens.length)
607 throw new Exception("Call statement has too many parametres: "
608 + code.toString());
609 else if (procedureSignature.length > tokens.length)
610 throw new Exception("Call statement has too few parametres: "
611 + code.toString());
612 // else if (procedureSignature[1].equals(tokens[1]))
613 // throw new Exception("Call statement and procedure name dont match: "
614 // + code.toString());
615
616 // create the new context for the sub procedure
617 Context newContext = new Context();
618 // Check that the types/prefixes match
619 for (int i = 2; i < tokens.length; i++) {
620 // TODO allow for auto casting of primitives
621 if (tokens[i].substring(1, 2).equals(
622 procedureSignature[i].substring(1, 2))) {
623 // Add the variables to the new context
624 if (Primitives.isPrimitive(tokens[i])) {
625 try {
626 // try and get the value for the variable
627 SPrimitive p = context.getPrimitives().getVariable(
628 tokens[i]);
629 newContext.getPrimitives()
630 .add(procedureSignature[i], p);
631 } catch (Exception e) {
632 // If an exception occurs the variable doesnt
633 // exist in the current context
634 // So the variable must be added to both context
635 context.getPrimitives().add(tokens[i], new SString(""));
636 newContext.getPrimitives().add(procedureSignature[i],
637 new SString(""));
638 }
639 } else if (Pointers.isPointer(tokens[i])) {
640 try {
641 // try and get the value for the variable
642 SPointer p = context.getPointers().getVariable(
643 tokens[i]);
644 newContext.getPointers().add(procedureSignature[i], p);
645 } catch (Exception e) {
646 // If an exception occurs the variable doesnt
647 // exist in the current context
648 // So the variable must be added to both context
649 context.getPointers().setObject(tokens[i], null);
650 newContext.getPointers().setObject(
651 procedureSignature[i], null);
652 }
653 } else
654 throw new Exception("Unrecognised variable type: "
655 + tokens[i] + " in " + code.toString());
656 } else
657 throw new IncorrectTypeException(procedureSignature[i], i);
658 }
659
660 // Follow the link and Run the code for the procedure
661 Status result = RunFrameAndReportError(code, newContext);
662 // If a return statement ends the procedure then we accept this as
663 // normal execution
664 switch (result) {
665 case Return:
666 result = Status.OK;
667 break;
668 case Break:
669 throw new Exception(BREAK_TEXT + " statement without matching "
670 + LOOP_TEXT + " in " + code.toString());
671 case Continue:
672 throw new Exception("");
673 }
674
675 // Now copy the values from the procedure context into the
676 // current context
677 for (int i = 2; i < tokens.length; i++) {
678 try {
679 if (Primitives.isPrimitive(tokens[i])) {
680 // try and get the value for the variable
681 SVariable p = context.getPrimitives()
682 .getVariable(tokens[i]);
683 SVariable newP = newContext.getPrimitives().getVariable(
684 procedureSignature[i]);
685 p.setValue(newP);
686 } else {
687 // try and get the value for the variable
688 SVariable p = context.getPointers().getVariable(tokens[i]);
689 SVariable newP = newContext.getPointers().getVariable(
690 procedureSignature[i]);
691 p.setValue(newP);
692 }
693 } catch (Exception e) {
694 assert (false);
695 }
696 }
697
698 return result;
699 }
700
701 /**
702 * Runs a text item on a frame as a SIMPLE statement. The statement is
703 * parsed and if it is a recognised SIMPLE keyword or procedure the code is
704 * executed.
705 *
706 * @param code
707 * the item containing the code to be executed.
708 * @param context
709 * @return
710 * @throws Exception
711 */
712 private static Status RunItem(Text code, Context context,
713 Status lastItemStatus) throws Exception {
714 if (_stop) {
715 throw new Exception("Program terminated");
716 }
717
718 String[] tokens = code.getProcessedCode();
719
720 if (tokens == null) {
721 tokens = parseStatement(code);
722 }
723
724 // Annotation items are ignored after parsing running options
725 if (tokens == null) {
726 return Status.OK;
727 // Comments without links are ignored
728 } else if (tokens.length == 0) {
729 if (code.getLink() == null)
730 return Status.OK;
731 else
732 return RunFrameAndReportError(code, context);
733 }
734
735 // At present only set statements can have literals so they
736 // are the only statements that we have to worry about string
737 // literals
738 if (tokens[0].equals("call") && tokens.length >= 2) {
739 return Call(tokens, code, context);
740 // Check if the user wants to display a message
741 // Check for set statements
742 } else if (tokens[0].startsWith("set")) {
743 if (tokens[0].equals("set")) {
744 try {
745 // Check if we are setting variable to variable
746 if (tokens[2].startsWith(SVariable.prefix)
747 && tokens.length == 3) {
748 context.getPrimitives().set(tokens[1], tokens[2]);
749 }
750 // Otherwise we are setting a variable with a literal
751 else {
752 // check for strings enclosed in quotes
753 if (tokens[2].startsWith("\"")) {
754 context.getPrimitives().setValue(
755 tokens[1],
756 new SString(tokens[2].substring(1,
757 tokens[2].length() - 1)));
758 // set a literal
759 } else if (tokens.length == 3) {
760 context.getPrimitives().setValue(tokens[1],
761 tokens[2]);
762 }
763 }
764 } catch (Exception e) {
765 throw new RuntimeException(e.getMessage());
766 }
767 } else if (tokens[0].equals("setassociation")) {
768 assertExactParametreCount(tokens, 3);
769
770 Map map = (Map) context.getPointers().getVariable(tokens[1])
771 .getValue();
772 String attribute = context.getPrimitives().getStringValue(
773 tokens[2]);
774 String value = context.getPrimitives()
775 .getStringValue(tokens[3]);
776 map.put(attribute, value);
777 } else if (tokens[0].equals("setframevalue")) {
778 assertMinParametreCount(tokens, 3);
779 assertVariableType(tokens[1], 1, SPointer.framePrefix);
780
781 // Get the attribute to be searched for on the target frame
782 Frame targetFrame = (Frame) context.getPointers().getVariable(
783 tokens[1]).getValue();
784 String targetAttribute = context.getPrimitives()
785 .getStringValue(tokens[2]).toLowerCase()
786 + ":";
787 String value = context.getPrimitives()
788 .getStringValue(tokens[3]);
789 Boolean found = false;
790 Text attributeItem = null;
791 Item valueItem = null;
792 // Begin the search
793 for (Text text : targetFrame.getBodyTextItems(true)) {
794 String s = text.getText().toLowerCase();
795
796 if (s.startsWith(targetAttribute)) {
797 attributeItem = text;
798 AttributeUtils.setSingleValue(attributeItem, value);
799 found = true;
800 break;
801 }
802 }
803 // Keep looking for a matching value nearby if we found an
804 // attribute without the value in the same item
805 if (!found && attributeItem != null) {
806 Point endPoint = attributeItem.getEndParagraphPosition();
807
808 for (Text text : targetFrame.getBodyTextItems(true)) {
809 Point startPoint = text.getPosition();
810 if (Math.abs(startPoint.y - endPoint.y) < 10
811 && Math.abs(startPoint.x - endPoint.x) < 20) {
812 found = true;
813 valueItem = text;
814 text.setText(value);
815 break;
816 }
817 }
818 }
819
820 // Set the values of the output parametres
821 if (tokens.length > 4) {
822 context.getPrimitives().setValue(tokens[4],
823 new SBoolean(found));
824 if (tokens.length > 5) {
825 context.getPointers().setObject(tokens[5],
826 attributeItem);
827 if (tokens.length > 6) {
828 context.getPointers().setObject(tokens[6],
829 valueItem);
830 }
831 }
832 }
833 } else if (tokens[0].startsWith("setitem")) {
834 if (tokens[0].equals("setitemposition")) {
835 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
836 // assertPrimitiveType(tokens[2], 2);
837 // assertPrimitiveType(tokens[3], 3);
838 Item item = (Item) context.getPointers().getVariable(
839 tokens[1]).getValue();
840 item.setPosition(context.getPrimitives().getVariable(
841 tokens[2]).integerValue().intValue(), context
842 .getPrimitives().getVariable(tokens[3])
843 .integerValue().intValue());
844 } else if (tokens[0].equals("setitemthickness")) {
845 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
846 // assertPrimitiveType(tokens[2], 2);
847 Item item = (Item) context.getPointers().getVariable(
848 tokens[1]).getValue();
849 item.setThickness(context.getPrimitives().getVariable(
850 tokens[2]).integerValue().intValue());
851 } else if (tokens[0].equals("setitemwidth")) {
852 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
853 // assertPrimitiveType(tokens[2], 2);
854 Item item = (Item) context.getPointers().getVariable(
855 tokens[1]).getValue();
856 item.setWidth(context.getPrimitives()
857 .getVariable(tokens[2]).integerValue().intValue());
858 } else if (tokens[0].equals("setitemsize")) {
859 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
860 // assertPrimitiveType(tokens[2], 2);
861 Item item = (Item) context.getPointers().getVariable(
862 tokens[1]).getValue();
863 item.setSize(context.getPrimitives().getVariable(tokens[2])
864 .integerValue().intValue());
865 } else if (tokens[0].equals("setitemlink")) {
866 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
867 // assertPrimitiveType(tokens[2], 2);
868 Item item = (Item) context.getPointers().getVariable(
869 tokens[1]).getValue();
870 item.setLink(context.getPrimitives().getVariable(tokens[2])
871 .stringValue());
872 } else if (tokens[0].equals("setitemdata")) {
873 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
874 // assertPrimitiveType(tokens[2], 2);
875 Item item = (Item) context.getPointers().getVariable(
876 tokens[1]).getValue();
877 item.setData(context.getPrimitives().getVariable(tokens[2])
878 .stringValue());
879 } else if (tokens[0].equals("setitemaction")) {
880 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
881 // assertPrimitiveType(tokens[2], 2);
882 Item item = (Item) context.getPointers().getVariable(
883 tokens[1]).getValue();
884 item.setAction(context.getPrimitives().getVariable(
885 tokens[2]).stringValue());
886 } else if (tokens[0].equals("setitemfillcolor")) {
887 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
888 // assertPrimitiveType(tokens[2], 2);
889 Item item = (Item) context.getPointers().getVariable(
890 tokens[1]).getValue();
891 String stringColor = context.getPrimitives().getVariable(
892 tokens[2]).stringValue();
893 item.setBackgroundColor((Color) Conversion.Convert(
894 Color.class, stringColor));
895 } else if (tokens[0].equals("setitemcolor")) {
896 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
897 // assertPrimitiveType(tokens[2], 2);
898 Item item = (Item) context.getPointers().getVariable(
899 tokens[1]).getValue();
900 String stringColor = context.getPrimitives().getVariable(
901 tokens[2]).stringValue();
902 item.setColor((Color) Conversion.Convert(Color.class,
903 stringColor));
904 } else if (tokens[0].equals("setitemtext")) {
905 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
906 // assertPrimitiveType(tokens[2], 2);
907 String newText = context.getPrimitives().getVariable(
908 tokens[2]).stringValue();
909 Text textItem = (Text) context.getPointers().getVariable(
910 tokens[1]).getValue();
911 textItem.setText(newText);
912 } else
913 throw new Exception("Unsupported setItem command: "
914 + code.toString());
915 } else if (tokens[0].equals("setstrchar")) {
916 assertExactParametreCount(tokens, 3);
917 StringBuffer s = new StringBuffer(context.getPrimitives()
918 .getStringValue(tokens[1]));
919 int pos = (int) context.getPrimitives().getIntegerValue(
920 tokens[2]);
921 char newChar = context.getPrimitives().getCharacterValue(
922 tokens[3]);
923 while (pos > s.length()) {
924 s.append(newChar);
925 }
926 s.setCharAt(pos - 1, newChar);
927
928 context.getPrimitives().setValue(tokens[1],
929 new SString(s.toString()));
930 } else if (tokens[0].equals("setcharinitem")) {
931 assertExactParametreCount(tokens, 4);
932 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
933
934 int row = (int) context.getPrimitives().getIntegerValue(
935 tokens[3]) - 1;
936 int col = (int) context.getPrimitives().getIntegerValue(
937 tokens[4]) - 1;
938 char newChar = context.getPrimitives().getCharacterValue(
939 tokens[2]);
940 Text item = (Text) context.getPointers().getVariable(tokens[1])
941 .getValue();
942 List<String> itemText = item.getTextList();
943
944 while (row >= itemText.size()) {
945 StringBuffer sb = new StringBuffer();
946 for (int i = 0; i <= col; i++)
947 sb.append(newChar);
948 itemText.add(sb.toString());
949 }
950 StringBuffer sb = new StringBuffer(itemText.get(row));
951 while (sb.length() <= col)
952 sb.append(newChar);
953 sb.setCharAt(col, newChar);
954
955 // set the modified string
956 itemText.set(row, sb.toString());
957 item.setTextList(itemText);
958 }
959 } else if (tokens[0].startsWith("assert")) {
960 if (tokens[0].equals("asserttrue")) {
961 assertExactParametreCount(tokens, 1);
962 if (!context.getPrimitives().getBooleanValue(tokens[1]))
963 throw new UnitTestFailedException("true", "false");
964 } else if (tokens[0].equals("assertfalse")) {
965 assertExactParametreCount(tokens, 1);
966 if (context.getPrimitives().getBooleanValue(tokens[1]))
967 throw new UnitTestFailedException("false", "true");
968 } else if (tokens[0].equals("assertfail")) {
969 assertExactParametreCount(tokens, 0);
970 throw new UnitTestFailedException("pass", "fail");
971 } else if (tokens[0].equals("assertnull")) {
972 assertExactParametreCount(tokens, 1);
973 Object value = context.getPrimitives().getVariable(tokens[1])
974 .getValue();
975 if (value != null)
976 throw new UnitTestFailedException("null", value.toString());
977 } else if (tokens[0].equals("assertnotnull")) {
978 assertExactParametreCount(tokens, 1);
979 Object value = context.getPrimitives().getVariable(tokens[1])
980 .getValue();
981 if (value == null)
982 throw new UnitTestFailedException("not null", "null");
983 } else if (tokens[0].equals("assertdefined")) {
984 assertExactParametreCount(tokens, 1);
985 if (!context.isDefined(tokens[1]))
986 throw new UnitTestFailedException("defined", "not defined");
987 } else if (tokens[0].equals("assertnotdefined")) {
988 assertExactParametreCount(tokens, 1);
989 if (context.isDefined(tokens[1]))
990 throw new UnitTestFailedException("defined", "not defined");
991 } else if (tokens[0].equals("assertequals")) {
992 assertExactParametreCount(tokens, 2);
993 if (!context.getPrimitives().equalValues(tokens[1], tokens[2]))
994 throw new UnitTestFailedException(context.getPrimitives()
995 .getStringValue(tokens[1]), context.getPrimitives()
996 .getStringValue(tokens[2]));
997 } else if (tokens[0].equals("assertdefined")) {
998 assertExactParametreCount(tokens, 1);
999 if (!context.isDefined(tokens[1])) {
1000 throw new UnitTestFailedException(tokens[1] + " exists",
1001 "not defined");
1002 }
1003 }
1004 } else if (tokens[0].startsWith("goto")) {
1005 String frameNameVar = DEFAULT_STRING;
1006 if (tokens.length > 1) {
1007 assertExactParametreCount(tokens, 1);
1008 frameNameVar = tokens[1];
1009 }
1010 String frameName = context.getPrimitives().getStringValue(
1011 frameNameVar);
1012 NavigationActions.Goto(frameName);
1013 } else if (tokens[0].startsWith("get")) {
1014 if (tokens[0].startsWith("getframe")) {
1015 if (tokens[0].equals("getframevalue")) {
1016 assertMinParametreCount(tokens, 3);
1017 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1018
1019 // Get the attribute to be searched for on the target frame
1020 Frame targetFrame = (Frame) context.getPointers()
1021 .getVariable(tokens[1]).getValue();
1022 String targetAttribute = context.getPrimitives()
1023 .getStringValue(tokens[2]).toLowerCase()
1024 + ":";
1025 Boolean found = false;
1026 String value = "";
1027 Text attributeItem = null;
1028 Item valueItem = null;
1029 // Begin the search
1030 for (Text text : targetFrame.getBodyTextItems(true)) {
1031 String s = text.getText().toLowerCase();
1032 if (s.startsWith(targetAttribute)) {
1033 attributeItem = text;
1034 value = AttributeUtils.getValue(s);
1035 if (value.length() > 0) {
1036 found = true;
1037 }
1038 break;
1039 }
1040 }
1041 // Keep looking for a matching value nearby if we found an
1042 // attribute without the value in the same item
1043 if (!found && attributeItem != null) {
1044 Point endPoint = attributeItem
1045 .getEndParagraphPosition();
1046
1047 for (Text text : targetFrame.getBodyTextItems(true)) {
1048 Point startPoint = text.getPosition();
1049 if (Math.abs(startPoint.y - endPoint.y) < 10
1050 && Math.abs(startPoint.x - endPoint.x) < 20) {
1051 found = true;
1052 valueItem = text;
1053 value = text.getText();
1054 break;
1055 }
1056 }
1057 }
1058
1059 // Set the values of the output parametres
1060 context.getPrimitives().setValue(tokens[3],
1061 new SString(value));
1062 if (tokens.length > 4) {
1063 context.getPrimitives().setValue(tokens[4],
1064 new SBoolean(found));
1065 if (tokens.length > 5) {
1066 context.getPointers().setObject(tokens[5],
1067 attributeItem);
1068 if (tokens.length > 6) {
1069 context.getPointers().setObject(tokens[6],
1070 valueItem);
1071 }
1072 }
1073 }
1074 } else if (tokens[0].startsWith("getframename")) {
1075 String frameNameVar = DEFAULT_STRING;
1076 String frameVar = DEFAULT_FRAME;
1077
1078 if (tokens.length > 1) {
1079 assertExactParametreCount(tokens, 2);
1080 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1081 frameNameVar = tokens[2];
1082 frameVar = tokens[1];
1083 }
1084 Frame frame = (Frame) context.getPointers().getVariable(
1085 frameVar).getValue();
1086 context.getPrimitives().setValue(frameNameVar,
1087 frame.getName());
1088 } else if (tokens[0].startsWith("getframefilepath")) {
1089 assertExactParametreCount(tokens, 2);
1090 String frameName = context.getPrimitives().getStringValue(
1091 tokens[1]);
1092 String path = FrameIO.LoadFrame(frameName).path;
1093 String filePath = FrameIO.getFrameFullPathName(path,
1094 frameName);
1095 context.getPrimitives().setValue(tokens[2], filePath);
1096 } else if (tokens[0].equals("getframelog")) {
1097 assertExactParametreCount(tokens, 1);
1098 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1099
1100 String log = SessionStats.getFrameEventList();
1101 Text t;
1102
1103 t = (Text) context.getPointers().getVariable(tokens[1])
1104 .getValue();
1105 t.setText(log);
1106 }
1107 } else if (tokens[0].equals("getassociation")) {
1108 assertMinParametreCount(tokens, 3);
1109 Map map = (Map) context.getPointers().getVariable(tokens[1])
1110 .getValue();
1111 String attribute = context.getPrimitives().getStringValue(
1112 tokens[2]);
1113 String newValue = map.get(attribute).toString();
1114 context.getPrimitives().setValue(tokens[3], newValue);
1115 } else if (tokens[0].startsWith("getcurrent")) {
1116 if (tokens[0].equals("getcurrentframe")) {
1117 assertMinParametreCount(tokens, 1);
1118 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1119
1120 Frame currentFrame = DisplayIO.getCurrentFrame();
1121 context.getPointers().setObject(tokens[1], currentFrame);
1122
1123 // check if the user is also after the frameName
1124 if (tokens.length > 2) {
1125 context.getPrimitives().setValue(tokens[2],
1126 new SString(currentFrame.getName()));
1127 }
1128 }
1129 } else if (tokens[0].startsWith("getitem")) {
1130 if (tokens[0].equals("getitemposition")) {
1131 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1132 // assertPrimitiveType(tokens[2], 2);
1133 // assertPrimitiveType(tokens[3], 3);
1134 Point pos = ((Item) context.getPointers().getVariable(
1135 tokens[1]).getValue()).getPosition();
1136 Integer x = pos.x;
1137 Integer y = pos.y;
1138 context.getPrimitives()
1139 .setValue(tokens[2], new SInteger(x));
1140 context.getPrimitives()
1141 .setValue(tokens[3], new SInteger(y));
1142 } else if (tokens[0].equals("getitemthickness")) {
1143 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1144 // assertPrimitiveType(tokens[2], 2);
1145 Float thickness = ((Item) context.getPointers()
1146 .getVariable(tokens[1]).getValue()).getThickness();
1147 context.getPrimitives().setValue(tokens[2],
1148 new SReal(thickness));
1149 } else if (tokens[0].equals("getitemwidth")) {
1150 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1151 // assertPrimitiveType(tokens[2], 2);
1152 Integer width = ((Item) context.getPointers().getVariable(
1153 tokens[1]).getValue()).getWidth();
1154 context.getPrimitives().setValue(tokens[2],
1155 new SInteger(width));
1156 } else if (tokens[0].equals("getitemsize")) {
1157 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1158 // assertPrimitiveType(tokens[2], 2);
1159 Integer size = ((Item) context.getPointers().getVariable(
1160 tokens[1]).getValue()).getSize();
1161 context.getPrimitives().setValue(tokens[2],
1162 new SInteger(size));
1163 } else if (tokens[0].equals("getitemlink")) {
1164 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1165 // assertPrimitiveType(tokens[2], 2);
1166 String link = ((Item) context.getPointers().getVariable(
1167 tokens[1]).getValue()).getLink();
1168 context.getPrimitives().setValue(tokens[2],
1169 new SString(link));
1170 } else if (tokens[0].equals("getitemdata")) {
1171 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1172 Collection<String> dataList = ((Item) context.getPointers()
1173 .getVariable(tokens[1]).getValue()).getData();
1174 String data = "";
1175 if (dataList.size() > 0)
1176 data = dataList.iterator().next();
1177 context.getPrimitives().setValue(tokens[2],
1178 new SString(data));
1179 } else if (tokens[0].equals("getitemaction")) {
1180 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1181 Collection<String> dataList = ((Item) context.getPointers()
1182 .getVariable(tokens[1]).getValue()).getAction();
1183 String action = "";
1184 if (dataList.size() > 0)
1185 action = dataList.iterator().next();
1186 context.getPrimitives().setValue(tokens[2],
1187 new SString(action));
1188 } else if (tokens[0].equals("getitemfillcolor")) {
1189 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1190 // assertPrimitiveType(tokens[2], 2);
1191 Color itemColor = ((Item) context.getPointers()
1192 .getVariable(tokens[1]).getValue())
1193 .getPaintBackgroundColor();
1194 String color = itemColor.getRed() + " "
1195 + itemColor.getGreen() + " " + itemColor.getBlue();
1196 context.getPrimitives().setValue(tokens[2],
1197 new SString(color));
1198 } else if (tokens[0].equals("getitemcolor")) {
1199 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1200 // assertPrimitiveType(tokens[2], 2);
1201 Color itemColor = ((Item) context.getPointers()
1202 .getVariable(tokens[1]).getValue()).getPaintColor();
1203 String color = itemColor.getRed() + " "
1204 + itemColor.getGreen() + " " + itemColor.getBlue();
1205 context.getPrimitives().setValue(tokens[2],
1206 new SString(color));
1207 } else if (tokens[0].equals("getitemtext")) {
1208 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1209 Item item = ((Item) context.getPointers().getVariable(
1210 tokens[1]).getValue());
1211 context.getPrimitives().setValue(
1212 tokens[2],
1213 new SString((item instanceof Text) ? ((Text) item)
1214 .getText() : ""));
1215 } else
1216 throw new Exception("Unsupported getItem command: "
1217 + code.toString());
1218 } else if (tokens[0].equals("getstrchar")) {
1219 assertExactParametreCount(tokens, 3);
1220 String s = context.getPrimitives().getStringValue(tokens[1]);
1221 int pos = (int) context.getPrimitives().getIntegerValue(
1222 tokens[2]);
1223
1224 context.getPrimitives().setValue(tokens[3],
1225 new SCharacter(s.charAt(pos - 1)));
1226 } else if (tokens[0].equals("getstrlength")) {
1227 assertExactParametreCount(tokens, 2);
1228 String s = context.getPrimitives().getStringValue(tokens[1]);
1229
1230 context.getPrimitives().setValue(tokens[2],
1231 new SInteger(s.length()));
1232 } else if (tokens[0].equals("getelapsedtime")) {
1233 assertExactParametreCount(tokens, 1);
1234 context.getPrimitives().setValue(tokens[1],
1235 new SInteger(AgentStats.getMilliSecondsElapsed()));
1236 } else if (tokens[0].equals("getlastnumberinframeset")) {
1237 String framesetNameVar = DEFAULT_STRING;
1238 String countVar = DEFAULT_INTEGER;
1239 if (tokens.length > 1) {
1240 assertMinParametreCount(tokens, 2);
1241 framesetNameVar = tokens[1];
1242 countVar = tokens[2];
1243 }
1244 String frameset = context.getPrimitives().getStringValue(
1245 framesetNameVar);
1246 long count = FrameIO.getLastNumber(frameset);
1247 context.getPrimitives().setValue(countVar, new SInteger(count));
1248 } else if (tokens[0].equals("getlistofframesets")) {
1249 String stringVar = DEFAULT_ITEM;
1250 if (tokens.length > 1) {
1251 assertMinParametreCount(tokens, 1);
1252 stringVar = tokens[1];
1253 }
1254 context.getPrimitives().setValue(stringVar,
1255 FrameIO.getFramesetList());
1256 } else if (tokens[0].equals("getsessionstats")) {
1257 assertExactParametreCount(tokens, 1);
1258 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1259
1260 String stats = SessionStats.getCurrentStats();
1261 Text t = (Text) context.getPointers().getVariable(tokens[1])
1262 .getValue();
1263 t.setText(stats);
1264 } else if (tokens[0].equals("getrandominteger")) {
1265 assertExactParametreCount(tokens, 3);
1266 int lowerBound = (int) context.getPrimitives().getIntegerValue(
1267 tokens[1]);
1268 int upperBound = (int) context.getPrimitives().getIntegerValue(
1269 tokens[2]);
1270 Random random = new Random();
1271 long result = Math.abs(random.nextInt())
1272 % (upperBound - lowerBound) + lowerBound;
1273 context.getPrimitives().setValue(tokens[3],
1274 new SInteger(result));
1275 } else if (tokens[0].equals("getrandomreal")) {
1276 assertExactParametreCount(tokens, 3);
1277 double lowerBound = context.getPrimitives().getDoubleValue(
1278 tokens[1]);
1279 double upperBound = context.getPrimitives().getDoubleValue(
1280 tokens[2]);
1281 Random random = new Random();
1282 double result = random.nextDouble() * (upperBound - lowerBound)
1283 + lowerBound;
1284 context.getPrimitives().setValue(tokens[3], new SReal(result));
1285 } else if (tokens[0].equals("getrandomtextitem")) {
1286 assertExactParametreCount(tokens, 2);
1287 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1288 assertVariableType(tokens[2], 2, SPointer.itemPrefix);
1289 List<Text> items = ((Frame) context.getPointers().getVariable(
1290 tokens[1]).getValue()).getBodyTextItems(false);
1291 Random random = new Random();
1292 int itemIndex = random.nextInt(items.size());
1293 context.getPointers()
1294 .setObject(tokens[2], items.get(itemIndex));
1295 }
1296 } else if (tokens[0].equals("or")) {
1297 for (int i = 1; i < tokens.length - 1; i++) {
1298 if (Primitives.isPrimitive(tokens[i])) {
1299 if (context.getPrimitives().getBooleanValue(tokens[i])) {
1300 context.getPrimitives().setValue(
1301 tokens[tokens.length - 1], new SBoolean(true));
1302 return Status.OK;
1303 }
1304 }
1305 }
1306 context.getPrimitives().setValue(tokens[tokens.length - 1],
1307 new SBoolean(false));
1308 } else if (tokens[0].equals("and")) {
1309 for (int i = 1; i < tokens.length - 1; i++) {
1310 if (Primitives.isPrimitive(tokens[i])) {
1311 if (!context.getPrimitives().getBooleanValue(tokens[i])) {
1312 context.getPrimitives().setValue(
1313 tokens[tokens.length - 1], new SBoolean(false));
1314 return Status.OK;
1315 }
1316 }
1317 }
1318 context.getPrimitives().setValue(tokens[tokens.length - 1],
1319 new SBoolean(true));
1320 } else if (tokens[0].equals("messagelnitem")
1321 || tokens[0].equals("messagelineitem")) {
1322 String itemVar = DEFAULT_ITEM;
1323
1324 if (tokens.length > 1) {
1325 assertExactParametreCount(tokens, 1);
1326 itemVar = tokens[1];
1327 assertVariableType(itemVar, 1, SPointer.itemPrefix);
1328 }
1329 Item message = (Item) context.getPointers().getVariable(itemVar)
1330 .getValue();
1331 try {
1332 FrameGraphics.DisplayMessage(((Text) message).copy());
1333 } catch (NullPointerException e) {
1334 FrameGraphics.DisplayMessage("null");
1335 } catch (ClassCastException e) {
1336 // Just ignore not text items!
1337 FrameGraphics.DisplayMessage(message.toString());
1338 } catch (Exception e) {
1339 // Just ignore other errors
1340 }
1341 } else if (tokens[0].equals("messageln")
1342 || tokens[0].equals("messageline")
1343 || tokens[0].equals("messagelnnospaces")
1344 || tokens[0].equals("messagelinenospaces")
1345 || tokens[0].equals("errorln") || tokens[0].equals("errorline")) {
1346 String message = getMessage(tokens, context, code.toString(),
1347 tokens[0].endsWith("nospaces") ? "" : " ", 1);
1348
1349 if (tokens[0].equals("errorln") || tokens[0].equals("errorline"))
1350 FrameGraphics.ErrorMessage(message);
1351 else
1352 FrameGraphics.DisplayMessageAlways(message);
1353 } else if (tokens[0].equals("typeatrate")) {
1354 assertMinParametreCount(tokens, 1);
1355 double delay = context.getPrimitives().getDoubleValue(tokens[1]);
1356 String s = getMessage(tokens, context, code.toString(), " ", 2);
1357 for (int i = 0; i < s.length(); i++) {
1358 FrameKeyboardActions.processChar(s.charAt(i), false);
1359 Thread.sleep((int) (delay * 1000));
1360 }
1361 } else if (tokens[0].equals("type") || tokens[0].equals("typenospaces")) {
1362
1363 String s = getMessage(tokens, context, code.toString(), tokens[0]
1364 .equals("type") ? " " : "", 1);
1365 for (int i = 0; i < s.length(); i++) {
1366 FrameKeyboardActions.processChar(s.charAt(i), false);
1367 Thread.sleep(25);
1368 }
1369 } else if (tokens[0].equals("runstring")) {
1370 String codeText = getMessage(tokens, context, code.toString(), " ",
1371 1);
1372 Text dynamicCode = new Text(1, codeText);
1373 RunItem(dynamicCode, context, Status.OK);
1374 } else if (tokens[0].equals("runoscommand")) {
1375 String command = getMessage(tokens, context, code.toString(), " ",
1376 1);
1377 Runtime.getRuntime().exec(command);
1378 } else if (tokens[0].equals("executeoscommand")) {
1379 String command = getMessage(tokens, context, code.toString(), " ",
1380 1);
1381 try {
1382 Process p = Runtime.getRuntime().exec(command);
1383 FrameGraphics.DisplayMessage(command, Color.darkGray);
1384
1385 BufferedReader stdInput = new BufferedReader(
1386 new InputStreamReader(p.getInputStream()));
1387 BufferedReader stdError = new BufferedReader(
1388 new InputStreamReader(p.getErrorStream()));
1389 String message = "";
1390 while ((message = stdInput.readLine()) != null) {
1391 FrameGraphics.DisplayMessage(message);
1392 }
1393 while ((message = stdError.readLine()) != null) {
1394 FrameGraphics.ErrorMessage(message);
1395 }
1396 } catch (Exception e) {
1397 throw new RuntimeException(e.getMessage());
1398 }
1399 } else if (tokens[0].startsWith("else")) {
1400 // if the if statement was false then run the else statement
1401 if (lastItemStatus == Status.FalseIf) {
1402 // check if it is a one line if statment
1403 if (tokens.length > 1) {
1404 // put together the one line statement
1405 StringBuilder statement = new StringBuilder();
1406 for (int i = 1; i < tokens.length; i++)
1407 statement.append(tokens[i]).append(' ');
1408 // create a copy of the code item to run
1409 Text copiedCode = code.copy();
1410 copiedCode.setText(statement.toString());
1411 return RunItem(copiedCode, context, Status.OK);
1412 } else {
1413 return RunFrameAndReportError(code, context);
1414 }
1415 } else if (lastItemStatus == Status.TrueIf) {
1416 return Status.OK;
1417 }
1418 throw new RuntimeException("Else without matching If statement");
1419 } else if (tokens[0].startsWith("if")) {
1420 Boolean result = null;
1421 int parametres = 1;
1422 String variable = DEFAULT_ITEM;
1423 String ifStatement = tokens[0];
1424 // Set the default variable
1425 if (tokens.length == 1) {
1426 if (ifStatement.equals("if") || ifStatement.equals("ifnot"))
1427 variable = DEFAULT_STRING;
1428 else if (ifStatement.equals("ifzero")
1429 || ifStatement.equals("ifnotzero"))
1430 variable = DEFAULT_INTEGER;
1431 } else {
1432 variable = tokens[1];
1433 }
1434
1435 if (ifStatement.equals("if")) {
1436 result = context.getPrimitives().getBooleanValue(variable);
1437 } else if (ifStatement.equals("ifnot")) {
1438 result = !context.getPrimitives().getBooleanValue(variable);
1439 } else if (ifStatement.equals("ifdefined")) {
1440 result = context.isDefined(tokens[1]);
1441 } else if (ifStatement.equals("ifnotdef")) {
1442 result = !context.isDefined(tokens[1]);
1443 } else if (ifStatement.equals("ifzero")) {
1444 result = context.getPrimitives().getIntegerValue(variable) == 0;
1445 } else if (ifStatement.equals("ifnotzero")) {
1446 result = context.getPrimitives().getIntegerValue(variable) != 0;
1447 } else if (tokens[0].equals("ifeq")) {
1448 result = context.equalValues(tokens[1], tokens[2]);
1449 parametres = 2;
1450 } else if (tokens[0].equals("ifeqnocase")) {
1451 result = context.getPrimitives().equalValuesNoCase(tokens[1],
1452 tokens[2]);
1453 parametres = 2;
1454 } else if (tokens[0].equals("ifnoteqnocase")) {
1455 result = !context.getPrimitives().equalValuesNoCase(tokens[1],
1456 tokens[2]);
1457 parametres = 2;
1458 } else if (tokens[0].equals("ifnoteq")) {
1459 result = !context.equalValues(tokens[1], tokens[2]);
1460 parametres = 2;
1461 } else if (tokens[0].equals("ifless")) {
1462 result = context.getPrimitives().compareValues(tokens[1],
1463 tokens[2]) < 0;
1464 parametres = 2;
1465 } else if (tokens[0].equals("ifgtr")) {
1466 result = context.getPrimitives().compareValues(tokens[1],
1467 tokens[2]) > 0;
1468 parametres = 2;
1469 } else if (tokens[0].equals("ifgeq")) {
1470 result = context.getPrimitives().compareValues(tokens[1],
1471 tokens[2]) >= 0;
1472 parametres = 2;
1473 } else if (tokens[0].equals("ifleq")) {
1474 result = context.getPrimitives().compareValues(tokens[1],
1475 tokens[2]) <= 0;
1476 parametres = 2;
1477 } else if (tokens[0].equals("ifexistingframe")) {
1478 result = FrameIO.DoesFrameExist(context.getPrimitives()
1479 .getStringValue(tokens[1]));
1480 } else if (tokens[0].equals("ifexistingframeset")) {
1481 String framesetName = context.getPrimitives().getStringValue(
1482 tokens[1]);
1483 result = FrameIO.DoesFramesetExist(framesetName);
1484 } else {
1485 // assertVariableType(variable, 1, SPointer.itemPrefix);
1486 if (ifStatement.equals("ifannotation")) {
1487 result = ((Item) context.getPointers()
1488 .getVariable(variable).getValue()).isAnnotation();
1489 } else if (ifStatement.equals("iflinked")) {
1490 result = ((Item) context.getPointers()
1491 .getVariable(variable).getValue()).getLink() != null;
1492 } else if (ifStatement.equals("ifactioned")) {
1493 result = ((Item) context.getPointers()
1494 .getVariable(variable).getValue()).getAction() != null;
1495 } else if (ifStatement.equals("ifnotactioned")) {
1496 result = ((Item) context.getPointers()
1497 .getVariable(variable).getValue()).getAction() == null;
1498 } else if (ifStatement.equals("ifbodytext")) {
1499 Item i = (Item) context.getPointers().getVariable(variable)
1500 .getValue();
1501 result = i instanceof Text && !i.isFrameName()
1502 && !i.isFrameTitle();
1503 } else if (ifStatement.equals("ifnotannotation")) {
1504 result = !((Item) context.getPointers().getVariable(
1505 variable).getValue()).isAnnotation();
1506 } else if (ifStatement.equals("ifnotlinked")) {
1507 result = ((Item) context.getPointers()
1508 .getVariable(variable).getValue()).getLink() == null;
1509 } else if (ifStatement.equals("ifnotbodytext")) {
1510 Item i = (Item) context.getPointers().getVariable(variable)
1511 .getValue();
1512 result = !(i instanceof Text) || i.isFrameName()
1513 || i.isFrameTitle();
1514 }
1515 }
1516
1517 if (result == null)
1518 throw new RuntimeException("Invalid If statement");
1519 // Now check if we need to run the code
1520 else if (result) {
1521 Status status;
1522 // check if it is a one line if statment
1523 if (tokens.length > parametres + 1) {
1524 // put together the one line statement
1525 StringBuilder statement = new StringBuilder();
1526 for (int i = parametres + 1; i < tokens.length; i++)
1527 statement.append(tokens[i]).append(' ');
1528 // create a copy of the code item to run
1529 Text copiedCode = code.copy();
1530 copiedCode.setText(statement.toString());
1531 status = RunItem(copiedCode, context, Status.OK);
1532 } else {
1533 status = RunFrameAndReportError(code, context);
1534 }
1535 if (status == Status.OK) {
1536 return Status.TrueIf;
1537 } else {
1538 return status;
1539 }
1540 }
1541 return Status.FalseIf;
1542 } // Look for variable length methods
1543 else if (tokens[0].equals("attachitemtocursor")) {
1544 String itemVar = DEFAULT_ITEM;
1545
1546 if (tokens.length > 1) {
1547 assertExactParametreCount(tokens, 1);
1548 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1549 itemVar = tokens[1];
1550 }
1551 Item item = (Item) context.getPointers().getVariable(itemVar)
1552 .getValue();
1553 item
1554 .setPosition(FrameMouseActions.MouseX,
1555 FrameMouseActions.MouseY);
1556 FrameMouseActions.pickup(item);
1557 } else if (tokens[0].equals("attachstrtocursor")) {
1558 String stringVar = DEFAULT_STRING;
1559
1560 if (tokens.length > 1) {
1561 assertExactParametreCount(tokens, 1);
1562 stringVar = tokens[1];
1563 }
1564 String s = context.getPrimitives().getStringValue(stringVar);
1565 Frame frame = DisplayIO.getCurrentFrame();
1566 Item item = frame.createNewText(s);
1567 item
1568 .setPosition(FrameMouseActions.MouseX,
1569 FrameMouseActions.MouseY);
1570 FrameMouseActions.pickup(item);
1571 } else if (tokens[0].equals("additemtoframe")) {
1572 String itemVar = DEFAULT_ITEM;
1573 String frameVar = DEFAULT_FRAME;
1574
1575 if (tokens.length > 1) {
1576 assertExactParametreCount(tokens, 2);
1577 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1578 assertVariableType(tokens[2], 2, SPointer.itemPrefix);
1579 itemVar = tokens[2];
1580 frameVar = tokens[1];
1581 }
1582 Frame frame = (Frame) context.getPointers().getVariable(frameVar)
1583 .getValue();
1584 Item item = (Item) context.getPointers().getVariable(itemVar)
1585 .getValue();
1586 frame.addItem(item);
1587 } else if (tokens[0].equals("connectdots")) {
1588 assertMinParametreCount(tokens, 2);
1589 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1590 assertVariableType(tokens[2], 2, SPointer.itemPrefix);
1591 Item dot1 = null;
1592 Item dot2 = null;
1593 try {
1594 dot1 = (Item) context.getPointers().getVariable(tokens[1])
1595 .getValue();
1596 } catch (Exception e) {
1597 throw new IncorrectTypeException("Dot", 1);
1598 }
1599 try {
1600 dot2 = (Item) context.getPointers().getVariable(tokens[2])
1601 .getValue();
1602 } catch (Exception e) {
1603 throw new IncorrectTypeException("Dot", 2);
1604 }
1605 Frame frame = dot1.getParent();
1606 frame.addItem(new Line(dot1, dot2, frame.getNextItemID()));
1607 } else if (tokens[0].equals("createitem")
1608 || tokens[0].equals("createtext")) {
1609 assertMinParametreCount(tokens, 4);
1610 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1611 assertVariableType(tokens[4], 4, SPointer.itemPrefix);
1612 Frame frame = (Frame) context.getPointers().getVariable(tokens[1])
1613 .getValue();
1614 Item newItem;
1615 int x = (int) context.getPrimitives().getIntegerValue(tokens[2]);
1616 int y = (int) context.getPrimitives().getIntegerValue(tokens[3]);
1617 // check for the option text and action for the new item
1618 if (tokens.length > 5) {
1619 String newText = context.getPrimitives().getStringValue(
1620 tokens[5]);
1621 String newAction = null;
1622 if (tokens.length > 6) {
1623 newAction = context.getPrimitives().getStringValue(
1624 tokens[6]);
1625 }
1626 newItem = frame.addText(x, y, newText, newAction);
1627 } else {
1628 if (tokens[0].equals("createtext")) {
1629 newItem = frame.createNewText();
1630 newItem.setPosition(x, y);
1631 } else {
1632 // create a point if the optional params are not provided
1633 newItem = frame.addDot(x, y);
1634 }
1635 }
1636 context.getPointers().setObject(tokens[4], newItem);
1637 } else if (tokens[0].equals("deleteitem")) {
1638 assertMinParametreCount(tokens, 1);
1639 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1640 Item item = (Item) context.getPointers().getVariable(tokens[1])
1641 .getValue();
1642 item.delete();
1643 } else if (tokens[0].equals("deleteframe")) {
1644 assertMinParametreCount(tokens, 1);
1645 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1646 Frame frame = (Frame) context.getPointers().getVariable(tokens[1])
1647 .getValue();
1648 boolean success = FrameIO.DeleteFrame(frame);
1649
1650 if (tokens.length > 2) {
1651 context.getPrimitives().setValue(tokens[2],
1652 new SBoolean(success));
1653 }
1654 } else if (tokens[0].equals("deleteframeset")) {
1655 assertMinParametreCount(tokens, 1);
1656 String framesetName = context.getPrimitives().getStringValue(
1657 tokens[1]);
1658 boolean success = FrameIO.DeleteFrameset(framesetName);
1659
1660 if (tokens.length > 2) {
1661 context.getPrimitives().setValue(tokens[2],
1662 new SBoolean(success));
1663 }
1664 } else if (tokens[0].equals("copyitem")) {
1665 assertMinParametreCount(tokens, 2);
1666 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1667 assertVariableType(tokens[2], 2, SPointer.itemPrefix);
1668 Item item = (Item) context.getPointers().getVariable(tokens[1])
1669 .getValue();
1670 Item copy = item.copy();
1671 context.getPointers().setObject(tokens[2], copy);
1672 } else if (tokens[0].equals("copyframeset")) {
1673 assertMinParametreCount(tokens, 2);
1674 String framesetToCopy = context.getPrimitives().getStringValue(
1675 tokens[1]);
1676 String copiedFrameset = context.getPrimitives().getStringValue(
1677 tokens[2]);
1678 boolean success = FrameIO.CopyFrameset(framesetToCopy,
1679 copiedFrameset);
1680
1681 if (tokens.length > 3) {
1682 context.getPrimitives().setValue(tokens[3],
1683 new SBoolean(success));
1684 }
1685 } else if (tokens[0].equals("copyframe")) {
1686 assertMinParametreCount(tokens, 2);
1687 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1688 assertVariableType(tokens[2], 2, SPointer.framePrefix);
1689 Frame frameToCopy = (Frame) context.getPointers().getVariable(
1690 tokens[1]).getValue();
1691 FrameIO.SuspendCache();
1692 Frame freshCopy = FrameIO.LoadFrame(frameToCopy.getName());
1693 // Change the frameset if one was provided
1694 if (tokens.length > 3) {
1695 String destinationFrameset = context.getPrimitives()
1696 .getStringValue(tokens[3]);
1697 freshCopy.setFrameset(destinationFrameset);
1698 }// Otherwise add it to the end of this frameset
1699 freshCopy.setFrameNumber(FrameIO.getLastNumber(freshCopy
1700 .getFramesetName()) + 1);
1701 context.getPointers().setObject(tokens[2], freshCopy);
1702 String fileContents = FrameIO.ForceSaveFrame(freshCopy);
1703 boolean success = fileContents != null;
1704 FrameIO.ResumeCache();
1705 if (tokens.length > 4) {
1706 context.getPrimitives().setValue(tokens[4],
1707 new SBoolean(success));
1708 }
1709 } else if (tokens[0].equals("createframe")) {
1710
1711 String framesetName = DEFAULT_STRING;
1712 String frameVar = DEFAULT_FRAME;
1713
1714 if (tokens.length > 1) {
1715 assertMinParametreCount(tokens, 2);
1716 assertVariableType(tokens[2], 2, SPointer.framePrefix);
1717 framesetName = tokens[1];
1718 frameVar = tokens[2];
1719 }
1720
1721 if (tokens.length > 3) {
1722 context.createFrame(framesetName, frameVar, tokens[3]);
1723 } else
1724 context.createFrame(framesetName, frameVar, null);
1725 } else if (tokens[0].equals("closeframe")) {
1726 String frameVar = DEFAULT_FRAME;
1727
1728 if (tokens.length > 1) {
1729 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1730 frameVar = tokens[1];
1731 }
1732
1733 if (tokens.length > 2) {
1734 // assertPrimitiveType(tokens[3], 3);
1735 context.closeFrame(frameVar, tokens[3]);
1736 } else
1737 context.closeFrame(frameVar, null);
1738 } else if (tokens[0].equals("readframe")
1739 || tokens[0].equals("openframe")) {
1740
1741 String frameName = DEFAULT_STRING;
1742 String frameVar = DEFAULT_FRAME;
1743
1744 if (tokens.length > 1) {
1745 assertMinParametreCount(tokens, 2);
1746 assertVariableType(tokens[2], 2, SPointer.framePrefix);
1747 frameName = tokens[1];
1748 frameVar = tokens[2];
1749 // assertPrimitiveType(frameName, 1);
1750 }
1751
1752 if (tokens.length > 3) {
1753 // assertPrimitiveType(tokens[3], 3);
1754 context.readFrame(frameName, frameVar, tokens[3]);
1755 } else
1756 context.readFrame(frameName, frameVar, null);
1757 } else if (tokens[0].equals("readkbdcond")) {
1758
1759 String nextCharVarName = DEFAULT_CHAR;
1760 String wasCharVarName = DEFAULT_BOOLEAN;
1761
1762 if (tokens.length > 1) {
1763 assertMinParametreCount(tokens, 2);
1764 assertVariableType(tokens[2], 2, SPointer.framePrefix);
1765 nextCharVarName = tokens[1];
1766 wasCharVarName = tokens[2];
1767 }
1768
1769 Character nextChar = _KeyStrokes.poll();
1770 boolean hasChar = nextChar != null;
1771 context.getPrimitives().setValue(wasCharVarName,
1772 new SBoolean(hasChar));
1773 if (hasChar)
1774 context.getPrimitives().setValue(nextCharVarName,
1775 new SCharacter(nextChar));
1776 } else if (tokens[0].equals("createassociation")) {
1777
1778 String associationVar = DEFAULT_ASSOCIATION;
1779
1780 if (tokens.length > 0) {
1781 assertVariableType(tokens[1], 2, SPointer.associationPrefix);
1782 associationVar = tokens[1];
1783 }
1784 Map<String, String> newMap = new HashMap<String, String>();
1785 context.getPointers().setObject(associationVar, newMap);
1786 } else if (tokens[0].equals("deleteassociation")) {
1787
1788 String associationVar = DEFAULT_ASSOCIATION;
1789
1790 if (tokens.length > 0) {
1791 assertVariableType(tokens[1], 2, SPointer.associationPrefix);
1792 associationVar = tokens[1];
1793 }
1794 context.getPointers().delete(associationVar);
1795 } else if (tokens[0].equals("openreadfile")) {
1796 assertVariableType(tokens[1], 1, SString.prefix);
1797 assertVariableType(tokens[2], 2, SPointer.filePrefix);
1798
1799 if (tokens.length > 3) {
1800 assertVariableType(tokens[3], 3, SBoolean.prefix);
1801 context.openReadFile(tokens[1], tokens[2], tokens[3]);
1802 } else
1803 context.openReadFile(tokens[1], tokens[2]);
1804 } else if (tokens[0].equals("readlinefile")
1805 || tokens[0].equals("readlnfile")) {
1806 assertVariableType(tokens[1], 1, SPointer.filePrefix);
1807
1808 if (tokens.length > 3) {
1809 assertVariableType(tokens[3], 3, SBoolean.prefix);
1810 context.readLineFile(tokens[1], tokens[2], tokens[3]);
1811 } else
1812 context.readLineFile(tokens[1], tokens[2]);
1813 } else if (tokens[0].equals("readitemfile")) {
1814 assertVariableType(tokens[1], 1, SPointer.filePrefix);
1815 assertVariableType(tokens[2], 1, SPointer.itemPrefix);
1816
1817 if (tokens.length > 3) {
1818 assertVariableType(tokens[3], 3, SBoolean.prefix);
1819 context.readItemFile(tokens[1], tokens[2], tokens[3]);
1820 } else
1821 context.readItemFile(tokens[1], tokens[2]);
1822 } else if (tokens[0].equals("openwritefile")) {
1823 assertVariableType(tokens[1], 1, SString.prefix);
1824 assertVariableType(tokens[2], 2, SPointer.filePrefix);
1825
1826 if (tokens.length > 3) {
1827 assertVariableType(tokens[3], 3, SBoolean.prefix);
1828 context.openWriteFile(tokens[1], tokens[2], tokens[3]);
1829 } else
1830 context.openWriteFile(tokens[1], tokens[2]);
1831 } else if (tokens[0].equals("writefile")
1832 || tokens[0].equals("writelinefile")
1833 || tokens[0].equals("writelnfile")) {
1834 assertVariableType(tokens[1], 1, SPointer.filePrefix);
1835
1836 StringBuilder textToWrite = new StringBuilder();
1837 if (tokens.length == 1) {
1838 textToWrite.append(context.getPrimitives().getVariable(
1839 DEFAULT_STRING).stringValue()
1840 + " ");
1841 } else {
1842 for (int i = 2; i < tokens.length; i++) {
1843 if (Primitives.isPrimitive(tokens[i])) {
1844 textToWrite.append(context.getPrimitives().getVariable(
1845 tokens[i]).stringValue());
1846 } else
1847 throw new Exception("Illegal parametre: " + tokens[i]
1848 + " in " + code.toString());
1849 }
1850 }
1851
1852 if (!tokens[0].equals("writefile"))
1853 textToWrite.append('\n');
1854 context.writeFile(tokens[1], textToWrite.toString());
1855 } else if (tokens[0].equals("displayframeset")) {
1856 assertMinParametreCount(tokens, 1);
1857 String framesetName = context.getPrimitives().getStringValue(
1858 tokens[1]);
1859 int lastFrameNo = FrameIO.getLastNumber(framesetName);
1860 int firstFrameNo = 0;
1861 double pause = 0.0;
1862 // get the first and last frames to display if they were proided
1863 if (tokens.length > 2) {
1864 firstFrameNo = (int) context.getPrimitives().getIntegerValue(
1865 tokens[2]);
1866 if (tokens.length > 3) {
1867 lastFrameNo = (int) context.getPrimitives()
1868 .getIntegerValue(tokens[3]);
1869 if (tokens.length > 4) {
1870 pause = context.getPrimitives().getDoubleValue(
1871 tokens[4]);
1872 }
1873 }
1874 }
1875 Runtime runtime = Runtime.getRuntime();
1876 // Display the frames
1877 for (int i = firstFrameNo; i <= lastFrameNo; i++) {
1878 Frame frame = FrameIO.LoadFrame(framesetName + i);
1879 if (frame != null) {
1880 double thisFramesPause = pause;
1881 // check for change in delay for this frame only
1882 Item pauseItem = ItemUtils.FindTag(frame.getItems(),
1883 "@DisplayFramePause:");
1884 if (pauseItem != null) {
1885 try {
1886 // attempt to read in the delay value
1887 thisFramesPause = Double.parseDouble(ItemUtils
1888 .StripTag(
1889 ((Text) pauseItem).getFirstLine(),
1890 "@DisplayFramePause"));
1891 } catch (NumberFormatException nfe) {
1892 }
1893 }
1894 DisplayIO.setCurrentFrame(frame);
1895 pause(thisFramesPause);
1896
1897 long freeMemory = runtime.freeMemory();
1898 if (freeMemory < DisplayTree.GARBAGE_COLLECTION_THRESHOLD) {
1899 runtime.gc();
1900 FrameGraphics
1901 .DisplayMessage("Force Garbage Collection!");
1902 }
1903 }
1904 }
1905 } else if (tokens[0].equals("createframeset")) {
1906 String framesetName = DEFAULT_STRING;
1907 String successVar = null;
1908 if (tokens.length > 1) {
1909 framesetName = tokens[1];
1910 if (tokens.length > 2)
1911 successVar = tokens[2];
1912 }
1913 context.createFrameset(framesetName, successVar);
1914 } else if (tokens[0].equals("writetree")) {
1915 assertMinParametreCount(tokens, 3);
1916 assertVariableType(tokens[1], 1, SPointer.framePrefix);
1917 Frame source = (Frame) context.getPointers().getVariable(tokens[1])
1918 .getValue();
1919 String format = context.getPrimitives().getStringValue(tokens[2]);
1920 String fileName = context.getPrimitives().getStringValue(tokens[3]);
1921 WriteTree wt = new WriteTree(format, fileName);
1922 if (wt.initialise(source)) {
1923 wt.setStartFrame(source);
1924 wt.run();
1925 }
1926 } else if (tokens[0].equals("concatstr")) {
1927 assertMinParametreCount(tokens, 3);
1928 String resultVar = tokens[tokens.length - 1];
1929
1930 StringBuilder sb = new StringBuilder();
1931 // loop through all the strings concatenating them
1932 for (int i = 1; i < tokens.length - 1; i++) {
1933 // assertPrimitiveType(tokens[i], i);
1934 sb.append(context.getPrimitives().getStringValue(tokens[i]));
1935 }
1936 context.getPrimitives().setValue(resultVar,
1937 new SString(sb.toString()));
1938 } else if (tokens[0].equals("convstrlower")) {
1939 assertExactParametreCount(tokens, 1);
1940 // assertPrimitiveType(tokens[1], 1);
1941 context.getPrimitives().setValue(
1942 tokens[1],
1943 new SString(context.getPrimitives().getStringValue(
1944 tokens[1]).toLowerCase()));
1945 } else if (tokens[0].equals("convstrupper")) {
1946 assertExactParametreCount(tokens, 1);
1947 // assertPrimitiveType(tokens[1], 1);
1948 context.getPrimitives().setValue(
1949 tokens[1],
1950 new SString(context.getPrimitives().getStringValue(
1951 tokens[1]).toUpperCase()));
1952 } else if (tokens[0].equals("countcharsinstr")) {
1953 assertExactParametreCount(tokens, 3);
1954 String s = context.getPrimitives().getStringValue(tokens[1]);
1955 String pattern = context.getPrimitives().getStringValue(tokens[2]);
1956 int count = countCharsInString(s, pattern);
1957 context.getPrimitives().setValue(tokens[3], new SInteger(count));
1958 } else if (tokens[0].equals("countcharsinitem")) {
1959 assertExactParametreCount(tokens, 3);
1960 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
1961 Item item = (Item) context.getPointers().getVariable(tokens[1])
1962 .getValue();
1963 String pattern = context.getPrimitives().getStringValue(tokens[2]);
1964 int count = 0;
1965 if (item instanceof Text)
1966 count = countCharsInString(((Text) item).getText(), pattern);
1967 context.getPrimitives().setValue(tokens[3], new SInteger(count));
1968 } else if (tokens[0].equals("parseframename")) {
1969 assertExactParametreCount(tokens, 4);
1970 String frameName = context.getPrimitives()
1971 .getStringValue(tokens[1]);
1972 String frameSet = "";
1973 int frameNo = -1;
1974 boolean success = true;
1975 try {
1976 frameSet = Conversion.getFrameset(frameName, false);
1977 frameNo = Conversion.getFrameNumber(frameName);
1978 } catch (Exception e) {
1979 success = false;
1980 }
1981 // assertPrimitiveType(tokens[2], 2);
1982 context.getPrimitives().setValue(tokens[2], new SBoolean(success));
1983
1984 // assertPrimitiveType(tokens[3], 3);
1985 context.getPrimitives().setValue(tokens[3], new SString(frameSet));
1986
1987 // assertPrimitiveType(tokens[4], 4);
1988 context.getPrimitives().setValue(tokens[4], new SInteger(frameNo));
1989 } else if (tokens[0].equals("parsestr")) {
1990 assertMinParametreCount(tokens, 2);
1991 // assertPrimitiveType(tokens[1], 1);
1992 // assertPrimitiveType(tokens[2], 2);
1993
1994 String s = context.getPrimitives().getStringValue(tokens[1]);
1995
1996 String separator = context.getPrimitives()
1997 .getStringValue(tokens[2]);
1998
1999 String[] split = s.split(separator, tokens.length - 4);
2000
2001 if (tokens.length > 3) {
2002 // assertPrimitiveType(tokens[3], 3);
2003 int count = split.length;
2004 // if the string is not blank and its got a remainder then
2005 // decrease the count by 1 to account for the remainder
2006 if (split.length != 0 && split.length > tokens.length - 5)
2007 count--;
2008
2009 context.getPrimitives()
2010 .setValue(tokens[3], new SInteger(count));
2011
2012 if (tokens.length > 4) {
2013 // Set the remainder string
2014 // assertPrimitiveType(tokens[4], 4);
2015 if (split.length < tokens.length - 4)
2016 context.getPrimitives().setValue(tokens[4],
2017 new SString());
2018 else
2019 context.getPrimitives().setValue(tokens[4],
2020 new SString(split[split.length - 1]));
2021
2022 // Set the strings for each of the vars
2023 if (tokens.length > 5) {
2024 for (int i = 5; i < tokens.length; i++) {
2025 // assertPrimitiveType(tokens[i], i);
2026 if (split.length < i - 4)
2027 context.getPrimitives().setValue(tokens[i],
2028 new SString());
2029 else
2030 context.getPrimitives().setValue(tokens[i],
2031 new SString(split[i - 5]));
2032 }
2033 }
2034 }
2035 }
2036 } else if (tokens[0].equals("stripstr")) {
2037 assertExactParametreCount(tokens, 2);
2038 String s = context.getPrimitives().getStringValue(tokens[1]);
2039 String charsToStrip = context.getPrimitives().getStringValue(
2040 tokens[2]);
2041 for (int i = 0; i < charsToStrip.length(); i++)
2042 s = s.replaceAll(charsToStrip.substring(i, i + 1), "");
2043 context.getPrimitives().setValue(tokens[1], new SString(s));
2044 } else if (tokens[0].equals("subststr")) {
2045 assertExactParametreCount(tokens, 3);
2046 String oldString = context.getPrimitives()
2047 .getStringValue(tokens[2]);
2048 String newString = context.getPrimitives()
2049 .getStringValue(tokens[3]);
2050 String result = context.getPrimitives().getStringValue(tokens[1]);
2051 result = result.replaceAll(oldString, newString);
2052 context.getPrimitives().setValue(tokens[1], new SString(result));
2053 } else if (tokens[0].equals("substr")) {
2054 assertExactParametreCount(tokens, 4);
2055 int startPos = (int) context.getPrimitives().getIntegerValue(
2056 tokens[2]) - 1;
2057 int length = (int) context.getPrimitives().getIntegerValue(
2058 tokens[3]);
2059 String s = context.getPrimitives().getStringValue(tokens[1]);
2060 String result;
2061 if (startPos + length < s.length())
2062 result = s.substring(startPos, startPos + length);
2063 else
2064 result = s.substring(startPos);
2065 context.getPrimitives().setValue(tokens[4], new SString(result));
2066 } else if (tokens[0].equals("pause")) {
2067 String lengthVar = DEFAULT_REAL;
2068
2069 if (tokens.length > 1) {
2070 assertExactParametreCount(tokens, 1);
2071 lengthVar = tokens[1];
2072 }
2073
2074 pause(context.getPrimitives().getDoubleValue(lengthVar));
2075 } else if (tokens[0].equals("glidecursorto")) {
2076 assertMinParametreCount(tokens, 2);
2077 int finalX = (int) context.getPrimitives().getIntegerValue(
2078 tokens[1]);
2079 int finalY = (int) context.getPrimitives().getIntegerValue(
2080 tokens[2]);
2081 int milliseconds = 1000;
2082 if (tokens.length > 3)
2083 milliseconds = (int) (context.getPrimitives().getDoubleValue(
2084 tokens[3]) * 1000);
2085
2086 int initialX = DisplayIO.getMouseX();
2087 int initialY = DisplayIO.getMouseY();
2088
2089 final int timeInterval = 40;
2090
2091 int deltaX = (int) (finalX - initialX);
2092 int deltaY = (int) (finalY - initialY);
2093
2094 int intervals = milliseconds / timeInterval;
2095 for (double i = 0; i < intervals; i++) {
2096 int newX = initialX + (int) (deltaX * i / intervals);
2097 int newY = initialY + (int) (deltaY * i / intervals);
2098 Thread.yield();
2099 Thread.sleep(timeInterval);
2100 DisplayIO.setCursorPosition(newX, newY);
2101 // DisplayIO.repaint();
2102 }
2103 // Thread.yield();
2104 Thread.sleep(milliseconds % timeInterval);
2105 DisplayIO.setCursorPosition(finalX, finalY);
2106 } else if (tokens[0].equals("glideitemto")) {
2107 assertMinParametreCount(tokens, 3);
2108 assertVariableType(tokens[1], 1, SPointer.itemPrefix);
2109 Item item = (Item) context.getPointers().getVariable(tokens[1])
2110 .getValue();
2111 int finalX = (int) context.getPrimitives().getIntegerValue(
2112 tokens[2]);
2113 int finalY = (int) context.getPrimitives().getIntegerValue(
2114 tokens[3]);
2115
2116 // DisplayIO.setCursorPosition(item.getX(), item.getY());
2117 // FrameMouseActions.pickup(item);
2118
2119 int milliseconds = 1000;
2120 if (tokens.length > 4)
2121 milliseconds = (int) (context.getPrimitives().getDoubleValue(
2122 tokens[4]) * 1000);
2123
2124 int initialX = item.getX();
2125 int initialY = item.getY();
2126 // int initialX = DisplayIO.getMouseX();
2127 // int initialY = DisplayIO.getMouseY();
2128
2129 final int timeInterval = 40;
2130
2131 int deltaX = (int) (finalX - initialX);
2132 int deltaY = (int) (finalY - initialY);
2133
2134 int intervals = milliseconds / timeInterval;
2135 for (double i = 0; i < intervals; i++) {
2136 int newX = initialX + (int) (deltaX * i / intervals);
2137 int newY = initialY + (int) (deltaY * i / intervals);
2138 Thread.yield();
2139 Thread.sleep(timeInterval);
2140 // DisplayIO.setCursorPosition(newX, newY);
2141
2142 item.setPosition(newX, newY);
2143 FrameGraphics.Repaint();
2144 }
2145 // Thread.yield();
2146 Thread.sleep(milliseconds % timeInterval);
2147 item.setPosition(finalX, finalY);
2148 // DisplayIO.setCursorPosition(finalX, finalY);
2149 FrameMouseActions.anchor(item);
2150 Frame.FreeItems.clear();
2151 FrameGraphics.Repaint();
2152 // FrameMouseActions.updateCursor();
2153 }
2154 // Now look for fixed parametre statements
2155 else if (tokens[0].equals(EXIT_TEXT)) {
2156 return Status.Exit;
2157 } else if (tokens[0].equals(LOOP_TEXT)) {
2158 Status status = Status.OK;
2159 // Keep looping until break or exit occurs
2160 while (status == Status.OK || status == Status.Continue) {
2161 status = RunFrameAndReportError(code, context);
2162 pause(code);
2163 }
2164 if (status == Status.Continue || status == Status.Break)
2165 status = Status.OK;
2166 return status;
2167 } else if (tokens[0].equals(CONTINUE_TEXT)
2168 || tokens[0].equals(CONTINUE2_TEXT)) {
2169 return Status.Continue;
2170 } else if (tokens[0].equals(BREAK_TEXT)
2171 || tokens[0].equals(BREAK2_TEXT)) {
2172 return Status.Break;
2173 } else if (tokens[0].equals(RETURN_TEXT)) {
2174 return Status.Return;
2175 } else if (tokens[0].equals("pressleftbutton")) {
2176 assertExactParametreCount(tokens, 0);
2177 DisplayIO.pressMouse(InputEvent.BUTTON1_MASK);
2178 } else if (tokens[0].equals("pressmiddlebutton")) {
2179 assertExactParametreCount(tokens, 0);
2180 DisplayIO.pressMouse(InputEvent.BUTTON2_MASK);
2181 } else if (tokens[0].equals("pressrightbutton")) {
2182 assertExactParametreCount(tokens, 0);
2183 DisplayIO.pressMouse(InputEvent.BUTTON3_MASK);
2184 } else if (tokens[0].equals("releaseleftbutton")) {
2185 assertExactParametreCount(tokens, 0);
2186 DisplayIO.releaseMouse(InputEvent.BUTTON1_MASK);
2187 } else if (tokens[0].equals("releasemiddlebutton")) {
2188 assertExactParametreCount(tokens, 0);
2189 DisplayIO.releaseMouse(InputEvent.BUTTON2_MASK);
2190 } else if (tokens[0].equals("releaserightbutton")) {
2191 assertExactParametreCount(tokens, 0);
2192 DisplayIO.releaseMouse(InputEvent.BUTTON3_MASK);
2193 } else if (tokens[0].equals("clickleftbutton")) {
2194 assertExactParametreCount(tokens, 0);
2195 DisplayIO.clickMouse(InputEvent.BUTTON1_MASK);
2196 } else if (tokens[0].equals("clickmiddlebutton")) {
2197 assertExactParametreCount(tokens, 0);
2198 DisplayIO.clickMouse(InputEvent.BUTTON2_MASK);
2199 } else if (tokens[0].equals("clickrightbutton")) {
2200 assertExactParametreCount(tokens, 0);
2201 DisplayIO.clickMouse(InputEvent.BUTTON3_MASK);
2202 } else if (tokens[0].equals("repaint")) {
2203 assertExactParametreCount(tokens, 0);
2204 FrameGraphics.Repaint();
2205 } else if (tokens[0].equals("add")) {
2206 assertMaxParametreCount(tokens, 3);
2207 switch (tokens.length) {
2208 case 1:
2209 context.getPrimitives().add(DEFAULT_INTEGER);
2210 break;
2211 case 2:
2212 context.getPrimitives().add(tokens[1]);
2213 break;
2214 case 3:
2215 context.getPrimitives().add(tokens[2], tokens[1]);
2216 break;
2217 case 4:
2218 context.getPrimitives().add(tokens[1], tokens[2], tokens[3]);
2219 break;
2220 default:
2221 assert (false);
2222 }
2223 } else if (tokens[0].equals("subtract")) {
2224 assertMaxParametreCount(tokens, 3);
2225 switch (tokens.length) {
2226 case 1:
2227 context.getPrimitives().subtract(DEFAULT_INTEGER);
2228 break;
2229 case 2:
2230 context.getPrimitives().subtract(tokens[1]);
2231 break;
2232 case 3:
2233 context.getPrimitives().subtract(tokens[2], tokens[1]);
2234 break;
2235 case 4:
2236 context.getPrimitives().subtract(tokens[1], tokens[2],
2237 tokens[3]);
2238 break;
2239 default:
2240 assert (false);
2241 }
2242 } else if (tokens[0].equals("multiply")) {
2243 assertMinParametreCount(tokens, 2);
2244 assertMaxParametreCount(tokens, 3);
2245 switch (tokens.length) {
2246 case 3:
2247 context.getPrimitives().multiply(tokens[2], tokens[1]);
2248 break;
2249 case 4:
2250 context.getPrimitives().multiply(tokens[1], tokens[2],
2251 tokens[3]);
2252 break;
2253 default:
2254 assert (false);
2255 }
2256 } else if (tokens[0].equals("divide")) {
2257 assertMinParametreCount(tokens, 2);
2258 assertMaxParametreCount(tokens, 3);
2259 switch (tokens.length) {
2260 case 3:
2261 context.getPrimitives().divide(tokens[2], tokens[1]);
2262 break;
2263 case 4:
2264 context.getPrimitives().divide(tokens[1], tokens[2], tokens[3]);
2265 break;
2266 default:
2267 assert (false);
2268 }
2269 } else if (tokens[0].equals("modulo")) {
2270 assertExactParametreCount(tokens, 3);
2271 context.getPrimitives().modulo(tokens[1], tokens[2], tokens[3]);
2272 } else if (tokens[0].equals("power")) {
2273 assertExactParametreCount(tokens, 3);
2274 context.getPrimitives().power(tokens[1], tokens[2], tokens[3]);
2275 } else if (tokens[0].equals("not")) {
2276 assertExactParametreCount(tokens, 2);
2277 context.getPrimitives().not(tokens[1], tokens[2]);
2278 } else if (tokens[0].equals("exp")) {
2279 assertExactParametreCount(tokens, 2);
2280 context.getPrimitives().exp(tokens[1], tokens[2]);
2281 } else if (tokens[0].equals("log")) {
2282 assertExactParametreCount(tokens, 2);
2283 context.getPrimitives().log(tokens[2], tokens[2]);
2284 } else if (tokens[0].equals("log10")) {
2285 assertExactParametreCount(tokens, 2);
2286 context.getPrimitives().log10(tokens[1], tokens[2]);
2287 } else if (tokens[0].equals("sqrt")) {
2288 assertExactParametreCount(tokens, 2);
2289 context.getPrimitives().sqrt(tokens[1], tokens[2]);
2290 } else if (tokens[0].equals("closewritefile")) {
2291 assertVariableType(tokens[1], 1, SPointer.filePrefix);
2292 context.closeWriteFile(tokens[1]);
2293 } else if (tokens[0].equals("closereadfile")) {
2294 assertVariableType(tokens[1], 1, SPointer.filePrefix);
2295 context.closeReadFile(tokens[1]);
2296 } else if (tokens[0].startsWith("foreach")) {
2297 if (tokens[0].equals("foreachassociation")) {
2298 assertExactParametreCount(tokens, 3);
2299 assertVariableType(tokens[1], 1, SPointer.associationPrefix);
2300 Map<String, String> map = (Map<String, String>) context
2301 .getPointers().getVariable(tokens[1]).getValue();
2302 for (Map.Entry entry : map.entrySet()) {
2303 String value = entry.getValue().toString();
2304 String key = entry.getKey().toString();
2305 context.getPrimitives().setValue(tokens[2], key);
2306 context.getPrimitives().setValue(tokens[3], value);
2307 Status status = RunFrameAndReportError(code, context);
2308 pause(code);
2309 // check if we need to exit this loop because of
2310 // statements in the code that was run
2311 if (status == Status.Exit || status == Status.Return)
2312 return status;
2313 else if (status == Status.Break)
2314 break;
2315 }
2316 } else {
2317 Class itemType = Object.class;
2318 String type = tokens[0].substring("foreach".length());
2319 // Check the type of foreach loop
2320 // and set the item type to iterate over
2321 if (type.equals("dot")) {
2322 itemType = Dot.class;
2323 } else if (type.equals("text")) {
2324 itemType = Text.class;
2325 } else if (type.equals("line")) {
2326 itemType = Line.class;
2327 } else if (type.equals("item") || type.equals("")) {
2328 itemType = Object.class;
2329 } else {
2330 throw new RuntimeException("Invalid ForEach loop type");
2331 }
2332
2333 assertVariableType(tokens[2], 2, SPointer.itemPrefix);
2334 assertVariableType(tokens[1], 1, SPointer.framePrefix);
2335 Frame currFrame = (Frame) context.getPointers().getVariable(
2336 tokens[1]).getValue();
2337 // Create the ip variable
2338 Item frameTitle = currFrame.getTitleItem();
2339
2340 for (Item i : currFrame.getItems()) {
2341 if (i == frameTitle)
2342 continue;
2343 if (!(itemType.isInstance(i)))
2344 continue;
2345
2346 context.getPointers().setObject(tokens[2], i);
2347 Status status = RunFrameAndReportError(code, context);
2348 pause(code);
2349 // check if we need to exit this loop because of
2350 // statements in the code that was run
2351 if (status == Status.Exit || status == Status.Return)
2352 return status;
2353 else if (status == Status.Break)
2354 return Status.OK;
2355 }
2356 }
2357 } else if (tokens[0].equals("movecursorto")) {
2358 assertExactParametreCount(tokens, 2);
2359 int x = (int) context.getPrimitives().getIntegerValue(tokens[1]);
2360 int y = (int) context.getPrimitives().getIntegerValue(tokens[2]);
2361 DisplayIO.setCursorPosition(x, y);
2362 } else {
2363 throw new RuntimeException("Unknown statement");
2364 }
2365 return Status.OK;
2366 }
2367
2368 public static int countCharsInString(String s, String pattern) {
2369 String newString = s;
2370 int count = -1;
2371 do {
2372 count++;
2373 s = newString;
2374 newString = s.replaceFirst(pattern, "");
2375 } while (s.length() != newString.length());
2376
2377 return count;
2378 }
2379
2380 public static void assertVariableType(String varName, int no, String type)
2381 throws Exception {
2382 if (!varName.startsWith(type))
2383 throw new IncorrectTypeException(type, no);
2384 }
2385
2386 /*
2387 * public static void assertPrimitiveType(String varName, int no) throws
2388 * Exception { if (!Primitives.isPrimitive(varName)) throw new
2389 * IncorrectTypeException("primitive", no); }
2390 */
2391
2392 public static void assertMinParametreCount(String[] tokens,
2393 int minParametres) throws Exception {
2394 if (tokens.length - 1 < minParametres)
2395 throw new BelowMinParametreCountException(minParametres);
2396 }
2397
2398 public static void assertExactParametreCount(String[] tokens,
2399 int parametreCount) throws Exception {
2400 if (tokens.length - 1 != parametreCount)
2401 throw new IncorrectParametreCountException(parametreCount);
2402 }
2403
2404 public static void assertMaxParametreCount(String[] tokens,
2405 int parametreCount) throws Exception {
2406 if (tokens.length - 1 > parametreCount)
2407 throw new AboveMaxParametreCountException(parametreCount);
2408 }
2409
2410 private static String getMessage(String[] tokens, Context context,
2411 String code, String separator, int firstStringIndex)
2412 throws Exception {
2413 StringBuilder message = new StringBuilder();
2414 if (tokens.length == firstStringIndex) {
2415 message.append(context.getPrimitives().getVariable(DEFAULT_STRING)
2416 .stringValue());
2417 } else {
2418 for (int i = firstStringIndex; i < tokens.length; i++) {
2419 if (Primitives.isPrimitive(tokens[i])) {
2420 message.append(context.getPrimitives().getVariable(
2421 tokens[i]).stringValue()
2422 + separator);
2423 } else
2424 throw new Exception("Illegal parametre: [" + tokens[i]
2425 + "] in line " + code);
2426 }
2427 }
2428 return message.toString();
2429 }
2430
2431 public static void stop() {
2432 _stop = true;
2433 }
2434
2435 public static void nextStatement() {
2436 _nextStatement = true;
2437 }
2438
2439 public static void ProgramStarted() {
2440 _programsRunning++;
2441 AgentStats.reset();
2442 FrameGraphics.DisplayMessage("Running SimpleProgram...", Color.BLUE);
2443 }
2444}
Note: See TracBrowser for help on using the repository browser.