moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kturtle / src / executer.cpp
blob92c81e2081d0521986dc6a29142f3e30139906e3
1 /*
2 Copyright (C) 2003 by Walter Schreppers
3 Copyright (C) 2004 by Cies Breijs
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of version 2 of the GNU General Public
7 License as published by the Free Software Foundation.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // This file is originally written by Walter Scheppers, but allmost
20 // every aspect of it is slightly changed by Cies Breijs.
23 #include <unistd.h> // for usleep();
25 #include <qtimer.h>
27 #include <kapplication.h>
28 #include <kdebug.h>
29 #include <klocale.h>
31 #include "executer.h"
33 // this function is used in executer and canvas:
34 #define ROUND2INT(x) ( (x) >= 0 ? (int)( (x) + .5 ) : (int)( (x) - .5 ) )
37 Executer::Executer(TreeNode* tree)
39 this->tree = tree;
40 functionTable.clear();
41 bBreak = false;
42 bReturn = false;
45 Executer::~Executer()
47 emit Finished();
50 bool Executer::run()
52 bBreak = false;
53 bReturn = false;
54 bPause = false;
55 bAbort = false;
56 symtable main;
57 symbolTables.push(main); // new symbol table for main block
59 TreeNode::const_iterator i;
60 for (i = tree->begin(); i != tree->end(); ++i)
62 if (bAbort) return false;
63 kapp->processEvents();
64 execute(*i);
66 symbolTables.pop(); //free up stack
68 return true;
71 void Executer::slowDown(TreeNode* node)
73 switch (runSpeed)
75 case 1: // slow
76 startWaiting(0);
77 break;
79 case 2: // slower
80 startWaiting(250);
81 break;
83 case 3: // slowest
84 startWaiting(900);
85 break;
87 default:
88 kdDebug(0)<<"Executer: Wrong execution speed given"<<endl;
89 break;
91 Token tok = node->getToken();
92 emit setSelection(tok.start.row, tok.start.col, tok.end.row, tok.end.col);
95 void Executer::slotChangeSpeed(int speed)
97 runSpeed = speed;
100 void Executer::pause()
102 // The next line is within all loops of the Executer
103 // if (bAbort) return;
104 // mostly before
105 // kapp->processEvents();
106 // this to keep the GUI of KTurtle accessible while executing the logo code
107 // so the Abort button can be clicked, and will function
108 bPause = true;
111 void Executer::abort()
113 // The next line is within all loops of the Executer
114 // if(bAbort) return;
115 // mostly before
116 // kapp->processEvents();
117 // this to keep the GUI of KTurtle accessible while executing the logo code
118 // so the Abort button can be clicked, and will function
119 bAbort = true;
123 void Executer::execute(TreeNode* node)
125 switch ( node->getType() )
127 case blockNode : execBlock(node); break;
128 case forNode : execFor(node); break;
129 case forEachNode : execForEach(node); break;
130 case whileNode : execWhile(node); break;
131 case ifNode : execIf(node); break;
132 case assignNode : execAssign(node); break;
133 case expressionNode : execExpression(/*node*/); break;
134 case idNode : execId(node); break;
135 case constantNode : execConstant(/*node*/); break; // does nothing value allready set
137 case addNode : execAdd(node); break;
138 case mulNode : execMul(node); break;
139 case divNode : execDiv(node); break;
140 case subNode : execSub(node); break;
141 case minusNode : execMinus(node); break;
143 case nodeGE : execGE(node); break;
144 case nodeGT : execGT(node); break;
145 case nodeLE : execLE(node); break;
146 case nodeLT : execLT(node); break;
147 case nodeNE : execNE(node); break;
148 case nodeEQ : execEQ(node); break;
150 case andNode : execAnd(node); break;
151 case orNode : execOr(node); break;
152 case notNode : execNot(node); break;
154 case functionNode : createFunction(node); break;
155 case functionCallNode : execFunction(node); break;
156 case funcReturnNode : execRetFunction(node); break;
157 case returnNode : execReturn(node); break;
158 case breakNode : execBreak(/*node*/); break;
160 case runNode : execRun(node); break;
162 case ClearNode : execClear(node); break;
163 case GoNode : execGo(node); break;
164 case GoXNode : execGoX(node); break;
165 case GoYNode : execGoY(node); break;
166 case ForwardNode : execForward(node); break;
167 case BackwardNode : execBackward(node); break;
168 case DirectionNode : execDirection(node); break;
169 case TurnLeftNode : execTurnLeft(node); break;
170 case TurnRightNode : execTurnRight(node); break;
171 case CenterNode : execCenter(node); break;
172 case SetPenWidthNode : execSetPenWidth(node); break;
173 case PenUpNode : execPenUp(node); break;
174 case PenDownNode : execPenDown(node); break;
175 case SetFgColorNode : execSetFgColor(node); break;
176 case SetBgColorNode : execSetBgColor(node); break;
177 case ResizeCanvasNode : execResizeCanvas(node); break;
178 case SpriteShowNode : execSpriteShow(node); break;
179 case SpriteHideNode : execSpriteHide(node); break;
180 case SpritePressNode : execSpritePress(node); break;
181 case SpriteChangeNode : execSpriteChange(node); break;
183 case MessageNode : execMessage(node); break;
184 case InputWindowNode : execInputWindow(node); break;
185 case printNode : execPrint(node); break;
186 case FontTypeNode : execFontType(node); break;
187 case FontSizeNode : execFontSize(node); break;
188 case RepeatNode : execRepeat(node); break;
189 case RandomNode : execRandom(node); break;
190 case WaitNode : execWait(node); break;
191 case WrapOnNode : execWrapOn(node); break;
192 case WrapOffNode : execWrapOff(node); break;
193 case ResetNode : execReset(node); break;
195 case EndOfFileNode : break; // just do nothing is enough
197 case Unknown : // dont break but fallthrough to default
199 default:
200 kdDebug(0)<<"Found unsupported node named '"<<node->getLook()<<"' in the tree @ ("<<node->getRow()<<", "<<node->getCol()<<")"<<endl;
201 break;
206 void Executer::createFunction(TreeNode* node)
208 QString funcname = node->getLook();
209 functionTable[funcname] = node; //store for later use
213 //execute a function
214 void Executer::execFunction(TreeNode* node)
216 QString funcname = node->getLook();
218 // locate function node
219 functable::iterator p = functionTable.find(funcname);
220 if ( p == functionTable.end() )
222 emit ErrorMsg(node->getToken(), i18n("Call to undefined function: %1.").arg(funcname), 5010);
223 return;
226 TreeNode* funcnode = p->second;
227 TreeNode* funcIds = funcnode->firstChild();
228 TreeNode* callparams = node->firstChild();
230 // check if number of parameters match
231 if ( callparams->size() != funcIds->size() )
233 emit ErrorMsg(node->getToken(), i18n("Call to function '%1' with wrong number of parameters.").arg(funcname), 5020);
234 return;
237 // pass parameters to function
238 // by adding them to it's symboltable and setting the values
239 TreeNode::iterator pfrom, pto = funcIds->begin();
240 symtable funcSymTable;
242 for (pfrom = callparams->begin(); pfrom != callparams->end(); ++pfrom )
244 if (bAbort) return;
245 if (bPause) startPausing();
246 kapp->processEvents();
248 // execute the parameters which can be expressions
249 execute(*pfrom);
251 QString idname = (*pto)->getLook();
252 funcSymTable[idname] = (*pfrom)->getValue();
253 ++pto;
256 symbolTables.push(funcSymTable); // use new symboltable for current function
258 // execute function statement block
259 bReturn = false; // set to true when return is called
260 execute( funcnode->secondChild() );
261 bReturn = false; // function execution done
263 symbolTables.pop(); // release function symboltable
267 // execute a function and expect and get return
268 // value from stack
269 // first child = function name
270 // second child = parameters
271 void Executer::execRetFunction(TreeNode* node)
273 execFunction(node);
274 if (runStack.size() == 0)
276 emit ErrorMsg(node->getToken(), i18n("Function %1 did not return a value.").arg( node->getLook() ), 5030);
277 return;
279 node->setValue( runStack.top() ); // set return val
280 runStack.pop(); // remove from stack
284 void Executer::execReturn(TreeNode* node)
286 execute( node->firstChild() ); // execute return expression
287 runStack.push( node->firstChild()->getValue() );
288 bReturn = true; // notify blocks of return
292 void Executer::execBreak(/*TreeNode* node*/)
294 bBreak = true; // stops loop block execution
298 void Executer::execBlock(TreeNode* node)
300 // execute all statements in block
301 TreeNode::iterator i;
302 for (i = node->begin(); i != node->end(); ++i)
304 if (runSpeed != 0) slowDown(*i);
305 if (bAbort) return;
306 if (bPause) startPausing();
307 kapp->processEvents();
309 execute(*i);
311 if (bReturn || bBreak) break; //jump out of block
316 void Executer::execForEach(TreeNode* node)
318 // sorry, not fully implemented/tested yet
319 TreeNode* expr1 = node->firstChild();
320 TreeNode* expr2 = node->secondChild();
321 TreeNode* statements = node->thirdChild();
323 execute(expr1);
324 execute(expr2);
326 QString expStr1 = expr1->getValue().String();
327 QString expStr2 = expr2->getValue().String();
329 bBreak = false;
331 int i = expStr2.contains(expStr1, false);
332 for ( ; i > 0; i-- )
334 if (bAbort) return;
335 if (bPause) startPausing();
336 kapp->processEvents();
338 execute(statements);
339 if (bBreak || bReturn) break; //jump out loop
341 bBreak = false;
346 void Executer::execFor(TreeNode* node)
348 TreeNode* id = node->firstChild();
349 TreeNode* startNode = node->secondChild();
350 TreeNode* stopNode = node->thirdChild();
351 TreeNode* statements = node->fourthChild();
353 QString name = id->getLook();
355 execute(startNode);
356 //assign startval to id
357 Value startVal = startNode->getValue();
358 ( symbolTables.top() )[ name ] = startVal;
361 execute(stopNode);
362 Value stopVal = stopNode->getValue();
364 if(node->size() == 4 ) //for loop without step part
366 bBreak = false;
367 for (double d = startVal.Number(); d <= stopVal.Number(); d = d + 1)
369 if (bAbort) return;
370 if (bPause) startPausing();
371 kapp->processEvents();
372 ( symbolTables.top() )[name] = d;
373 execute( statements );
374 if (bBreak || bReturn) break; //jump out loop
376 bBreak = false;
378 else //for loop with step part
380 TreeNode* step = node->fourthChild();
381 statements = node->fifthChild();
383 execute(step);
384 Value stepVal = step->getValue();
385 bBreak = false;
386 if ( (stepVal.Number() >= 0.0) && (startVal.Number() <= stopVal.Number() ) )
388 for ( double d = startVal.Number(); d <= stopVal.Number(); d = d + stepVal.Number() )
390 if (bAbort) return;
391 if (bPause) startPausing();
392 kapp->processEvents();
394 (symbolTables.top() )[name] = d;
395 execute( statements );
396 if (bBreak || bReturn) break; //jump out loop
399 else if ( (stepVal.Number() < 0.0) && (startVal.Number() >= stopVal.Number() ) )
401 for (double d = startVal.Number(); d >= stopVal.Number(); d = d + stepVal.Number() )
403 if (bAbort) return;
404 if (bPause) startPausing();
405 kapp->processEvents();
407 ( symbolTables.top() )[name] = d;
408 execute(statements);
409 if (bBreak || bReturn) break; //jump out loop
412 bBreak = false;
418 void Executer::execRepeat(TreeNode* node)
420 TreeNode* value = node->firstChild();
421 TreeNode* statements = node->secondChild();
423 bBreak = false;
424 execute(value);
425 for ( int i = ROUND2INT( value->getValue().Number() ); i > 0; i-- )
427 if (bAbort) return;
428 if (bPause) startPausing();
429 kapp->processEvents();
431 execute(statements);
432 if (bBreak || bReturn) break; //jump out loop
434 bBreak = false;
438 void Executer::execWhile(TreeNode* node)
440 TreeNode* condition = node->firstChild();
441 TreeNode* statements = node->secondChild();
443 bBreak = false;
444 execute(condition);
445 while (condition->getValue().Number() != 0)
447 if (bAbort) return;
448 if (bPause) startPausing();
449 kapp->processEvents();
451 execute(statements);
452 if (bBreak || bReturn) break; //jump out loop
453 execute(condition);
455 bBreak = false;
459 void Executer::execIf(TreeNode* node)
461 TreeNode* condition = node->firstChild();
462 TreeNode* ifblok = node->secondChild();
464 //determine if there is an else part
465 if (node->size() == 2) // no else
467 execute( condition );
468 if( condition->getValue().Number() != 0 ) execute(ifblok);
470 else // else part given
472 TreeNode* elseblok = node->thirdChild();
473 execute( condition );
474 if( condition->getValue().Number() != 0 ) execute(ifblok);
475 else execute( elseblok );
481 void Executer::execAssign(TreeNode* node)
483 TreeNode* expr = node->firstChild();
485 execute(expr);
486 ( symbolTables.top() )[ node->getLook() ] = expr->getValue();
489 void Executer::execExpression(/*TreeNode* node*/)
491 // execExpression is not implemented, because it should not be needed!
494 void Executer::execId(TreeNode* node)
496 node->setValue( ( symbolTables.top() )[ node->getLook() ] );
499 void Executer::execConstant(/*TreeNode* node*/)
501 // do nothing, value is already set
504 Value Executer::exec2getValue(TreeNode* node)
506 execute(node);
507 return node->getValue();
511 void Executer::execAdd(TreeNode* node)
513 Value left( exec2getValue( node->firstChild() ) );
514 Value right( exec2getValue( node->secondChild() ) );
516 if (left.Type() == numberValue && right.Type() == numberValue) node->setValue( left + right );
517 else node->setValue( left.String().append( right.String() ) );
521 void Executer::execMul(TreeNode* node)
523 Value left( exec2getValue( node->firstChild() ) );
524 Value right( exec2getValue( node->secondChild() ) );
526 if (left.Type() == numberValue && right.Type() == numberValue) node->setValue( left * right );
527 else emit ErrorMsg(node->getToken(), i18n("Can only multiply numbers."), 9000);
531 void Executer::execDiv(TreeNode* node)
533 Value left( exec2getValue( node->firstChild() ) );
534 Value right( exec2getValue( node->secondChild() ) );
536 if (left.Type() == numberValue && right.Type() == numberValue)
538 if (right.Number() == 0) emit ErrorMsg(node->getToken(), i18n("Cannot divide by zero."), 9000);
539 else node->setValue( left / right );
541 else emit ErrorMsg(node->getToken(), i18n("Can only divide numbers."), 9000);
545 void Executer::execSub(TreeNode* node)
547 Value left( exec2getValue( node->firstChild() ) );
548 Value right( exec2getValue( node->secondChild() ) );
550 if (left.Type() == numberValue && right.Type() == numberValue)
551 node->setValue( left - right );
553 else emit ErrorMsg(node->getToken(), i18n("Can only subtract numbers."), 9000);
558 void Executer::execLT(TreeNode* node)
560 Value left( exec2getValue( node->firstChild() ) );
561 Value right( exec2getValue( node->secondChild() ) );
563 node->setValue( left < right );
566 void Executer::execLE(TreeNode* node)
568 Value left( exec2getValue( node->firstChild() ) );
569 Value right( exec2getValue( node->secondChild() ) );
571 node->setValue( left <= right );
574 void Executer::execGT(TreeNode* node)
576 Value left( exec2getValue( node->firstChild() ) );
577 Value right( exec2getValue( node->secondChild() ) );
579 node->setValue( left > right );
582 void Executer::execGE(TreeNode* node)
584 Value left( exec2getValue( node->firstChild() ) );
585 Value right( exec2getValue( node->secondChild() ) );
587 node->setValue( left >= right );
591 void Executer::execEQ(TreeNode* node)
593 Value left( exec2getValue( node->firstChild() ) );
594 Value right( exec2getValue( node->secondChild() ) );
596 node->setValue( left == right );
600 void Executer::execNE(TreeNode* node)
602 Value left( exec2getValue( node->firstChild() ) );
603 Value right( exec2getValue( node->secondChild() ) );
605 node->setValue( left != right );
610 void Executer::execAnd(TreeNode* node)
612 bool nl = exec2getValue( node->firstChild() ).Number() != 0;
613 bool nr = exec2getValue( node->secondChild() ).Number() != 0;
614 node->setValue( (double) (nl && nr) );
618 void Executer::execOr(TreeNode* node)
620 bool nl = exec2getValue( node->firstChild() ).Number() != 0;
621 bool nr = exec2getValue( node->secondChild() ).Number() != 0;
622 node->setValue(nl || nr);
626 void Executer::execNot(TreeNode* node)
628 node->setValue( exec2getValue( node->firstChild() ).Number() == 0 );
632 void Executer::execMinus(TreeNode* node)
634 node->setValue( -exec2getValue( node->firstChild() ).Number() );
638 QString Executer::runCommand(const QString& command)
640 FILE *pstream;
642 if ( ( pstream = popen( command.ascii(), "r" ) ) == NULL ) return ("");
644 QString Line;
645 char buf[100];
647 while( fgets(buf, sizeof(buf), pstream) !=NULL) {
648 if (bAbort) return ("");
649 kapp->processEvents();
651 Line += buf;
653 pclose(pstream);
654 return Line;
658 void Executer::execRun(TreeNode* node)
660 QString cmd = exec2getValue( node->firstChild() ).String();
661 node->setValue( runCommand(cmd) );
667 void Executer::execClear(TreeNode* node)
669 if ( checkParameterQuantity(node, 0, 5060) ) emit Clear();
672 void Executer::execCenter(TreeNode* node)
674 if ( checkParameterQuantity(node, 0, 5060) ) emit Center();
677 void Executer::execPenUp(TreeNode* node)
679 if ( checkParameterQuantity(node, 0, 5060) ) emit PenUp();
682 void Executer::execPenDown(TreeNode* node)
684 if ( checkParameterQuantity(node, 0, 5060) ) emit PenDown();
687 void Executer::execSpriteShow(TreeNode* node)
689 if ( checkParameterQuantity(node, 0, 5060) ) emit SpriteShow();
692 void Executer::execSpriteHide(TreeNode* node)
694 if ( checkParameterQuantity(node, 0, 5060) ) emit SpriteHide();
697 void Executer::execSpritePress(TreeNode* node)
699 if ( checkParameterQuantity(node, 0, 5060) ) emit SpritePress();
702 void Executer::execWrapOn(TreeNode* node)
704 if ( checkParameterQuantity(node, 0, 5060) ) emit WrapOn();
707 void Executer::execWrapOff(TreeNode* node)
709 if ( checkParameterQuantity(node, 0, 5060) ) emit WrapOff();
712 void Executer::execReset(TreeNode* node)
714 if ( checkParameterQuantity(node, 0, 5060) ) emit Reset();
717 void Executer::execMessage(TreeNode* node)
719 if ( checkParameterQuantity(node, 1, 5060) && checkParameterType(node, stringValue, 5060) )
720 emit MessageDialog( node->firstChild()->getValue().String() );
728 void Executer::execGoX(TreeNode* node)
730 if ( !checkParameterQuantity(node, 1, 5060) ) return;
731 TreeNode* param1 = node->firstChild();
732 execute(param1);
733 if ( checkParameterType(node, numberValue, 5060) )
735 emit GoX( param1->getValue().Number() );
739 void Executer::execGoY(TreeNode* node)
741 if ( !checkParameterQuantity(node, 1, 5060) ) return;
742 TreeNode* param1 = node->firstChild();
743 execute(param1);
744 if ( checkParameterType(node, numberValue, 5060) )
746 emit GoY( param1->getValue().Number() );
750 void Executer::execForward(TreeNode* node)
752 if ( !checkParameterQuantity(node, 1, 5060) ) return;
753 TreeNode* param1 = node->firstChild();
754 execute(param1);
755 if ( checkParameterType(node, numberValue, 5060) )
757 emit Forward( param1->getValue().Number() );
761 void Executer::execBackward(TreeNode* node)
763 if ( !checkParameterQuantity(node, 1, 5060) ) return;
764 TreeNode* param1 = node->firstChild();
765 execute(param1);
766 if ( checkParameterType(node, numberValue, 5060) )
768 emit Backward( param1->getValue().Number() );
772 void Executer::execDirection(TreeNode* node)
774 if ( !checkParameterQuantity(node, 1, 5060) ) return;
775 TreeNode* param1 = node->firstChild();
776 execute(param1);
777 if ( checkParameterType(node, numberValue, 5060) )
779 emit Direction( param1->getValue().Number() );
783 void Executer::execTurnLeft(TreeNode* node)
785 if ( !checkParameterQuantity(node, 1, 5060) ) return;
786 TreeNode* param1 = node->firstChild();
787 execute(param1);
788 if ( checkParameterType(node, numberValue, 5060) )
790 emit TurnLeft( param1->getValue().Number() );
794 void Executer::execTurnRight(TreeNode* node)
796 if ( !checkParameterQuantity(node, 1, 5060) ) return;
797 TreeNode* param1 = node->firstChild();
798 execute(param1);
799 if ( checkParameterType(node, numberValue, 5060) )
801 emit TurnRight( param1->getValue().Number() );
805 void Executer::execSetPenWidth(TreeNode* node)
807 if ( !checkParameterQuantity(node, 1, 5060) ) return;
808 TreeNode* param1 = node->firstChild();
809 execute(param1);
810 if ( checkParameterType(node, numberValue, 5060) )
812 int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
813 if (x < 1 || x > 10000)
814 emit ErrorMsg(node->getToken(), i18n("The penwidth cannot be set to something smaller than 1, or bigger than 10000."), 6050);
815 else
816 emit SetPenWidth(x);
820 void Executer::execSpriteChange(TreeNode* node)
822 if ( !checkParameterQuantity(node, 1, 5060) ) return;
823 TreeNode* param1 = node->firstChild();
824 execute(param1);
825 if ( checkParameterType(node, numberValue, 5060) )
827 int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
828 emit SpriteChange(x);
832 void Executer::execFontSize(TreeNode* node)
834 if ( !checkParameterQuantity(node, 1, 5060) ) return;
835 TreeNode* param1 = node->firstChild();
836 execute(param1);
837 if ( checkParameterType(node, numberValue, 5060) )
839 int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
840 if ( x < 0 || x > 350 )
841 emit ErrorMsg(node->getToken(), i18n("The parameters of function %1 must be within range: 0 to 350.").arg( node->getLook() ), 5065);
842 else
843 emit FontSize(x);
852 void Executer::execGo(TreeNode* node)
854 if ( !checkParameterQuantity(node, 2, 5060) ) return;
855 TreeNode* nodeX = node->firstChild(); // getting
856 TreeNode* nodeY = node->secondChild();
857 execute(nodeX); // executing
858 execute(nodeY);
860 if ( checkParameterType(node, numberValue, 5060) )
862 emit Go( nodeX->getValue().Number(), nodeY->getValue().Number() );
866 void Executer::execResizeCanvas(TreeNode* node)
868 if ( !checkParameterQuantity(node, 2, 5060) ) return;
869 TreeNode* nodeX = node->firstChild(); // getting
870 TreeNode* nodeY = node->secondChild();
871 execute(nodeX); // executing
872 execute(nodeY);
874 if ( checkParameterType(node, numberValue, 5060) )
876 int x = ROUND2INT( nodeX->getValue().Number() ); // converting & rounding to int
877 int y = ROUND2INT( nodeY->getValue().Number() );
878 if ( ( x < 1 || y < 1 ) || ( x > 10000 || y > 10000 ) )
879 emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 1 to 10000.").arg( node->getLook() ), 7030);
880 else
881 emit ResizeCanvas(x, y);
885 void Executer::execRandom(TreeNode* node)
887 if ( !checkParameterQuantity(node, 2, 5060) ) return;
888 TreeNode* nodeX = node->firstChild(); // getting
889 TreeNode* nodeY = node->secondChild();
890 execute(nodeX); // executing
891 execute(nodeY);
893 if ( !checkParameterType(node, numberValue, 5060) ) return;
894 double x = nodeX->getValue().Number();
895 double y = nodeY->getValue().Number();
896 double r = (double)( KApplication::random() ) / RAND_MAX;
897 node->setValue( r * ( y - x ) + x );
904 void Executer::execSetFgColor(TreeNode* node)
906 if ( !checkParameterQuantity(node, 3, 5060) ) return;
907 TreeNode* nodeR = node->firstChild(); // getting
908 TreeNode* nodeG = node->secondChild();
909 TreeNode* nodeB = node->thirdChild();
910 execute(nodeR); // executing
911 execute(nodeG);
912 execute(nodeB);
913 if ( checkParameterType(node, numberValue, 5060) )
915 int r = ROUND2INT( nodeR->getValue().Number() ); // converting & rounding to int
916 int g = ROUND2INT( nodeG->getValue().Number() );
917 int b = ROUND2INT( nodeB->getValue().Number() );
918 if ( ( r < 0 || g < 0 || b < 0 ) || ( r > 255 || g > 255 || b > 255 ) )
919 emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 0 to 255.").arg( node->getLook() ), 6090);
920 else
921 emit SetFgColor(r, g, b);
925 void Executer::execSetBgColor(TreeNode* node)
927 if ( !checkParameterQuantity(node, 3, 5060) ) return;
928 TreeNode* nodeR = node->firstChild(); // getting
929 TreeNode* nodeG = node->secondChild();
930 TreeNode* nodeB = node->thirdChild();
931 execute(nodeR); // executing
932 execute(nodeG);
933 execute(nodeB);
934 if ( checkParameterType(node, numberValue, 5060) )
936 int r = ROUND2INT( nodeR->getValue().Number() ); // converting & rounding to int
937 int g = ROUND2INT( nodeG->getValue().Number() );
938 int b = ROUND2INT( nodeB->getValue().Number() );
939 if ( ( r < 0 || g < 0 || b < 0 ) || ( r > 255 || g > 255 || b > 255 ) )
940 emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 0 to 255.").arg( node->getLook() ), 6090);
941 else
942 emit SetBgColor(r, g, b);
956 void Executer::execInputWindow(TreeNode* node)
958 if ( !checkParameterQuantity(node, 1, 5060) ) return;
960 QString value = node->firstChild()->getValue().String();
961 emit InputDialog(value);
963 node->setType(constantNode);
964 if ( value.isEmpty() ) node->getValue().resetValue(); // set value back to empty
965 else
967 bool ok = true;
968 double num = value.toDouble(&ok); // to see if the value from the InpDialog is a float
969 if (ok) node->setValue(num);
970 else node->setValue(value);
974 void Executer::execPrint(TreeNode* node)
976 if (node->size() == 0)
978 emit ErrorMsg(node->getToken(), i18n("The print command needs input"), 5050);
979 return;
981 TreeNode::iterator i;
982 QString str = "";
983 for (i = node->begin(); i != node->end(); ++i)
985 execute(*i); // execute expression
986 str = str + (*i)->getValue().String();
988 emit Print(str);
991 void Executer::execFontType(TreeNode* node)
993 // if not 2 params go staight to the checkParam, diplay the error, and return to prevent a crash
994 if ( !checkParameterQuantity(node, 2, 5060) && !checkParameterType(node, stringValue, 5060) ) return;
996 QString extra;
997 if (node->size() == 2) QString extra = node->secondChild()->getValue().String();
998 QString family = node->firstChild()->getValue().String();
999 emit FontType(family, extra);
1003 void Executer::execWait(TreeNode* node)
1005 if ( !checkParameterQuantity(node, 1, 5060) ) return;
1006 TreeNode* param1 = node->firstChild();
1007 execute(param1);
1008 if ( !checkParameterType(node, numberValue, 5060) ) return;
1009 int msec = (int)( 1000 * param1->getValue().Number() );
1010 startWaiting(msec);
1013 void Executer::startWaiting(int msec)
1015 bStopWaiting = false;
1016 // call a timer that sets stopWaiting to true when it runs
1017 QTimer::singleShot( msec, this, SLOT( slotStopWaiting() ) );
1018 while (bStopWaiting == false)
1020 if (bAbort) return; // waits need to be interrupted by the stop action
1021 if (bPause) startPausing();
1022 kapp->processEvents();
1024 // only 10 times per second is enough... else the CPU gets 100% loaded ( not nice :)
1025 usleep(100000);
1029 void Executer::slotStopWaiting()
1031 bStopWaiting = true;
1034 void Executer::startPausing()
1036 while (bPause == true)
1038 if (bAbort) return; // waits need to be interrupted by the stop action
1039 kapp->processEvents();
1040 // only 10 times per second is enough... else the CPU gets 100% loaded ( not nice :)
1041 usleep(100000);
1045 void Executer::slotStopPausing()
1047 bPause = false;
1053 bool Executer::checkParameterQuantity(TreeNode* node, uint quantity, int errorCode)
1055 if (quantity == 0)
1057 if (node->size() == 0) return true; // thats easy!
1058 emit ErrorMsg(node->getToken(), i18n("The %1 command accepts no parameters.").arg( node->getLook() ), errorCode);
1059 return false;
1062 uint nodeSize = node->size();
1063 if (nodeSize != 0) // when all parameters are forgotten the parser puts a Unknown/tokEOL param, catch this:
1064 if (node->firstChild()->getToken().type == tokEOL) nodeSize = 0;
1066 if (nodeSize != quantity)
1068 if (nodeSize < quantity)
1070 emit ErrorMsg(node->getToken(), i18n("The %1 command was called with %2 but needs 1 parameter.", "The %1 command was called with %2 but needs %n parameters.", quantity).arg( node->getLook() ).arg(nodeSize), errorCode);
1072 else
1074 emit ErrorMsg(node->getToken(), i18n("The %1 command was called with %2 but only accepts 1 parameter.", "The %1 command was called with %2 but only accepts %n parameters.", quantity).arg( node->getLook() ).arg(nodeSize), errorCode);
1076 return false;
1078 return true; // if all tests passed
1082 bool Executer::checkParameterType(TreeNode* node, int valueType, int errorCode)
1084 uint quantity = node->size();
1085 uint ii = 1;
1086 TreeNode::iterator i = node->begin();
1087 while ( i != node->end() && ii <= quantity )
1089 if ( (*i)->getValue().Type() != valueType )
1091 switch (valueType)
1093 case stringValue:
1094 if (quantity == 1)
1095 emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts a string as its parameter.").arg( node->getLook() ), errorCode);
1096 else
1097 emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts strings as its parameters.").arg( node->getLook() ), errorCode);
1098 break;
1100 case numberValue:
1101 if (quantity == 1)
1102 emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts a number as its parameter.").arg( node->getLook() ), errorCode);
1103 else
1104 emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts numbers as its parameters.").arg( node->getLook() ), errorCode);
1105 break;
1107 return false;
1109 ++i;
1110 ii++;
1112 return true; // if all tests passed
1115 #include "executer.moc"