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();
27 #include <kapplication.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
)
40 functionTable
.clear();
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();
66 symbolTables
.pop(); //free up stack
71 void Executer::slowDown(TreeNode
* node
)
88 kdDebug(0)<<"Executer: Wrong execution speed given"<<endl
;
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
)
100 void Executer::pause()
102 // The next line is within all loops of the Executer
103 // if (bAbort) return;
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
111 void Executer::abort()
113 // The next line is within all loops of the Executer
114 // if(bAbort) return;
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
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
200 kdDebug(0)<<"Found unsupported node named '"<<node
->getLook()<<"' in the tree @ ("<<node
->getRow()<<", "<<node
->getCol()<<")"<<endl
;
206 void Executer::createFunction(TreeNode
* node
)
208 QString funcname
= node
->getLook();
209 functionTable
[funcname
] = node
; //store for later use
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);
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);
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
)
245 if (bPause
) startPausing();
246 kapp
->processEvents();
248 // execute the parameters which can be expressions
251 QString idname
= (*pto
)->getLook();
252 funcSymTable
[idname
] = (*pfrom
)->getValue();
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
269 // first child = function name
270 // second child = parameters
271 void Executer::execRetFunction(TreeNode
* node
)
274 if (runStack
.size() == 0)
276 emit
ErrorMsg(node
->getToken(), i18n("Function %1 did not return a value.").arg( node
->getLook() ), 5030);
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
);
306 if (bPause
) startPausing();
307 kapp
->processEvents();
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();
326 QString expStr1
= expr1
->getValue().String();
327 QString expStr2
= expr2
->getValue().String();
331 int i
= expStr2
.contains(expStr1
, false);
335 if (bPause
) startPausing();
336 kapp
->processEvents();
339 if (bBreak
|| bReturn
) break; //jump out loop
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();
356 //assign startval to id
357 Value startVal
= startNode
->getValue();
358 ( symbolTables
.top() )[ name
] = startVal
;
362 Value stopVal
= stopNode
->getValue();
364 if(node
->size() == 4 ) //for loop without step part
367 for (double d
= startVal
.Number(); d
<= stopVal
.Number(); d
= d
+ 1)
370 if (bPause
) startPausing();
371 kapp
->processEvents();
372 ( symbolTables
.top() )[name
] = d
;
373 execute( statements
);
374 if (bBreak
|| bReturn
) break; //jump out loop
378 else //for loop with step part
380 TreeNode
* step
= node
->fourthChild();
381 statements
= node
->fifthChild();
384 Value stepVal
= step
->getValue();
386 if ( (stepVal
.Number() >= 0.0) && (startVal
.Number() <= stopVal
.Number() ) )
388 for ( double d
= startVal
.Number(); d
<= stopVal
.Number(); d
= d
+ stepVal
.Number() )
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() )
404 if (bPause
) startPausing();
405 kapp
->processEvents();
407 ( symbolTables
.top() )[name
] = d
;
409 if (bBreak
|| bReturn
) break; //jump out loop
418 void Executer::execRepeat(TreeNode
* node
)
420 TreeNode
* value
= node
->firstChild();
421 TreeNode
* statements
= node
->secondChild();
425 for ( int i
= ROUND2INT( value
->getValue().Number() ); i
> 0; i
-- )
428 if (bPause
) startPausing();
429 kapp
->processEvents();
432 if (bBreak
|| bReturn
) break; //jump out loop
438 void Executer::execWhile(TreeNode
* node
)
440 TreeNode
* condition
= node
->firstChild();
441 TreeNode
* statements
= node
->secondChild();
445 while (condition
->getValue().Number() != 0)
448 if (bPause
) startPausing();
449 kapp
->processEvents();
452 if (bBreak
|| bReturn
) break; //jump out loop
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();
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
)
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
)
642 if ( ( pstream
= popen( command
.ascii(), "r" ) ) == NULL
) return ("");
647 while( fgets(buf
, sizeof(buf
), pstream
) !=NULL
) {
648 if (bAbort
) return ("");
649 kapp
->processEvents();
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();
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();
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();
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();
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();
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();
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();
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();
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);
820 void Executer::execSpriteChange(TreeNode
* node
)
822 if ( !checkParameterQuantity(node
, 1, 5060) ) return;
823 TreeNode
* param1
= node
->firstChild();
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();
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);
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
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
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);
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
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
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);
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
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);
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
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);
981 TreeNode::iterator i
;
983 for (i
= node
->begin(); i
!= node
->end(); ++i
)
985 execute(*i
); // execute expression
986 str
= str
+ (*i
)->getValue().String();
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;
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();
1008 if ( !checkParameterType(node
, numberValue
, 5060) ) return;
1009 int msec
= (int)( 1000 * param1
->getValue().Number() );
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 :)
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 :)
1045 void Executer::slotStopPausing()
1053 bool Executer::checkParameterQuantity(TreeNode
* node
, uint quantity
, int errorCode
)
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
);
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
);
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
);
1078 return true; // if all tests passed
1082 bool Executer::checkParameterType(TreeNode
* node
, int valueType
, int errorCode
)
1084 uint quantity
= node
->size();
1086 TreeNode::iterator i
= node
->begin();
1087 while ( i
!= node
->end() && ii
<= quantity
)
1089 if ( (*i
)->getValue().Type() != valueType
)
1095 emit
ErrorMsg(node
->getToken(), i18n("The %1 command only accepts a string as its parameter.").arg( node
->getLook() ), errorCode
);
1097 emit
ErrorMsg(node
->getToken(), i18n("The %1 command only accepts strings as its parameters.").arg( node
->getLook() ), errorCode
);
1102 emit
ErrorMsg(node
->getToken(), i18n("The %1 command only accepts a number as its parameter.").arg( node
->getLook() ), errorCode
);
1104 emit
ErrorMsg(node
->getToken(), i18n("The %1 command only accepts numbers as its parameters.").arg( node
->getLook() ), errorCode
);
1112 return true; // if all tests passed
1115 #include "executer.moc"