summaryrefslogtreecommitdiffstats
path: root/kturtle
diff options
context:
space:
mode:
Diffstat (limited to 'kturtle')
-rw-r--r--kturtle/AUTHORS11
-rw-r--r--kturtle/COPYING340
-rw-r--r--kturtle/ChangeLog0
-rw-r--r--kturtle/Doxyfile233
-rw-r--r--kturtle/INSTALL178
-rw-r--r--kturtle/Makefile.am5
-rw-r--r--kturtle/NEWS2
-rw-r--r--kturtle/README95
-rw-r--r--kturtle/TODO345
-rw-r--r--kturtle/data/Makefile.am12
-rw-r--r--kturtle/data/README.data27
-rw-r--r--kturtle/data/ad.logo125
-rw-r--r--kturtle/data/arrow.logo23
-rw-r--r--kturtle/data/canvascolors.logo33
-rw-r--r--kturtle/data/curly.logo13
-rw-r--r--kturtle/data/flower.logo26
-rw-r--r--kturtle/data/kde.logo120
-rw-r--r--kturtle/data/logohighlightstyle.en_US.xml141
-rw-r--r--kturtle/data/logokeywords.en_US.xml241
-rw-r--r--kturtle/data/randomname.logo18
-rw-r--r--kturtle/data/square.logo6
-rw-r--r--kturtle/data/squaresss.logo22
-rw-r--r--kturtle/data/timestables.logo15
-rw-r--r--kturtle/data/triangle.logo6
-rw-r--r--kturtle/data/trianglesss.logo24
-rw-r--r--kturtle/file.txt34
-rw-r--r--kturtle/kturtle.kdevelop160
-rw-r--r--kturtle/kturtle.kdevses65
-rw-r--r--kturtle/kturtle.lsm16
-rw-r--r--kturtle/scripts/README.scripts56
-rwxr-xr-xkturtle/scripts/i18n_examples.pl214
-rwxr-xr-xkturtle/scripts/i18n_highlighting.pl129
-rw-r--r--kturtle/src/Makefile.am37
-rw-r--r--kturtle/src/canvas.cpp644
-rw-r--r--kturtle/src/canvas.h101
-rw-r--r--kturtle/src/dialogs.cpp320
-rw-r--r--kturtle/src/dialogs.h165
-rw-r--r--kturtle/src/executer.cpp1116
-rw-r--r--kturtle/src/executer.h186
-rw-r--r--kturtle/src/hi16-app-kturtle.pngbin0 -> 632 bytes
-rw-r--r--kturtle/src/hi32-app-kturtle.pngbin0 -> 1396 bytes
-rw-r--r--kturtle/src/kturtle.cpp1181
-rw-r--r--kturtle/src/kturtle.desktop124
-rw-r--r--kturtle/src/kturtle.h182
-rw-r--r--kturtle/src/kturtle.kcfg93
-rw-r--r--kturtle/src/kturtleui.rc97
-rw-r--r--kturtle/src/lexer.cpp411
-rw-r--r--kturtle/src/lexer.h59
-rw-r--r--kturtle/src/main.cpp115
-rw-r--r--kturtle/src/parser.cpp1084
-rw-r--r--kturtle/src/parser.h126
-rw-r--r--kturtle/src/pics/Makefile.am8
-rw-r--r--kturtle/src/pics/turtle.0000.pngbin0 -> 480 bytes
-rw-r--r--kturtle/src/pics/turtle.0001.pngbin0 -> 1516 bytes
-rw-r--r--kturtle/src/pics/turtle.0002.pngbin0 -> 1561 bytes
-rw-r--r--kturtle/src/pics/turtle.0003.pngbin0 -> 1569 bytes
-rw-r--r--kturtle/src/pics/turtle.0004.pngbin0 -> 1671 bytes
-rw-r--r--kturtle/src/pics/turtle.0005.pngbin0 -> 1705 bytes
-rw-r--r--kturtle/src/pics/turtle.0006.pngbin0 -> 1606 bytes
-rw-r--r--kturtle/src/pics/turtle.0007.pngbin0 -> 2039 bytes
-rw-r--r--kturtle/src/pics/turtle.0008.pngbin0 -> 1856 bytes
-rw-r--r--kturtle/src/pics/turtle.0009.pngbin0 -> 475 bytes
-rw-r--r--kturtle/src/pics/turtle.0010.pngbin0 -> 1542 bytes
-rw-r--r--kturtle/src/pics/turtle.0011.pngbin0 -> 1585 bytes
-rw-r--r--kturtle/src/pics/turtle.0012.pngbin0 -> 1631 bytes
-rw-r--r--kturtle/src/pics/turtle.0013.pngbin0 -> 1702 bytes
-rw-r--r--kturtle/src/pics/turtle.0014.pngbin0 -> 1684 bytes
-rw-r--r--kturtle/src/pics/turtle.0015.pngbin0 -> 1552 bytes
-rw-r--r--kturtle/src/pics/turtle.0016.pngbin0 -> 1998 bytes
-rw-r--r--kturtle/src/pics/turtle.0017.pngbin0 -> 1809 bytes
-rw-r--r--kturtle/src/pics/turtle.0018.pngbin0 -> 483 bytes
-rw-r--r--kturtle/src/pics/turtle.0019.pngbin0 -> 1546 bytes
-rw-r--r--kturtle/src/pics/turtle.0020.pngbin0 -> 1584 bytes
-rw-r--r--kturtle/src/pics/turtle.0021.pngbin0 -> 1568 bytes
-rw-r--r--kturtle/src/pics/turtle.0022.pngbin0 -> 1654 bytes
-rw-r--r--kturtle/src/pics/turtle.0023.pngbin0 -> 1681 bytes
-rw-r--r--kturtle/src/pics/turtle.0024.pngbin0 -> 1612 bytes
-rw-r--r--kturtle/src/pics/turtle.0025.pngbin0 -> 2029 bytes
-rw-r--r--kturtle/src/pics/turtle.0026.pngbin0 -> 1857 bytes
-rw-r--r--kturtle/src/pics/turtle.0027.pngbin0 -> 473 bytes
-rw-r--r--kturtle/src/pics/turtle.0028.pngbin0 -> 1522 bytes
-rw-r--r--kturtle/src/pics/turtle.0029.pngbin0 -> 1575 bytes
-rw-r--r--kturtle/src/pics/turtle.0030.pngbin0 -> 1608 bytes
-rw-r--r--kturtle/src/pics/turtle.0031.pngbin0 -> 1682 bytes
-rw-r--r--kturtle/src/pics/turtle.0032.pngbin0 -> 1672 bytes
-rw-r--r--kturtle/src/pics/turtle.0033.pngbin0 -> 1576 bytes
-rw-r--r--kturtle/src/pics/turtle.0034.pngbin0 -> 2010 bytes
-rw-r--r--kturtle/src/pics/turtle.0035.pngbin0 -> 1826 bytes
-rw-r--r--kturtle/src/pics/turtle.pngbin0 -> 480 bytes
-rw-r--r--kturtle/src/settings.kcfgc5
-rw-r--r--kturtle/src/token.cpp19
-rw-r--r--kturtle/src/token.h222
-rw-r--r--kturtle/src/translate.cpp107
-rw-r--r--kturtle/src/translate.h49
-rw-r--r--kturtle/src/treenode.cpp255
-rw-r--r--kturtle/src/treenode.h276
-rw-r--r--kturtle/src/value.cpp328
-rw-r--r--kturtle/src/value.h85
98 files changed, 10130 insertions, 0 deletions
diff --git a/kturtle/AUTHORS b/kturtle/AUTHORS
new file mode 100644
index 00000000..8316b8b4
--- /dev/null
+++ b/kturtle/AUTHORS
@@ -0,0 +1,11 @@
+Cies Breijs <cies # showroommama.nl>
+Main developer and initiator
+
+
+Walter Schreppers <Walter.Schreppers # ua.ac.be>
+Author of "wsbasic" (wsbasic.sf.net) the base for the interpreter of KTurtle
+
+
+Anne-Marie Mahfouf <annemarie.mahfouf # free.fr>
+Big contributor, supporter and fan
+
diff --git a/kturtle/COPYING b/kturtle/COPYING
new file mode 100644
index 00000000..c13faf0d
--- /dev/null
+++ b/kturtle/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kturtle/ChangeLog b/kturtle/ChangeLog
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/kturtle/ChangeLog
diff --git a/kturtle/Doxyfile b/kturtle/Doxyfile
new file mode 100644
index 00000000..d3df809e
--- /dev/null
+++ b/kturtle/Doxyfile
@@ -0,0 +1,233 @@
+# Doxyfile 1.3.3-Gideon
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = KTurtle
+PROJECT_NUMBER = 0.1
+OUTPUT_DIRECTORY =
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = YES
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT =
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.xpm \
+ *.dox
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = YES
+TOC_EXPAND = YES
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = YES
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS =NO
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+UML_LOOK = YES
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/kturtle/INSTALL b/kturtle/INSTALL
new file mode 100644
index 00000000..6b29f2ed
--- /dev/null
+++ b/kturtle/INSTALL
@@ -0,0 +1,178 @@
+
+
+
+See README for specific instuction on how to build KTurtle!
+
+
+
+
+
+The following is default stuff:
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/kturtle/Makefile.am b/kturtle/Makefile.am
new file mode 100644
index 00000000..4d316de1
--- /dev/null
+++ b/kturtle/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = src data
+
+EXTRA_DIST = AUTHORS COPYING INSTALL NEWS TODO COPYING ChangeLog kturtle.lsm
+
+include ../admin/Doxyfile.am
diff --git a/kturtle/NEWS b/kturtle/NEWS
new file mode 100644
index 00000000..b44dda35
--- /dev/null
+++ b/kturtle/NEWS
@@ -0,0 +1,2 @@
+27th December 2003
+First import in kdenonbeta
diff --git a/kturtle/README b/kturtle/README
new file mode 100644
index 00000000..b11066b2
--- /dev/null
+++ b/kturtle/README
@@ -0,0 +1,95 @@
+Hi,
+
+you are reading the README of the 'KTurtle' project that is initiated
+and maintained by Cies Breijs (cies-AT-showroommama-DOT-nl). In this
+README I will tell you how to get KTurtle running on your computer.
+
+
+
+1. Requirements
+You need to have KDE 3.2 or higher. I don't know if it will work with different
+KDE versions since I did not test it. If it does not work please see
+the Questions section below.
+
+
+
+2. Compiling
+The simplest way to compile this package is:
+
+ 1) `cd' to the directory containing the package's source code and type
+ `./configure --prefix=<PATH>' to configure the package for your
+ system.
+
+ Make sure to replace <PATH> by the path wher your KDE apps are
+ installed. This is mostly '/usr', but sometimes (for SuSE) '/opt/kde'.
+ If you dont know what to do try: `./configure --prefix=/usr'. If you don't give a --prefix the default path /usr/local will be used, resulting that KTurtle will no be with your other apps, and may not run smoothly.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for. If the
+ configure script exits with an error it will probably hint you
+ what it needs in order to succeed.
+
+ 2) Type `make' to compile the package.
+
+ 'make' also takes a while, and it also has the possibility to exit
+ with errors. Although the errors messages 'make' produces are mostly
+ not as clear as the error messages from 'configure', they are a hint
+ to what went wrong. Please see the Questions section below if you
+ dont know what to do with these messages.
+
+If it succeeded a binary named 'kturtle' is made and can be find in the
+'src' directory within the directory containing the package's source
+code.
+
+Before you can run KTurtle you need to install it.
+
+
+
+3. Installing
+NOTE: you often need 'root' privilliges to do the following!
+
+ 1) Type `make install' to install the programs and any data files and
+ documentation.
+
+ 2) You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+If you want to uninstall KTurtle you should type 'make uninstall' when
+in the source code directory.
+
+Please note that 'make install' will install KTurtle to the path that is provided to the './configure' command with the '--prefix' flag!
+
+
+4. Running
+Under normal circumstances should be able to run KTurtle from the
+commandline by typing 'kturtle'.
+
+If it does not work please go to the source code directory of KTurtle
+and type:
+
+ cd src
+ ./kturlte
+
+If this does not work please follow instuction form the Question section.
+
+
+
+5. Questions
+Check out the FAQ in the source code directory of KTurtle to see if your
+question has allready been asked.
+
+You can also mail questions to the mail address you find in the
+beginning of this document. Or visit the KTurtle website:
+http://kturlte.sf.net , or http://edu.kde.org/kturtle
+and post it in the forum.
+
+
+
+Thanks for reading!
+
+Cies.
+
+
+
+
+
diff --git a/kturtle/TODO b/kturtle/TODO
new file mode 100644
index 00000000..f9da37cb
--- /dev/null
+++ b/kturtle/TODO
@@ -0,0 +1,345 @@
+This document goes on the BUGs and WISHes that regarding KTurtle
+
+18 june 2005
+------------------
+for KDE 3.5
+- add the fractals examples from http://www.stber-koenig.de/markus/kturtle/ in the examples folder
+-> problem when adding examples for translations
+
+- implement KNewStuff to share logo files via kde-files.org per language with png associated on the website
+
+
+ CHECKLIST FOR KTURTLE IN KDE 3.4:
+
+annma> get some other sprites alternative to the turtle
+
+ cies> or a better website
+
+annma> I would say: hunt bugs
+
+ cies> i think promotion will be an important part
+
+annma> I would say make sure we test kturtle thoroughly
+annma> remove config, remove installed files and try from scratch
+
+ cies> more examples? would that pull?
+annma> more examples are only in en_US at the moment
+
+annma> is all the code in the doc working correctly?
+ cies> dint check for a while
+ cies> i changed some syntaxt
+annma> that is to be checked
+
+ cies> maybe a contest...
+ cies> best logo script gets in the examples of the next kturtle
+ cies> and get TRANSLATED to many lang.s
+ cies> how does that sound?
+annma> yes
+ cies> good for a dot story
+annma> sounds good
+
+
+
+
+
+
+
+
+
+Chapeters in this documents:
+
+BUGs
+ - urgent bugs (small/regular and critical)
+ - big ones (that need losts of work)
+ - regular ones (the phat cocroach type)
+ - small bugs (annoyances that can be considered urgent, ie poisonless musquito's)
+ - unconfirmed
+
+WISHes
+ - important WISHes (that are needed for a 1.0 release and help to fulfill kturtles objectives)
+ - less important but nice WISHes
+ - WISHes that still have to be discussed
+
+
+ here we go!
+
+
+My [cies] TODO list (in this order!):
+- the connection with the manual should be fixed (might need a change in kdelibs) FIXED tnx Waldo!
+- bug, wishes, errmsgs-fixes concering the interpreter HAS TO RESULT IN HUGE REFACTORING
+- spice up the errormessage window with my great ideas ON HOLD
+
+
+
+
+>>>>> BUGs::Urgent
+
+cies> currently no urgent bugs that i know of. except for:
+THERE IS NO HELP ON THE ERROR DIALOG! (nor on the ColorPicker Dialog and the Configure Dlg)
+ this is needed for help button references
+
+
+
+
+>>>>> BUGs::Big
+ - I porbably have to refine the way error message get emitted, problems: Ugly-, short-, technical messages.
+
+ I'll have to:
+
+- try to break up/refine the most common errors
+- Reformulate all the error messages after simulating them
+- have links in there to corresponing help pages --> see WISHes
+- Maybe more LONGER, desciptive error messages should be triggered by the 'Help on Error", these messages should be stored in/out-side of the executer/parser, but maybe even better, the errormsg file. I18n should then be easy, and it should supply richtext ((k)html) + links to the manual. (this could be in the same dialog)
+- errmsgs should maybe be filtered since there is quite some garbage in the errors that come back.
+- possible no newlines in a command this could make the error messages more specific/descriptive. DONE
+
+
+
+
+>>>>> BUGs::Regular
+cies: get all the commands in the logokeywords.*.xml file working properly, and remove the commands that are not needed:
+Need to work eventually:
+- input (without window, grabKeyEvents... not easy :)
+- sprite* (i'll maybe look into this when i have Qt3.3 which fixes the nasty crashbug that came across)
+- 'speed' will come later [seperate 'move' methods have to be made inaddition to the line methods]
+
+would be nice (not in yet):
+- message, just a dialog with sone user defined text
+- and a dialog that return a bool (YesNoDlg)
+- more drawing functions, use directly from QCanvas; like: filled circle, filled square, filled triangle
+- more expressers: isString, isNumber, isRound
+- round()
+- true and fasle as cunfiguarables ---> in highlightstyle as Fat/grey
+
+- <joke> and what about a 'goto' command ( you can never make them mistakes young enough, muahoahoaaaa >:-} ) </joke> well?
+
+
+- use qt-richtext <qt></qt> in dialogs etc.
+
+
+
+
+>>>>> BUGs::Small
+have the slow-execution cursor stop at more places like: inputwindow, inline functions
+
+if the inputwindow is canceled the returned value is empty. Yet we need to be a hybrid string ("") or number (0).
+
+when aborting execution dont say "Done." in the statusbar
+
+Maybe change the location of the Logo highlightstyles
+
+
+
+
+>>>>> BUGs::Unconfirmed
+annma can you go though the next 2 bugs and supply some more info bout them to me? tnx
+- The documentation of "not" seems wrong. Should it be a unary <-- annma
+ operator?
+- German examples are twice the same (ask Matthias) <--annma
+
+
+
+
+>>>>> WISHes::important
+cies> refactor the interpreter so it is easier to add new commands (using meta programming)
+
+
+
+
+>>>>> WISHes::less important but nice
+I saw the KD Executer talk on the aKademy... I (cies) want KD Executer tests for KTurtle to better manage the quality! [ maybe this is important, :) ]
+
+
+the default font can be a bit bigger and sans serif, and default the <tab> on 2 spaces
+
+
+have a context menu on right-click in the canvas to save the drawing (right-click -> Save Canvas). cies: then also put "print canvas" and "fullscreen" in there
+
+have the coords of the pixel under the mouse on the canvas in the statusbar
+
+
+CLI-file-selection (for mimetype eaz)
+
+
+cies: a fontchooser would be fun
+30/12/2003 annma: for the editor font? I can do it ---> default editor font should be bigger and sans serif
+04/01/2003 we'll see after the editor part is done
+
+
+
+
+
+>>>>> WISHes::still subject to discussion
+commands do not follow usual commands like forward is FD, reference: http://asijonline.net/ep/logo/logo_com.htm
+ -is there a logo standardisation? Compatibility is something that i (cies) would think is overdone. Logo is only used for a short moment, to learn programming; it will never produce real-world programs. So?
+
+
+Preview in konqueror: (from IRC discussion about the preview thing a mimetype and a litle kpart-previewer would not be too dificult wouldn't it
+<TSDgeos> you could put the widget you use in klogo in the kpart in read only mode
+<polux> yeah good idea, instead of including it as a katepart, making a kturtlepart)
+<cies> we could but what is the use of it? will it help to fulfill kturtles objectives?
+
+
+Translating data in the knewstuff.xml file: how would the translators access the file which is on the server?
+ - i dunno what's ment by this.. annma?
+
+
+
+After a conversiation with lypanov I came to the conclusion that making the executer 'statefull' is a very by thing! So I take the cheap approach using kapp->processEvents();... Maybe someday, later, I'll do it neatly -- the lypanov pointed out. FIXED
+
+
+
+annma - 29th December 2003
+about the resizing
+I think the canvas size should fill all the right side under the toolbar when KTurtle is started. When resizing the window with the mouse, the canvas grows bigger, everything resize smoothly (-> resizeEvent( QResizeEvent * )).
+You can leave the resizing option of the canvas in the Settings but only for having the canvas bigger. That would mean setting minimums in the config dialog.
+
+cies: Sorry i have to disagree, let me explain: a lot of logoscripts will be written on a certain canvas size, if the canvas is made bigger the script will give 'broken' output. I also dont have a way to update the 'wrapping' if a canvas is resized. IMHO the canvassize should be changed by a command, nl. canvassize x,y -- which works on my side of mother earth :-) IMHO all changes to the canvas MUST be done by commands and not by clicky-clicky... Putting the 'initial canvas size' in the settings window is only for the teatcher to setup all his computers.
+
+Sorry for beeing so inflexible... *Really* I am still open for discussion! :-) I just have developed a certain vision of KTurtle's future that is really hard to let go.
+(annma 30/12/2003 ok then, but the config option should be made clearer that the new canvas size will be next start)
+
+
+
+Annma: Idea from my daughter: have a Tux and a Konqui as alternate turtle for the cursor. I don't know if it's possible and if you like it ;)
+
+cies: That is a good plan! I have tux allready in my sprites dir (I'm a fan too!)... but there's one nice thing about the turtle: this animal is very regocnisable from above, and the head points in the direction of movement. Tux is more a front faced character, so nice would be to have an option to put the automatic turning off, and to have a different method to turn tux by command. [please note that i wont do any extra work on getting qt3.3 (needed for sprites), it comes when it comes]
+
+
+
+
+
+
+>>>> RECENTLY FIXED BUGs
+
+- settings->configure cauzes crash FIXED thanks to Martijn Klingens -> move "LanguageLabel = new QLabel(kcfg_LanguageComboBox..." down a few lines (after kcfg_LanguageComboBox is init'ed) BACKPORT
+
+- default language translation somehow doesnt work, it seems NO Logo language is selected at all FIXED
+- this also results in no examples FIXED
+
+
+- About the language: when user is set to fr (not fr_FR but fr like me being in Canada), the parsing does not work because Settings::LogoLanguage() is set to fr and NOT to fr_FR.
+ Syntax highlighting does not work for fr DONE annma
+
+- Default does not work in Language ComboBox -> I am not sure your use of KConfig XT is optimum here, Cies
+ and other bug: output: kturtle: desktopLanguage: fr:en_US
+ kturtle: defaultLanguage: en_US
+ Why is not default Language fr_FR? DONE annma 02/04/2004
+
+- open recent does not keep the files after quitting DONE annma 02/04/2004
+
+- crash on quitting after Opening files DONE annma 02/04/2004
+
+- cies: Make the interpreter (stolen from wsbasic.sf.net) (executer, parser, lexer, number and treenode) more native Qt. Right now they are a mixture of standard-CLI-C++ and Qt thingies (i put the Qt thingies there). I tried do that but i found that i'm not comfortable with the concept of streams -- which are used a lot in the interpreter. Especially streaming QString was an obstacle i couldnt take. DONE
+>>>>> after this is done we can also make the ()[],.""-configurable
+
+With long lines and wrapping the canvas can get into a endless loop -> 100%CPU, i tried a lot to fix this allready, maybe my solution needs some tuning :).
+Maybe i should just catch errors and break that endless loop :) FIXED!!! FINALLY
+
+
+
+
+cies: The KconfigXT issue: If an error like this
+"""
+ make[4]: Entering directory `/home/cies/kdenonbeta/kturtle/src'
+ ./kturtle.kcfg ./settings.kcfgc; ret=$?; \
+ if test "$ret" != 0; then rm -f settings.h ; exit $ret ; fi
+ /bin/sh: line 1: ./kturtle.kcfg: Permission denied
+ make[4]: *** [settings.h] Error 126
+"""
+happends when make'ing KTurtle form cvs one should change the first line of configure.in.in from:
+ #MIN_CONFIG(3.0)
+into:
+ #MIN_CONFIG(3.2)
+that will fix it :-) FIXED with KDE 3.3 (I suspect)
+
+
+
+- display the current command language in StatusBar? DONE apperently
+
+
+print command is buggy, examples: FIXED!
+ print 2004 + " before " + 25
+ from the manual should output
+ "2004 before 25"
+ according to the comment, but outputs
+ "2029"
+
+
+
+RESEARCH ON THE HELP PROBLEM
+
+then the help-kioslave is kdelibs/kdoctools
+
+little help needed: when i use konq to go
+"help:/kate?anchor=kate-part-selection-persistent" (which is the proper way to go
+there iirc) i get seemingly transferred to
+"help:/kate/index.html#kate-part-selection-persistent" but not to the anchor on that
+page -- it stays on the top of that page. When i enter the location bar again i get
+to the anchor. ---> shoud i file a bug, for with apps should i do that OR where is
+the code that handles this. Anyone? :)
+
+yet this works wel if i go straight to (in konq):
+help:/kate/index.html#kate-part-selection-persistent
+
+or if i use kdcop to set "help:/kate/index.html#kate-part-selection-persistent" in
+KHelpCenterIface-OpenUrl, than all works fine...
+
+yet this doesnt work
+dcop khelpcenter KHelpCenterIface openUrl "help:/kate/index.html#kate-part-selection-persistent", ""
+
+
+Im tryered of this... I can fix it; too much for me. Sorry
+
+
+in kdelibs/kdecore/kapp... :
+url = QString("help:/%1?anchor=%2").arg(appname).arg(anchor);
+and
+DCOPRef( "khelpcenter", "KHelpCenterIface" ).send( "openUrl", url, startup_id );
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+*************
+vi .cvsrc
+ cvs -z4 -q
+ diff -u3 -p
+ update -dP
+ checkout -P
+
+touch /home/cies/.cvspass
+
+export CVSROOT=:pserver:cies@cvs.kde.org:/home/kde
+cvs login
+
+mkdir kdecvs
+cd kdecvs/
+
+cvs co -l kdeedu
+cvs co kdeedu/kturtle
+cvs co -l kde-i18n
+cvs co -l kde-i18n/nl
+cvs co -l kde-i18n/nl/data
+cvs co -l kde-i18n/nl/data/kdeedu
+cvs co kde-i18n/nl/data/kdeedu/kturtle
+cvs co -l kdeedu/doc
+cvs co kdeedu/doc/kturtle
+
+cd kdeedu/
+cvs co admin
+make -f Makefile.cvs && ./configure
+
+cd ../kde-i18n
+cvs co admin
+make -f Makefile.cvs && ./configure
+
diff --git a/kturtle/data/Makefile.am b/kturtle/data/Makefile.am
new file mode 100644
index 00000000..2b523eda
--- /dev/null
+++ b/kturtle/data/Makefile.am
@@ -0,0 +1,12 @@
+txt_DATA = ad.logo curly.logo square.logo triangle.logo \
+arrow.logo flower.logo squaresss.logo trianglesss.logo \
+canvascolors.logo randomname.logo timestables.logo kde.logo
+txtdir = $(kde_datadir)/kturtle/examples/en_US
+
+xml_DATA = logohighlightstyle.en_US.xml
+xmldir = $(kde_datadir)/katepart/syntax
+
+keywords_DATA = logokeywords.en_US.xml
+keywordsdir = $(kde_datadir)/kturtle/data
+
+EXTRA_DIST = $(txt_DATA) $(xml_DATA) $(keywords_DATA)
diff --git a/kturtle/data/README.data b/kturtle/data/README.data
new file mode 100644
index 00000000..8bce26c0
--- /dev/null
+++ b/kturtle/data/README.data
@@ -0,0 +1,27 @@
+Dear Reader,
+
+this is your captain speaking...
+
+KTurtle currently has 3 types of 'data' (as we call it), namely:
+- examples (which are *.logo files)
+- logokeyword.*.xml files
+- logohighlightstyle.*.xml files
+
+In this kdeedu/kturtle/data directory we only store the 'en_US' (default) versions of this data.
+This means that here we store:
+- the English logo examples (a, hopefully ever growing, bunch of *.logo files)
+- the definition used to translate these examples in "logokeyword.en_US.xml"
+- and the accompanying highlight style in "logoheighlightstyle.en_US.xml"
+
+The makefile system makes sure every part gets installed to the right place.
+(if you dont believe me see the Makefile.am in this dir)
+
+For the other localizations a dir like this, containing these files for an other language, can be found in the kde-i18n module of kde.
+On kdecvs this is: kde-i18n/*/data/kdeedu/kturtle (for Dutch this would be: kde-i18n/nl/data/kdeedu/kturtle)
+
+If the localization of KTurtle to you favorite language does not exist yet, you might concider making it. In the documentation of KTurtle you can find some pointers on how to start. Also make sure to see the contents of the kdeedu/kturtle/scripts directory since it contains Rafael Beccar's nifty tranlaton perl scripts that can make translating KTurtle human resource friendly. If you face difficulty translating feel free to contact one of the KTrutle developers.
+
+
+Thanks for reading,
+
+Cies Breijs.
diff --git a/kturtle/data/ad.logo b/kturtle/data/ad.logo
new file mode 100644
index 00000000..8604d02f
--- /dev/null
+++ b/kturtle/data/ad.logo
@@ -0,0 +1,125 @@
+# KTurtle advertisement :)
+
+reset
+canvassize 400,190
+penwidth 10
+
+
+learn K x,y [
+ dir 0
+ go x,y
+ bw 75
+ go x+40,y
+ dir -140
+ fw 60
+ bw 10
+ tl 85
+ fw 50
+]
+
+learn T x,y [
+ go x,y
+ dir 90
+ fw 50
+ bw 25
+ dir 180
+ fw 70
+]
+
+learn u x,y [
+ go x,y
+ dir 180
+ fw 47
+ tl 45
+ fw 7
+ tl 45
+ fw 20
+ tl 45
+ fw 7
+ tl 45
+ fw 47
+]
+
+learn r x,y [
+ go x,y
+ dir 180
+ fw 55
+ go x,y+15
+ dir 45
+ penup
+ fw 4
+ pendown
+ fw 10
+ tr 45
+ fw 10
+]
+
+learn t x,y [
+ dir 180
+ go x,y
+ fw 67
+ tl 45
+ fw 7
+ tl 45
+ fw 10
+ go x,y+30
+ dir 90
+ fw 10
+]
+
+learn l x,y [
+ dir 180
+ go x,y
+ fw 77
+]
+
+learn e x,y [
+ go x,y+30
+ dir 90
+ fw 50
+ tl 90
+ fw 15
+ tl 45
+ fw 15
+ tl 45
+ fw 20
+ tl 45
+ fw 15
+ tl 45
+ fw 25
+ tl 45
+ fw 15
+ tl 45
+ fw 25
+]
+
+
+K 50,30
+T 108,35
+u 167,50
+r 220,50
+t 256,30
+l 289,30
+e 305,50
+
+go 12,115
+fontsize 25
+print "Educative Programming Environment"
+
+hide
+wait 1
+show
+
+go 120,145
+dir 80
+penwidth 5
+pencolor 255,0,0
+fw 130
+
+wait 0.5
+go 180,135
+print "play"
+
+go 238,160
+wait 0.5
+dir 0 \ No newline at end of file
diff --git a/kturtle/data/arrow.logo b/kturtle/data/arrow.logo
new file mode 100644
index 00000000..7eddd453
--- /dev/null
+++ b/kturtle/data/arrow.logo
@@ -0,0 +1,23 @@
+# draw a red arrow
+
+reset
+
+canvassize 200, 200
+canvascolor 0, 0, 0
+pencolor 255, 0, 0
+penwidth 5
+clear
+
+go 20,20
+direction 135
+
+forward 200
+turnleft 135
+forward 100
+turnleft 135
+forward 141
+turnleft 135
+forward 100
+turnleft 45
+
+go 40, 100
diff --git a/kturtle/data/canvascolors.logo b/kturtle/data/canvascolors.logo
new file mode 100644
index 00000000..709bf839
--- /dev/null
+++ b/kturtle/data/canvascolors.logo
@@ -0,0 +1,33 @@
+# color demo
+
+canvascolor 255,255,255
+hide
+
+repeat 5 [
+
+for c = 0 to 255 [
+ canvascolor 255-c,255,255
+]
+for c = 0 to 255 [
+ canvascolor 0,255-c,255
+]
+for c = 0 to 255 [
+ canvascolor c,0,255
+]
+for c = 0 to 255 [
+ canvascolor 255,c,255-c
+]
+for c = 0 to 255 [
+ canvascolor 255,255-c,0
+]
+for c = 0 to 255 [
+ canvascolor 255,0,c
+]
+for c = 0 to 255 [
+ canvascolor 255-c,0,255-c
+]
+for c = 0 to 255 [
+ canvascolor c,c,c
+]
+
+] \ No newline at end of file
diff --git a/kturtle/data/curly.logo b/kturtle/data/curly.logo
new file mode 100644
index 00000000..f24ebab3
--- /dev/null
+++ b/kturtle/data/curly.logo
@@ -0,0 +1,13 @@
+# curly.logo
+
+reset
+penup
+forward 50
+pendown
+
+repeat 4 [
+ for x = 1 to 100 [
+ forward 10
+ turnright 100 - x
+ ]
+] \ No newline at end of file
diff --git a/kturtle/data/flower.logo b/kturtle/data/flower.logo
new file mode 100644
index 00000000..04a26ff0
--- /dev/null
+++ b/kturtle/data/flower.logo
@@ -0,0 +1,26 @@
+# flower
+
+reset
+canvassize 170, 170
+canvascolor 255, 55, 140
+go 45, 120
+pencolor 160, 0, 255
+penwidth 3
+
+repeat 8 [
+ repeat 4 [
+ forward 20
+ turnright 30
+ ]
+ repeat 7 [
+ forward 10
+ turnright 15
+ ]
+ repeat 9 [
+ forward 3
+ turnright 10
+ ]
+]
+
+go 145, 145
+direction 0 \ No newline at end of file
diff --git a/kturtle/data/kde.logo b/kturtle/data/kde.logo
new file mode 100644
index 00000000..34c6f550
--- /dev/null
+++ b/kturtle/data/kde.logo
@@ -0,0 +1,120 @@
+# The KDE Logo for a KDE logo
+# interpreter.
+# Copyright 2005 Andy Teijelo <ateijelo@uh.cu>
+# GNU General Public License version 2
+
+reset
+canvassize 620, 480
+canvascolor 10,50,200
+pencolor 255,255,255
+penwidth 3
+
+go 294,280
+
+turnright 81
+forward 50
+turnleft 81
+forward 90
+turnright 145
+forward 120
+turnleft 72
+forward 55
+turnleft 108
+forward 116
+turnright 73
+forward 112
+turnleft 115
+forward 55
+turnleft 65
+forward 113
+turnright 142
+forward 92
+turnleft 96
+forward 50
+turnleft 84
+forward 209
+
+go 358,322
+
+direction -112.5
+
+repeat 4
+[
+ repeat 2
+ [
+ forward 6
+ turnright 3.75
+ ]
+
+ turnleft 63
+ forward 43
+ turnright 39
+ forward 3
+ turnright 39
+ forward 32
+ turnright 39
+ forward 3
+ turnright 39
+ forward 43
+ turnleft 63
+
+ repeat 2
+ [
+ forward 6
+ turnright 3.75
+ ]
+]
+
+forward 4
+turnright 112.5
+forward 25
+
+turnright 58
+repeat 21
+[
+ forward 13.5
+ turnleft 10
+]
+
+forward 9
+turnright 117
+forward 34
+turnleft 60
+forward 8
+turnright 62
+
+forward 25
+turnright 39
+forward 3
+turnright 39
+forward 32
+turnright 39
+forward 3
+turnright 39
+forward 43
+turnleft 63
+
+repeat 2
+[
+ forward 6
+ turnright 3.75
+]
+
+go 320,395
+direction 90
+
+penwidth 5
+
+repeat 4
+[
+ forward 160
+ repeat 6
+ [
+ forward 4
+ turnleft 15
+
+ ]
+ forward 160
+]
+
+go 320,440 \ No newline at end of file
diff --git a/kturtle/data/logohighlightstyle.en_US.xml b/kturtle/data/logohighlightstyle.en_US.xml
new file mode 100644
index 00000000..330fc496
--- /dev/null
+++ b/kturtle/data/logohighlightstyle.en_US.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE language>
+<!-- Logo syntax highlightning v0.2 by Cies Breijs -->
+<language name="en_US" version="0.2" kateversion="2.1" section="Logo" extensions="*.logo;*.lgo;*.LOGO;*.Logo" mimetype="text/x-logosrc;text/x-logo;application/x-logo" priority="9" casesensitive="0">
+
+
+<highlighting>
+ <list name="metafunctions">
+ <item> learn </item>
+ </list>
+
+ <list name="statements">
+ <item> run </item>
+ <item> clear </item>
+ <item> ccl </item>
+ <item> go </item>
+ <item> gox </item>
+ <item> gx </item>
+ <item> goy </item>
+ <item> gy </item>
+ <item> forward </item>
+ <item> fw </item>
+ <item> backward </item>
+ <item> bw </item>
+ <item> direction </item>
+ <item> dir </item>
+ <item> turnleft </item>
+ <item> tl </item>
+ <item> turnright </item>
+ <item> tr </item>
+ <item> center </item>
+ <item> penwidth </item>
+ <item> pw </item>
+ <item> penup </item>
+ <item> pu </item>
+ <item> pendown </item>
+ <item> pd </item>
+ <item> pencolor </item>
+ <item> pc </item>
+ <item> canvascolor </item>
+ <item> cc </item>
+ <item> canvassize </item>
+ <item> cs </item>
+ <item> show </item>
+ <item> ss </item>
+ <item> hide </item>
+ <item> sh </item>
+ <item> press </item>
+ <item> sp </item>
+ <item> change </item>
+ <item> sc </item>
+ <item> message </item>
+ <item> inputwindow </item>
+ <item> print </item>
+ <item> fonttype </item>
+ <item> fontsize </item>
+ <item> random </item>
+ <item> wrapon </item>
+ <item> wrapoff </item>
+ <item> reset </item>
+ </list>
+
+ <list name="controllers">
+ <item> while </item>
+ <item> foreach </item>
+ <item> in </item>
+ <item> for </item>
+ <item> to </item>
+ <item> do </item>
+ <item> repeat </item>
+ <item> rpt </item>
+ <item> if </item>
+ <item> else </item>
+ <item> return </item>
+ <item> break </item>
+ <item> wait </item>
+ </list>
+
+ <list name="boolops">
+ <item> and </item>
+ <item> or </item>
+ <item> not </item>
+ </list>
+
+ <contexts>
+ <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
+
+ <keyword attribute="MetaFunctions" String="metafunctions" context="#stay"/>
+ <keyword attribute="Statements" String="statements" context="#stay"/>
+ <keyword attribute="Execution Controllers" String="controllers" context="#stay"/>
+ <keyword attribute="Boolean Operators" String="boolops" context="#stay"/>
+
+ <RegExpr attribute="Expressers" String="([!=&gt;&lt;][=]|[&gt;&lt;])" context="#stay"/>
+ <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
+ <RegExpr attribute="Number" String="([0-9]+\.[0-9]*|\.[0-9]+)?|[0-9]*" context="#stay"/>
+ <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
+ <RegExpr attribute="Operator" String="[+*/\(\)-]" context="#stay"/>
+ <RegExpr attribute="Scopes" String="[\[\]]" context="#stay"/>
+ <DetectChar attribute="String" char="&quot;" context="String"/>
+ </context>
+
+ <context name="String" attribute="String" lineEndContext="#stay">
+ <HlCStringChar attribute="String" context="#stay"/>
+ <RegExpr attribute="Operator" String="%[a-zA-Z]" context="#stay"/>
+ <DetectChar attribute="String" char="&quot;" context="#pop"/>
+ </context>
+
+ </contexts>
+
+ <itemDatas>
+ <itemData name="Normal Text" defStyleNum="dsNormal"/>
+ <itemData name="Normal" defStyleNum="dsNormal"/>
+ <itemData name="MetaFunctions" defStyleNum="dsKeyword" color="#00bb00" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Statements" defStyleNum="dsKeyword" color="#006600" selColor="#ffffff" bold="0" italic="0"/>
+ <itemData name="Execution Controllers" defStyleNum="dsKeyword" color="#006600" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Expressers" defStyleNum="dsKeyword" color="#1e99cc" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Boolean Operators" defStyleNum="dsKeyword" color="#9922cc" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Scopes" defStyleNum="dsKeyword" color="#00bb00" selColor="#ffffff" bold="1" italic="0"/>
+ <itemData name="Number" defStyleNum="dsFloat" color="#0000ff" selColor="#00eeff" bold="0" italic="0"/>
+ <itemData name="Comment" defStyleNum="dsComment" color="#999922" selColor="#888888" bold="0" italic="0"/>
+ <itemData name="String" defStyleNum="dsString" color="#800000" selColor="#ffffff" bold="0" italic="0"/>
+ <itemData name="Raw String" defStyleNum="dsString" color="#800000" selColor="#ffffff" bold="0" italic="0"/>
+ <itemData name="Operator" defStyleNum="dsOthers" color="#888888" selColor="#ffffff" bold="0" italic="0"/>
+ </itemDatas>
+</highlighting>
+
+
+<general>
+
+ <folding indentationsensitive="0" />
+
+ <comments>
+ <comment name="singleLine" start="#" />
+ </comments>
+
+ <keywords casesensitive="0" />
+
+</general>
+
+
+</language>
diff --git a/kturtle/data/logokeywords.en_US.xml b/kturtle/data/logokeywords.en_US.xml
new file mode 100644
index 00000000..44001590
--- /dev/null
+++ b/kturtle/data/logokeywords.en_US.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0"?>
+<!DOCTYPE logokeywords>
+
+<logokeywords lang="en_US" ver="0.01">
+
+<!-- scope -->
+ <command name="begin">
+ <keyword>[</keyword>
+ </command>
+
+ <command name="end">
+ <keyword>]</keyword>
+ </command>
+
+
+
+<!--
+TO THE TRANSLATORS:
+
+Translate the terms between the KEYWORD tags to the appropriate term in your language.
+You might want to checkout what terms other Logo languages have chosen in the past (google is your friend).
+Make sure to see the scripts and the README file in the kdeedu/kturtle/scripts directory, they help you!
+If you did not read it allready: there is a chapter on how to translate KTurtle in the KTurtle documentation.
+
+Thanks for your efford, we love you!
+-->
+
+
+
+
+<!-- execution controllers -->
+ <command name="while">
+ <keyword>while</keyword>
+ </command>
+
+ <command name="if">
+ <keyword>if</keyword>
+ </command>
+
+ <command name="else">
+ <keyword>else</keyword>
+ </command>
+
+ <command name="for">
+ <keyword>for</keyword>
+ </command>
+
+ <command name="to">
+ <keyword>to</keyword>
+ </command>
+
+ <command name="return">
+ <keyword>return</keyword>
+ </command>
+
+ <command name="break">
+ <keyword>break</keyword>
+ </command>
+
+ <command name="foreach">
+ <keyword>foreach</keyword>
+ </command>
+
+ <command name="in">
+ <keyword>in</keyword>
+ </command>
+
+ <command name="do">
+ <keyword>do</keyword>
+ </command>
+
+ <command name="repeat">
+ <keyword>repeat</keyword>
+ <alias>rpt</alias>
+ </command>
+
+ <command name="wait">
+ <keyword>wait</keyword>
+ </command>
+
+
+<!-- boolean operators -->
+ <command name="and">
+ <keyword>and</keyword>
+ </command>
+
+ <command name="or">
+ <keyword>or</keyword>
+ </command>
+
+ <command name="not">
+ <keyword>not</keyword>
+ </command>
+
+
+<!-- the meta command -->
+ <command name="learn">
+ <keyword>learn</keyword>
+ </command>
+
+
+<!-- normal keywords -->
+ <command name="run">
+ <keyword>run</keyword>
+ </command>
+
+ <command name="clear">
+ <keyword>clear</keyword>
+ <alias>ccl</alias>
+ </command>
+
+ <command name="go">
+ <keyword>go</keyword>
+ </command>
+
+ <command name="gox">
+ <keyword>gox</keyword>
+ <alias>gx</alias>
+ </command>
+
+ <command name="goy">
+ <keyword>goy</keyword>
+ <alias>gy</alias>
+ </command>
+
+ <command name="forward">
+ <keyword>forward</keyword>
+ <alias>fw</alias>
+ </command>
+
+ <command name="backward">
+ <keyword>backward</keyword>
+ <alias>bw</alias>
+ </command>
+
+ <command name="direction">
+ <keyword>direction</keyword>
+ <alias>dir</alias>
+ </command>
+
+ <command name="turnleft">
+ <keyword>turnleft</keyword>
+ <alias>tl</alias>
+ </command>
+
+ <command name="turnright">
+ <keyword>turnright</keyword>
+ <alias>tr</alias>
+ </command>
+
+ <command name="center">
+ <keyword>center</keyword>
+ </command>
+
+ <command name="setpenwidth">
+ <keyword>penwidth</keyword>
+ <alias>pw</alias>
+ </command>
+
+ <command name="penup">
+ <keyword>penup</keyword>
+ <alias>pu</alias>
+ </command>
+
+ <command name="pendown">
+ <keyword>pendown</keyword>
+ <alias>pd</alias>
+ </command>
+
+ <command name="setfgcolor">
+ <keyword>pencolor</keyword>
+ <alias>pc</alias>
+ </command>
+
+ <command name="setbgcolor">
+ <keyword>canvascolor</keyword>
+ <alias>cc</alias>
+ </command>
+
+ <command name="resizecanvas">
+ <keyword>canvassize</keyword>
+ <alias>cs</alias>
+ </command>
+
+ <command name="spriteshow">
+ <keyword>show</keyword>
+ <alias>ss</alias>
+ </command>
+
+ <command name="spritehide">
+ <keyword>hide</keyword>
+ <alias>sh</alias>
+ </command>
+
+ <command name="spritepress">
+ <keyword>press</keyword>
+ <alias>sp</alias>
+ </command>
+
+ <command name="spritechange">
+ <keyword>change</keyword>
+ <alias>sc</alias>
+ </command>
+
+ <command name="message">
+ <keyword>message</keyword>
+ </command>
+
+ <command name="inputwindow">
+ <keyword>inputwindow</keyword>
+ </command>
+
+ <command name="print">
+ <keyword>print</keyword>
+ </command>
+
+ <command name="fonttype">
+ <keyword>fonttype</keyword>
+ </command>
+
+ <command name="fontsize">
+ <keyword>fontsize</keyword>
+ </command>
+
+ <command name="random">
+ <keyword>random</keyword>
+ </command>
+
+ <command name="wrapon">
+ <keyword>wrapon</keyword>
+ </command>
+
+ <command name="wrapoff">
+ <keyword>wrapoff</keyword>
+ </command>
+
+ <command name="reset">
+ <keyword>reset</keyword>
+ </command>
+
+</logokeywords>
diff --git a/kturtle/data/randomname.logo b/kturtle/data/randomname.logo
new file mode 100644
index 00000000..db6b9e1e
--- /dev/null
+++ b/kturtle/data/randomname.logo
@@ -0,0 +1,18 @@
+# prints your name at random
+
+reset
+canvassize 255,255
+hide
+
+name = inputwindow "What's your name?"
+
+repeat 50 [
+ x = random 0, 255
+ y = random 0, 255
+ s = random 10, 51
+
+ go x, y
+ fontsize s
+ pencolor x,y,s*5
+ print name
+] \ No newline at end of file
diff --git a/kturtle/data/square.logo b/kturtle/data/square.logo
new file mode 100644
index 00000000..9c90ef07
--- /dev/null
+++ b/kturtle/data/square.logo
@@ -0,0 +1,6 @@
+# draw a square
+
+repeat 4 [
+ forward 100
+ turnleft 90
+]
diff --git a/kturtle/data/squaresss.logo b/kturtle/data/squaresss.logo
new file mode 100644
index 00000000..e3700b8c
--- /dev/null
+++ b/kturtle/data/squaresss.logo
@@ -0,0 +1,22 @@
+# draw many squares
+
+learn square X [
+ repeat 4 [
+ forward X
+ turnleft 90
+ ]
+]
+
+reset
+canvassize 400, 400
+go 150,200
+penwidth 5
+hide
+
+repeat 12 [
+ penup
+ forward 30
+ pendown
+ square 80
+ turnright 30
+]
diff --git a/kturtle/data/timestables.logo b/kturtle/data/timestables.logo
new file mode 100644
index 00000000..9c2cc3e7
--- /dev/null
+++ b/kturtle/data/timestables.logo
@@ -0,0 +1,15 @@
+# print times-tables
+
+reset
+canvassize 300,250
+hide
+penup
+go 10, 0
+
+n = inputwindow "Enter the number for which i'll print the times-table"
+
+for x = 0 to 10 [
+ backward 20
+ r = x * n
+ print x," * ",n," = ",r
+]
diff --git a/kturtle/data/triangle.logo b/kturtle/data/triangle.logo
new file mode 100644
index 00000000..605cd7ef
--- /dev/null
+++ b/kturtle/data/triangle.logo
@@ -0,0 +1,6 @@
+# draw a triangle
+
+repeat 3 [
+ forward 100
+ turnleft 120
+]
diff --git a/kturtle/data/trianglesss.logo b/kturtle/data/trianglesss.logo
new file mode 100644
index 00000000..99fa65a0
--- /dev/null
+++ b/kturtle/data/trianglesss.logo
@@ -0,0 +1,24 @@
+# draw triangle wheels
+
+reset
+
+learn triangle X [
+ repeat 3 [
+ forward X
+ turnleft 120
+ ]
+]
+
+for r = 1 to 30 [
+ clear
+ repeat 18 [
+ triangle r*r*5
+ tr 20
+ ]
+ wait 1
+]
+
+wait 3
+clear
+
+print " I'm tired..."
diff --git a/kturtle/file.txt b/kturtle/file.txt
new file mode 100644
index 00000000..99893afd
--- /dev/null
+++ b/kturtle/file.txt
@@ -0,0 +1,34 @@
+Reading Package Lists...
+Building Dependency Tree...
+Correcting dependencies... Done
+The following extra packages will be installed:
+ alsa-headers libasound2-dev libaudio-dev libaudiofile-dev libfontconfig1-dev
+ libfreetype6-dev libglib2.0-dev libjpeg62-dev liblcms1-dev libmad0-dev
+ libogg-dev libpng12-dev libqt3-headers libvorbis-dev libxcursor-dev
+ pkg-config qt3-dev-tools xlibmesa3-gl xlibmesa3-glu zlib1g-dev
+Suggested packages:
+ libasound2-doc libglib2.0-doc libgnome-dev libglide3
+Recommended packages:
+ libqt3-mt-dev libqt3-dev
+The following packages will be REMOVED:
+ arts gideon gideon-data gideon-plugins kaddressbook kalarm kalarmd kandy
+ kappfinder karm kate kcontrol kde-cvs-snapshot kdeartwork kdeartwork-misc
+ kdeartwork-style kdeartwork-theme-desktop kdeartwork-theme-window kdebase
+ kdebase-bin kdebase-data kdebase-kio-plugins kdelibs kdelibs-bin kdelibs-data
+ kdelibs4 kdelibs4-doc kdepim kdepim-kfile-plugins kdepim-libs kdeprint
+ kdesktop kdm kfind kgpgcertmanager khelpcenter kicker kitchensync klipper
+ kmail kmailcvt kmenuedit knode knotes konqueror konqueror-nsplugins konsole
+ kontact korganizer korn kpager kpersonalizer kpilot kscreensaver ksmserver
+ ksplash ksync ksysguard ksysguardd ktip ktnef kwin libarts1 libarts1-dev
+ libartsc0 libkcal2 libkdenetwork2 libkgantt0 libkonq4 libmimelib1
+ x-window-system-core xlibmesa-dri xlibmesa-gl xlibmesa-glu
+The following NEW packages will be installed:
+ alsa-headers libasound2-dev libaudio-dev libaudiofile-dev libfontconfig1-dev
+ libfreetype6-dev libglib2.0-dev libjpeg62-dev liblcms1-dev libmad0-dev
+ libogg-dev libpng12-dev libqt3-headers libvorbis-dev libxcursor-dev
+ pkg-config qt3-dev-tools xlibmesa3-gl xlibmesa3-glu zlib1g-dev
+0 upgraded, 20 newly installed, 74 to remove and 9 not upgraded.
+1 not fully installed or removed.
+Need to get 10.1MB of archives.
+After unpacking 284MB disk space will be freed.
+Do you want to continue? [Y/n] Abort.
diff --git a/kturtle/kturtle.kdevelop b/kturtle/kturtle.kdevelop
new file mode 100644
index 00000000..6cd625dd
--- /dev/null
+++ b/kturtle/kturtle.kdevelop
@@ -0,0 +1,160 @@
+<?xml version = '1.0'?>
+<kdevelop>
+ <general>
+ <author>Cies Breijs</author>
+ <email>cies # showroommama ! nl</email>
+ <version>0.01</version>
+ <projectmanagement>KDevKDEAutoProject</projectmanagement>
+ <primarylanguage>C++</primarylanguage>
+ <keywords>
+ <keyword>C++</keyword>
+ <keyword>Code</keyword>
+ <keyword>Qt</keyword>
+ <keyword>KDE</keyword>
+ </keywords>
+ <projectdirectory>.</projectdirectory>
+ <absoluteprojectpath>false</absoluteprojectpath>
+ <description/>
+ <ignoreparts/>
+ <secondaryLanguages/>
+ </general>
+ <kdevautoproject>
+ <general>
+ <activetarget>src/kturtle</activetarget>
+ <useconfiguration>default</useconfiguration>
+ </general>
+ <run>
+ <mainprogram>src/kturtle</mainprogram>
+ <directoryradio>executable</directoryradio>
+ <customdirectory>/</customdirectory>
+ <programargs/>
+ <terminal>false</terminal>
+ <autocompile>true</autocompile>
+ <envvars/>
+ </run>
+ <configurations>
+ <optimized>
+ <builddir>optimized</builddir>
+ <ccompiler>GccOptions</ccompiler>
+ <cxxcompiler>GppOptions</cxxcompiler>
+ <f77compiler>G77Options</f77compiler>
+ <cxxflags>-O2 -g0</cxxflags>
+ </optimized>
+ <debug>
+ <configargs>--enable-debug=full</configargs>
+ <builddir>debug</builddir>
+ <ccompiler>GccOptions</ccompiler>
+ <cxxcompiler>GppOptions</cxxcompiler>
+ <f77compiler>G77Options</f77compiler>
+ <cxxflags>-O0 -g3</cxxflags>
+ </debug>
+ </configurations>
+ <make>
+ <envvars>
+ <envvar value="1" name="WANT_AUTOCONF_2_5" />
+ <envvar value="1" name="WANT_AUTOMAKE_1_6" />
+ </envvars>
+ <abortonerror>false</abortonerror>
+ <numberofjobs>1</numberofjobs>
+ <dontact>false</dontact>
+ <makebin/>
+ </make>
+ </kdevautoproject>
+ <kdevfileview>
+ <groups>
+ <group pattern="*.cpp;*.cxx;*.h" name="Sources" />
+ <group pattern="*.ui" name="User Interface" />
+ <group pattern="*.png" name="Icons" />
+ <group pattern="*.po;*.ts" name="Translations" />
+ <group pattern="*" name="Others" />
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ <hidenonlocation>false</hidenonlocation>
+ </groups>
+ <tree>
+ <hidepatterns></hidepatterns>
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ <showvcsfields>true</showvcsfields>
+ </tree>
+ </kdevfileview>
+ <kdevdoctreeview>
+ <ignoretocs>
+ <toc>gtk</toc>
+ <toc>gnustep</toc>
+ <toc>python</toc>
+ <toc>php</toc>
+ <toc>perl</toc>
+ </ignoretocs>
+ <projectdoc>
+ <userdocDir>/home/cies/src/kturtle/html/</userdocDir>
+ <apidocDir>/home/cies/src/kturtle/html/</apidocDir>
+ </projectdoc>
+ <ignoreqt_xml/>
+ <ignoredoxygen/>
+ <ignorekdocs/>
+ <ignoredevhelp/>
+ </kdevdoctreeview>
+ <kdevdebugger>
+ <general>
+ <dbgshell>libtool</dbgshell>
+ <programargs/>
+ <gdbpath/>
+ <configGdbScript/>
+ <runShellScript/>
+ <runGdbScript/>
+ <breakonloadinglibs>true</breakonloadinglibs>
+ <separatetty>false</separatetty>
+ <floatingtoolbar>false</floatingtoolbar>
+ </general>
+ <display>
+ <staticmembers>false</staticmembers>
+ <demanglenames>true</demanglenames>
+ </display>
+ </kdevdebugger>
+ <kdevfilecreate>
+ <filetypes/>
+ <useglobaltypes>
+ <type ext="ui" />
+ <type ext="cpp" />
+ <type ext="h" />
+ </useglobaltypes>
+ </kdevfilecreate>
+ <kdevcvs>
+ <cvsoptions>-z3 -d:ext:cies@cvs.sourceforge.net:/cvsroot/kturtle co kturtle </cvsoptions>
+ <commitoptions/>
+ <addoptions/>
+ <logoptions/>
+ <updateoptions>-dP</updateoptions>
+ <removeoptions>-f</removeoptions>
+ <revertoptions>-C -d -P</revertoptions>
+ <diffoptions>-u3 -p</diffoptions>
+ <rshoptions>ssh</rshoptions>
+ </kdevcvs>
+ <kdevcvsservice>
+ <recursivewhenupdate>true</recursivewhenupdate>
+ <prunedirswhenupdate>true</prunedirswhenupdate>
+ <createdirswhenupdate>true</createdirswhenupdate>
+ <recursivewhencommitremove>true</recursivewhencommitremove>
+ <revertoptions>-C</revertoptions>
+ </kdevcvsservice>
+ <kdevcppsupport>
+ <references/>
+ <codecompletion>
+ <includeGlobalFunctions>true</includeGlobalFunctions>
+ <includeTypes>true</includeTypes>
+ <includeEnums>true</includeEnums>
+ <includeTypedefs>false</includeTypedefs>
+ <automaticCodeCompletion>true</automaticCodeCompletion>
+ <automaticArgumentsHint>true</automaticArgumentsHint>
+ <automaticHeaderCompletion>true</automaticHeaderCompletion>
+ <codeCompletionDelay>250</codeCompletionDelay>
+ <argumentsHintDelay>400</argumentsHintDelay>
+ <headerCompletionDelay>250</headerCompletionDelay>
+ </codecompletion>
+ </kdevcppsupport>
+ <cppsupportpart>
+ <filetemplates>
+ <interfacesuffix>.h</interfacesuffix>
+ <implementationsuffix>.cpp</implementationsuffix>
+ </filetemplates>
+ </cppsupportpart>
+</kdevelop>
diff --git a/kturtle/kturtle.kdevses b/kturtle/kturtle.kdevses
new file mode 100644
index 00000000..9eb9c8b8
--- /dev/null
+++ b/kturtle/kturtle.kdevses
@@ -0,0 +1,65 @@
+<?xml version = '1.0' encoding = 'UTF-8'?>
+<!DOCTYPE KDevPrjSession>
+<KDevPrjSession>
+ <DocsAndViews NumberOfDocuments="16" >
+ <Doc0 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/TODO" >
+ <View0 Type="Source" />
+ </Doc0>
+ <Doc1 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/main.cpp" >
+ <View0 Type="Source" />
+ </Doc1>
+ <Doc2 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/kturtle.h" >
+ <View0 Type="Source" />
+ </Doc2>
+ <Doc3 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/kturtle.cpp" >
+ <View0 Type="Source" />
+ </Doc3>
+ <Doc4 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/dialogs.h" >
+ <View0 Type="Source" />
+ </Doc4>
+ <Doc5 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/dialogs.cpp" >
+ <View0 Type="Source" />
+ </Doc5>
+ <Doc6 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/executer.cpp" >
+ <View0 Type="Source" />
+ </Doc6>
+ <Doc7 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/translate.h" >
+ <View0 line="0" Type="Source" />
+ </Doc7>
+ <Doc8 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/lexer.cpp" >
+ <View0 line="408" Type="Source" />
+ </Doc8>
+ <Doc9 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/translate.cpp" >
+ <View0 line="104" Type="Source" />
+ </Doc9>
+ <Doc10 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/canvas.cpp" >
+ <View0 line="390" Type="Source" />
+ </Doc10>
+ <Doc11 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/parser.cpp" >
+ <View0 line="1052" Type="Source" />
+ </Doc11>
+ <Doc12 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/settings.cpp" >
+ <View0 line="50" Type="Source" />
+ </Doc12>
+ <Doc13 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/token.cpp" >
+ <View0 line="0" Type="Source" />
+ </Doc13>
+ <Doc14 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/treenode.cpp" >
+ <View0 line="219" Type="Source" />
+ </Doc14>
+ <Doc15 NumberOfViews="1" URL="file:/home/cies/kdecvs/kdeedu/kturtle/src/value.cpp" >
+ <View0 line="247" Type="Source" />
+ </Doc15>
+ </DocsAndViews>
+ <pluginList>
+ <kdevbookmarks>
+ <bookmarks/>
+ </kdevbookmarks>
+ <kdevsubversion>
+ <subversion recurseresolve="1" recurserelocate="1" recursemerge="1" recursecommit="1" base="" recursepropget="1" recurseswitch="1" recurseupdate="1" recursepropset="1" recursediff="1" recurserevert="1" forcemove="1" recursecheckout="1" forceremove="1" recurseadd="1" recurseproplist="1" forcemerge="1" />
+ </kdevsubversion>
+ <kdevdebugger>
+ <breakpointList/>
+ </kdevdebugger>
+ </pluginList>
+</KDevPrjSession>
diff --git a/kturtle/kturtle.lsm b/kturtle/kturtle.lsm
new file mode 100644
index 00000000..dd56c0ca
--- /dev/null
+++ b/kturtle/kturtle.lsm
@@ -0,0 +1,16 @@
+Begin3
+Title: KTurtle -- Some description
+Version: 0.01
+Entered-date:
+Description:
+Keywords: KDE Qt
+Author: Cies Breijs <cies # showroommama ! nl>
+Maintained-by: Cies Breijs <cies # showroommama ! nl>
+Home-page:
+Alternate-site:
+Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils
+ xxxxxx kturtle-0.01.tar.gz
+ xxx kturtle-0.01.lsm
+Platform: Linux. Needs KDE
+Copying-policy: GPL
+End
diff --git a/kturtle/scripts/README.scripts b/kturtle/scripts/README.scripts
new file mode 100644
index 00000000..2df17a38
--- /dev/null
+++ b/kturtle/scripts/README.scripts
@@ -0,0 +1,56 @@
+kturtle/scripts/
+this directory of the source version KTurtle contains two scripts that will make translating of KTurtle to other langauges much easier.
+
+When translating KTurtle more than just the usual 'documantation and strings' have to be translated, namely:
+- the examples (which are *.logo files),
+- the logokeyword.*.xml files, and
+- the logohighlightstyle.*.xml files.
+
+These files are called data files, and their English originals can be found in kdeedu/kturtle/data.
+For more information on these files and their translation read:
+kdeedu/kturtle/data/README.data
+
+In this directory you find Rafael Beccar's nifty tranlaton perl scripts that can make translating KTurtle human resourcefriendly.
+
+This is how these scripts work:
+
+But only logokeywords.YOURLANGCODE.xml needs to be under current directory..
+
+If everything is working fine the general process is something like:
+
+
+1. MANUALLY TRANSLATE THE KEYWORD
+Copy the logokeywords.en_US.xml file (from kdeedu/kturtle/data) to the kturtle directory in your branch of the kde-i18n module (for Dutch this would be: kde-i18n/nl/data/kdeedu/kturtle). Translate the file, and change the name to:
+logokeywords.YOURLANGCODE.xml
+
+
+2. AUTOMAGICALLY GENERATE THE HIGHLIGHTSTYLE FOR YOUR LANGUAGE
+- Copy logokeywords.YOURLANGCODE.xml to kdeedu/kturtle/scripts
+- change directory to kdeedu/kturtle/sripts, and run:
+./i18n_highlighting.pl logokeywords.YOURLANGCODE.xml
+- Now you have a translated logohighlightstyle.YOURLANGCODE.xml under current directory (kdeedu/kturtle/scripts)
+
+
+3. AUTOMAGICALLY GENERATE NEARLY FINISHED TRANSLATIONS OF THE EXAMPLES
+- change directory to kdeedu/kturtle/scripts, and run:
+./i18n_examples.pl logokeywords.YOURLANGCODE.xml
+- the translated examples can then be found in current directory. Some manual adjusments are
+needed, namely: the sings in the code and the comments
+
+
+4. LAST BUT NOT LEAST!!! CHECK IF EVERYTHING WORKS
+- move all the generated files to the kturtle directory in your branch of the kde-i18n module
+- check if it installs correctly
+- check if the fresh logo examples in your language run when KTurtle is set to your language (see the Settings)
+
+
+Please report BUGs when it doesnt work (bugs.kde.org)!
+
+Thanks for the efford, we love you!
+
+
+
+
+
+
+
diff --git a/kturtle/scripts/i18n_examples.pl b/kturtle/scripts/i18n_examples.pl
new file mode 100755
index 00000000..36115ea8
--- /dev/null
+++ b/kturtle/scripts/i18n_examples.pl
@@ -0,0 +1,214 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004-2005 Rafael Beccar <rafael.beccar ! kdemail.net>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General
+# Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# Author: Rafael Beccar <rafael.beccar ! kdemail.net>
+#
+# Bs.As. November 2004
+#
+# Automagically generate localized KTurtle logo code.
+#
+# Usage: ./i18n_examples.pl logokeywords.YOURLANGCODE.xml
+#
+# e.g.:
+# $./i18n_examples.pl logokeywords.es.xml
+#
+# arrow.logo -> arrow.es.LOGO
+# canvascolors.logo -> canvascolors.es.LOGO
+# curly.logo -> curly.es.LOGO
+#
+# NOTES:
+# - You'll need logokeywords.YOURLANGCODE.xml under kturtle/scripts
+# - Commented lines, variable names, and strings like
+# "What's your name?" must be translated by hand.
+# - You might want to rename the resulting files to something
+# into your own language e.g. arrow.es.LOGO to flecha.LOGO
+# - Please, if the script is not working for you report it to
+# KDE-Edu mailing list.
+#
+
+
+use strict;
+
+my @en_commands;
+my $langcode;
+my @mylang_commands;
+my %commands;
+my $i;
+my @examples= glob "../data/*.logo";
+my $filename;
+my $line;
+
+
+#Get the langcode we are translating to
+$_ = $ARGV[0];
+if (/logokeywords.(\w+).xml/){
+ $langcode = $1;
+ }
+
+#Get en_US commands
+open EN_COMMANDS, "<../data/logokeywords.en_US.xml"
+ or die "Cannot open logokeywords.en_US.xml";
+$i=0;
+while (<EN_COMMANDS>){
+ if (/<keyword>(.*)<\/keyword>/){
+ $en_commands[$i]=$1;
+ $i++;
+ }
+ elsif (/<alias>(.*)<\/alias>/){
+ $en_commands[$i]=$1;
+ $i++;
+ }
+ }
+
+close EN_COMMANDS;
+
+#Get commands for the given language
+$i=0;
+while(<>){
+ if (/<keyword>(.*)<\/keyword>/){
+ $mylang_commands[$i]=$1;
+ $commands{$en_commands[$i]}=$mylang_commands[$i];
+ $i++;
+ }
+ elsif (/<alias>(.*)<\/alias>/){
+ $mylang_commands[$i]=$1;
+ $commands{$en_commands[$i]}=$mylang_commands[$i];
+ $i++;
+ }
+
+ }
+
+
+#Remove brackets from @en_commands (they aren't needed here)
+#Brackets will be managed in a different way later
+shift @en_commands;
+shift @en_commands;
+
+
+#Parse *.logo and generate the homologous for the given language
+foreach (@examples){
+ if (m%^../data/(\w+).logo%){$filename="$1".".$langcode."."logo";}
+ else{die "Error: Check if you have ../data/*.logo files";}
+ printf "\n%-25s > ./%s \n", $_, $filename;
+ open EXAMPLE,"<$_"
+ or die "Cannot open $_ \n";
+ while (<EXAMPLE>){
+ #Manage comments (they do not get translated)
+ if (/^#(.*)/){
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "#$1\n";
+ select STDOUT;}
+ #Manage tabulated "for .. to .." lines
+ elsif (/(^\s+)(\bfor\b)(.*)(\bto\b)/){
+ chomp ($line = "$1$commands{$2}$3$commands{$4}$'");
+ open TRANSLATION, ">>$filename";
+ select TRANSLATION;
+ print "$line \n";
+ select STDOUT;}
+ #Manage tabulated brackets
+ elsif (/(^\s+)(\p{IsPunct})/){
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$1$2\n";
+ select STDOUT;}
+ #Manage any other tabulated line
+ elsif (/(^\s+)(\w+)/){
+ my $tab=$1;
+ if ($commands{$2}){
+ chomp ($line = "$commands{$2}$'");
+ }
+ elsif (/([=])(\s+)(\w+)/){
+ if ($commands{$3}){
+ $tab="";
+ chomp ($line = "$`$1$2$commands{$3}$'");
+ }
+ }
+ elsif (/([=])(\w+)/){
+ if ($commands{$2}){
+ chomp ($line = "$`$1$commands{$2}$'");
+ }
+ }
+ else
+ {
+ chomp ($line = "$2$'");
+ }
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$tab$line\n";
+ select STDOUT;}
+ #Manage "for .. to .." lines
+ elsif (/(^\bfor\b)(.*)(\bto\b)/){
+ chomp (my $line = "$commands{$1}$2$commands{$3}$'");
+ open TRANSLATION, ">>$filename";
+ select TRANSLATION;
+ print "$line\n";
+ select STDOUT;}
+ #Manage any other line of code
+ elsif (/(^\w+)/){
+ if ($commands{$&}){
+ chomp ($line = "$commands{$&}$'");
+ }
+ elsif (/([=])(\s+)(\w+)/){
+ if ($commands{$3}){
+ chomp ($line = "$`$1$2$commands{$3}$'");
+ }
+ }
+ elsif (/([=])(\w+)/){
+ if ($commands{$2}){
+ chomp ($line = "$`$1$commands{$2}$'");
+ }
+ }
+ else{
+ chomp ($line = "$1$'");
+ }
+ open TRANSLATION, ">>$filename";
+ select TRANSLATION;
+ print "$line \n";
+ select STDOUT;
+ }
+ #Manage brackets
+ elsif (/\p{IsPunct}/){
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$&\n";
+ select STDOUT;}
+ #Manage empty lines
+ elsif (/^\s+/){
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "\n";
+ select STDOUT;}
+
+ }
+ }
+
+print <<EOF;
+
+The translation of KTurtle examples is almost DONE...
+You will need to translate the following by hand:
+1) Commented lines,
+2) Variable names (if any of them is named in english or represents a reserved word in your language),
+3) Strings like "What's your name?"
+4) File names
+
+Thanks a lot!
+
+EOF
+
diff --git a/kturtle/scripts/i18n_highlighting.pl b/kturtle/scripts/i18n_highlighting.pl
new file mode 100755
index 00000000..463c364a
--- /dev/null
+++ b/kturtle/scripts/i18n_highlighting.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004 Rafael Beccar <rafael.beccar ! kdemail.net>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 of the GNU General
+# Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# Author: Rafael Beccar <rafael.beccar ! kdemail.net>
+#
+# Bs.As. November 2004
+#
+# Automagically gen. localized highlighting for KTurtle commands
+#
+# Usage:
+# ./i18n_highlighting.pl logokeywords.YOURLANG.xml
+#
+# E.g.
+# ./i18n_highlighting.pl logokeywords.es.xml
+#
+# NOTES:
+# - You'll need logokeywords.YOURLANGCODE.xml under kturtle/scripts
+#
+# - The script search for logokeywords.en_US.xml under ../data/
+# and writes the resulting files under current directory
+#
+
+
+use strict;
+
+my $langcode;
+my @en_commands;
+my @mylang_commands;
+my %commands;
+my $i;
+my $line;
+
+#Give message if no parameter passed
+if (! $ARGV[0]){
+ die "Usage:\n ./i18n_highlighting.pl logokeywords.YOURLANG.xml";}
+
+#Get the langcode we are translating to
+$_ = $ARGV[0];
+if (/logokeywords.(\w+).xml/){
+ $langcode = $1;
+ }
+
+#Get en_US commands
+open EN_COMMANDS, "<../data/logokeywords.en_US.xml"
+ or die "Cannot open ../data/logokeywords.en_US.xml";
+$i=0;
+while (<EN_COMMANDS>){
+ if (/<keyword>(.*)<\/keyword>/){
+ $en_commands[$i]=$1;
+ $i++;
+ }
+ elsif (/<alias>(.*)<\/alias>/){
+ $en_commands[$i]=$1;
+ $i++;
+ }
+ }
+
+close EN_COMMANDS;
+
+#Get commands for the given language
+$i=0;
+while(<>){
+ if (/<keyword>(.*)<\/keyword>/){
+ $mylang_commands[$i]=$1;
+ $commands{$en_commands[$i]}=$mylang_commands[$i];
+ $i++;
+ }
+ elsif (/<alias>(.*)<\/alias>/){
+ $mylang_commands[$i]=$1;
+ $commands{$en_commands[$i]}=$mylang_commands[$i];
+ $i++;
+ }
+ }
+
+#Remove brackets from @en_commands (they are not needed here)
+#Brackets will be managed in a different way later
+shift @en_commands;
+shift @en_commands;
+
+#Set destination
+my $filename = "logohighlightstyle.${langcode}.xml";
+
+
+#Parse logohighlightstyle.en_US.xml and generate the homologous for the given language
+open HIGHLIGHT,"<../data/logohighlightstyle.en_US.xml"
+ or die "Cannot open $_ \n";
+while (<HIGHLIGHT>){
+ #Manage language tag
+ if (m%(en_US)%){
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$`${langcode}$'";
+ select STDOUT;}
+ #Manage translatable lines
+ elsif (m%<item> (\w+) </item>%){
+ if ($commands{$1}){
+ $line = "\t<item> $commands{$1} </item>";}
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$line \n";
+ select STDOUT;
+ }
+ #Manage not translatable lines
+ else{
+ open TRANSLATION,">>$filename";
+ select TRANSLATION;
+ print "$_";}
+ select STDOUT;
+ }
+close TRANSLATION;
+print "DONE... The translated file is:\n $filename \n";
+
+
diff --git a/kturtle/src/Makefile.am b/kturtle/src/Makefile.am
new file mode 100644
index 00000000..7ed55e4d
--- /dev/null
+++ b/kturtle/src/Makefile.am
@@ -0,0 +1,37 @@
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes)
+
+SUBDIRS = pics
+
+# added from kjots
+AM_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+kturtle_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+kturtle_LDADD = $(LIB_KDEUI) $(LIB_KIO) $(LIB_KDEPRINT) $(LIB_KPARTS) -lkatepartinterfaces
+
+KDE_ICON = kturtle
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+bin_PROGRAMS = kturtle
+
+# the application source, library search path, and link libraries
+kturtle_SOURCES = main.cpp kturtle.cpp canvas.cpp dialogs.cpp value.cpp lexer.cpp parser.cpp executer.cpp treenode.cpp token.cpp translate.cpp settings.kcfgc
+
+# let automoc handle all the meta source files (moc)
+kturtle_METASOURCES = AUTO
+
+# these are the headers for your project
+noinst_HEADERS = kturtle.h canvas.h dialogs.cpp value.h lexer.h parser.h executer.h treenode.h token.h translate.h
+
+kde_kcfg_DATA = kturtle.kcfg
+
+# this is where the shell's XML-GUI resource file goes
+shellrcdir = $(kde_datadir)/kturtle
+shellrc_DATA = kturtleui.rc
+
+# place KTurtle in the start menu under Miscellanous
+xdg_apps_DATA = kturtle.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kturtle.pot
diff --git a/kturtle/src/canvas.cpp b/kturtle/src/canvas.cpp
new file mode 100644
index 00000000..871c1614
--- /dev/null
+++ b/kturtle/src/canvas.cpp
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2003 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+
+// Note on this file:
+// It contains 200 lines of code just to make sure very long line are drawn correctly
+// till a certain extent... Beyond that extent the code just cuts the crap, since use user
+// it then probably not doing anything usefull anymore; so he she will not notice the code
+// is cheating a bit in order to prevent CPU hogging.
+// If anyone has a good fix for this problem, than please test it with these logo scripts:
+
+// # bastard script 1
+// reset
+// canvassize 350,348
+// center
+// for x = 1 to 255 [
+// fw x
+// tr x / 65
+// ]
+
+// # bastard script 2
+// reset
+// canvassize 350,350
+// center
+// for x = 1 to 255 [
+// fw x*x
+// tr x
+// ]
+
+// Thanks for looking at the code of KTurtle!
+
+// Updated 21.10.2004 by Kiril Jovchev
+// -- Changed that position is kept in double values.
+// This makes accuracy higher.
+
+
+// BEGIN includes, defines and constants
+
+#include <cmath>
+
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "settings.h"
+#include "canvas.h"
+
+
+// this function is used in executer and canvas:
+#define ROUND2INT(x) ( (x) >= 0 ? (int)( (x) + .5 ) : (int)( (x) - .5 ) )
+
+const double PI = 3.14159265358979323846;
+const double DEG2RAD = 3.14159265358979323846/180;
+
+// END
+
+
+
+// BEGIN public methods
+
+Canvas::Canvas(QWidget *parent, const char *name) : QCanvasView(0, parent, name)
+{
+ // Create a new canvas for this view
+ canvas = new QCanvas(parent);
+ canvas->setAdvancePeriod(250); // refresh-rate in [ms]
+
+ // set initial values
+ initValues();
+
+ // at last we assign the canvas to the view
+ setCanvas(canvas);
+}
+
+Canvas::~Canvas()
+{
+ delete sprite;
+ delete spriteFrames;
+}
+
+
+QPixmap* Canvas::canvas2Pixmap()
+{
+ pixmap = QPixmap( canvas->width(), canvas->height() );
+ QPainter painter(&pixmap);
+ canvas->drawArea(canvas->rect(), &painter);
+ return &pixmap;
+}
+
+// END
+
+
+
+// BEGIN public slots
+
+void Canvas::slotClear()
+{
+ QCanvasItemList list = canvas->allItems();
+ QCanvasItemList::Iterator it = list.begin();
+ for (; it != list.end(); ++it)
+ {
+ // kill everything but the turtle (who lives on a seperate layer)
+ if ( *it && !( (*it)->z() == 250 ) ) delete *it;
+ }
+}
+
+void Canvas::slotClearSpriteToo()
+{
+ QCanvasItemList list = canvas->allItems();
+ QCanvasItemList::Iterator it = list.begin();
+ for (; it != list.end(); ++it)
+ {
+ if (*it) delete *it;
+ }
+}
+
+
+void Canvas::slotGo(double x, double y)
+{
+ int intX = ROUND2INT(x);
+ int intY = ROUND2INT(y);
+
+ if ( wrap && !canvas->onCanvas(intX, intY) )
+ {
+ QPoint offsetPoint = offset(intX, intY);
+ posX = x - ( offsetPoint.x() * canvasWidth );
+ posY = y - ( offsetPoint.y() * canvasHeight );
+ }
+ else
+ {
+ posX = x;
+ posY = y;
+ }
+ updateSpritePos();
+}
+
+void Canvas::slotGoX(double x)
+{
+ int intX = ROUND2INT(x);
+ int intPosY = ROUND2INT(posY);
+ if ( wrap && !canvas->onCanvas(intX, intPosY) )
+ {
+ QPoint offsetPoint = offset(intX, intPosY);
+ posX = x - ( offsetPoint.x() * canvasWidth );
+ }
+ else posX = x;
+ updateSpritePos();
+}
+
+void Canvas::slotGoY(double y)
+{
+ int intY = ROUND2INT(y);
+ int intPosX = ROUND2INT(posX);
+ if ( wrap && !canvas->onCanvas(intPosX, intY) )
+ {
+ QPoint offsetPoint = offset(intPosX, intY);
+ posY = y - ( offsetPoint.y() * canvasHeight );
+ }
+ else posY = y;
+ updateSpritePos();
+}
+
+void Canvas::slotForward(double x)
+{
+ double posXnew = posX + ( x * sin(direction * DEG2RAD) );
+ double posYnew = posY - ( x * cos(direction * DEG2RAD) );
+ if (pen) lineShell(posX, posY, posXnew, posYnew);
+ slotGo(posXnew, posYnew);
+}
+
+void Canvas::slotBackward(double x)
+{
+ double posXnew = posX - ( x * sin(direction * DEG2RAD) );
+ double posYnew = posY + ( x * cos(direction * DEG2RAD) );
+ if (pen) lineShell(posX, posY, posXnew, posYnew);
+ slotGo(posXnew, posYnew);
+}
+
+void Canvas::slotDirection(double deg)
+{
+ direction = deg;
+ updateSpriteAngle();
+}
+
+void Canvas::slotTurnLeft(double deg)
+{
+ direction = direction - deg;
+ updateSpriteAngle();
+}
+
+void Canvas::slotTurnRight(double deg)
+{
+ direction = direction + deg;
+ updateSpriteAngle();
+}
+
+void Canvas::slotCenter()
+{
+ posX = canvasWidth / 2;
+ posY = canvasHeight / 2;
+ updateSpritePos();
+}
+
+void Canvas::slotSetPenWidth(int w)
+{
+ if (w == 1) penWidth = 0; // 0 gives 1 pixel lines using fast algorithem
+ else penWidth = w;
+}
+
+void Canvas::slotPenUp()
+{
+ pen = false;
+}
+
+void Canvas::slotPenDown()
+{
+ pen = true;
+}
+
+void Canvas::slotSetFgColor(int r, int g, int b)
+{
+ // shouldn't it be checked if: ( 0 =< r, g, b =< 255) ?
+ fgR = r;
+ fgG = g;
+ fgB = b;
+}
+
+void Canvas::slotSetBgColor(int r, int g, int b)
+{
+ canvas->setBackgroundColor( QColor(r, g, b) );
+}
+
+void Canvas::slotResizeCanvas(int x, int y)
+{
+ if (x <= 0 || y <= 0)
+ {
+ // TODO put error message
+ x = 100;
+ y = 100;
+ }
+ canvasWidth = x;
+ canvasHeight = y;
+ canvas->resize(x, y);
+ emit CanvasResized();
+}
+
+
+// I'm having major problems with the canvas and qt-3.2
+// qt-3.3 will fix it and the supposed fix is allready in qt-copy
+// i'll not work any further on sprites, while i dont have qt-3.3 or a fresh qt-copy
+
+void Canvas::slotSpriteShow()
+{
+ sprite->show();
+}
+
+void Canvas::slotSpriteHide()
+{
+ sprite->hide();
+}
+
+void Canvas::slotSpritePress()
+{
+}
+
+void Canvas::slotSpriteChange(int x)
+{
+ sprite->setFrame(x);
+ sprite->move(ROUND2INT(posX - sprite->width()/2), ROUND2INT(posY - sprite->height()/2));
+}
+
+void Canvas::slotPrint(QString text)
+{
+ QCanvasText* t = new QCanvasText(text, font, canvas);
+ // text does not do the wrapping, never... sorry
+ t->setColor( QColor(fgR, fgG, fgB) );
+ t->move(ROUND2INT(posX), ROUND2INT(posY));
+ t->show();
+}
+
+void Canvas::slotFontType(QString family, QString extra)
+{
+ font.setFamily(family);
+ font.setBold( extra.contains("bold") > 0 );
+ font.setItalic( extra.contains("italic") > 0 );
+ font.setUnderline( extra.contains("underline") > 0 );
+ font.setOverline( extra.contains("overline") > 0 );
+ font.setStrikeOut( extra.contains("strikeout") > 0 );
+}
+
+void Canvas::slotFontSize(int px)
+{
+ font.setPixelSize(px);
+}
+
+void Canvas::slotWrapOn()
+{
+ wrap = true;
+}
+
+void Canvas::slotWrapOff()
+{
+ wrap = false;
+}
+
+void Canvas::slotReset()
+{
+ slotClearSpriteToo();
+ initValues();
+}
+
+// END
+
+
+
+// BEGIN private methods
+
+void Canvas::initValues()
+{
+ // canvas size
+ slotResizeCanvas( Settings::canvasWidth(), Settings::canvasHeight() );
+ canvasWidth = Settings::canvasWidth();
+ canvasHeight = Settings::canvasHeight();
+ // colors
+ canvas->setBackgroundColor( QColor(255, 255, 255) ); // background
+ fgR = 0; // pencolor (forground)
+ fgG = 0;
+ fgB = 0;
+ // pen, wrap, direction and font
+ penWidth = 0;
+ pen = true;
+ wrap = true;
+ direction = 0;
+ font = QFont("serif", 18);
+ // the position
+ posX = canvasWidth / 2;
+ posY = canvasHeight / 2;
+ // construct the default sprite
+ loadSpriteFrames("turtle");
+ updateSpritePos();
+ updateSpriteAngle();
+ sprite->show();
+}
+
+
+void Canvas::lineShell(double xa, double ya, double xb, double yb)
+{
+ // line can fallback into this function in case of cutLoop == true
+ cutLoop = false;
+ // Reset the loop detection memory
+ prevStartPos3 = prevStartPos2 = prevStartPos1 = prevEndPos3 = prevEndPos2 = prevEndPos1 = QPoint(0, 0);
+ // and go!
+ line(xa, ya, xb, yb);
+}
+
+void Canvas::line(double xa, double ya, double xb, double yb)
+{
+ QCanvasLine* l = new QCanvasLine(canvas);
+ int intXa = ROUND2INT(xa);
+ int intYa = ROUND2INT(ya);
+ int intXb = ROUND2INT(xb);
+ int intYb = ROUND2INT(yb);
+ l->setPoints(intXa, intYa, intXb, intYb);
+ l->setPen( QPen(QColor(fgR, fgG, fgB), penWidth, SolidLine) );
+ l->setZ(1);
+ l->show();
+ // kdDebug(0)<<"Canvas::line(); xa:"<<xa<<", ya:"<<ya<<", xb:"<<xb<<", yb:"<<yb<<endl;
+ if ( wrap && !canvas->onCanvas( ROUND2INT(xb), ROUND2INT(yb) ) )
+ {
+ if (endlessLoop( QPoint(intXa, intYa), QPoint(intXb, intYb) ) == true) // detect for endless loop
+ {
+ slotCenter();
+ kdDebug(0)<<"Canvas::line(): ENDLESS LOOP DETECTED, BROKE THE LOOP"<<endl;
+ cutLoop = true;
+ return;
+ }
+
+ QPoint translation = translationFactor(xa, ya, xb, yb);
+ if (translation == QPoint(0, 0) )
+ {
+ // this could never happen in theory
+ kdDebug(0)<<"Canvas::line(): ***********ERRORRR***********"<<endl;
+ return;
+ }
+ // kdDebug(0)<<"Canvas::line(); translate by: <<tranlation<<endl;
+ line (xa + translation.x() * canvasWidth, ya + translation.y() * canvasHeight,
+ xb + translation.x() * canvasWidth, yb + translation.y() * canvasHeight);
+ if (cutLoop == true)
+ {
+ // kdDebug(0)<<"Canvas::line(): cutLoop is set to TRUE! ABORT LINE MISSION"<<endl;
+ return;
+ }
+ }
+}
+
+bool Canvas::endlessLoop(QPoint begin, QPoint end)
+{
+ // kdDebug(0)<<"prevStartPos3: "<<prevStartPos3<<", prevStartPos2: "<<prevStartPos2<<", prevStartPos1: "<<prevStartPos1<<", prevStartPos0: "<<begin<<", prevEndPos3: "<<prevEndPos3<<", prevEndPos2: "<<prevEndPos2<<", prevEndPos1: "<<prevEndPos1<<", prevEndPos0: "<<end<<endl;
+ if ( prevStartPos2 == begin && prevStartPos3 == prevStartPos1 &&
+ prevEndPos2 == end && prevEndPos3 == prevEndPos1 )
+ {
+ // this is to break the horrible endless loop bug that i cannot fix...
+ // i need more simple reproductions of this bug to really find it
+ // for now i say it is something with QCanvas but i'm likely wrong on thisone
+ // kdDebug(0)<<"Canvas::endlessLoop TRUE!!"<<endl;
+ return true;
+ }
+ else
+ {
+ // kdDebug(0)<<"Canvas::endlessLoop FASLE!!"<<endl;
+ prevStartPos3 = prevStartPos2;
+ prevStartPos2 = prevStartPos1;
+ prevStartPos1 = begin;
+ prevEndPos3 = prevEndPos2;
+ prevEndPos2 = prevEndPos1;
+ prevEndPos1 = end;
+ return false;
+ }
+ return false; // fallback will not be used
+}
+
+bool Canvas::pointInRange(double px, double py, double xa, double ya, double xb, double yb)
+{
+ if ( ( ( px >= xa && px <= xb ) || ( px <= xa && px >= xb ) ) &&
+ ( ( py >= ya && py <= yb ) || ( py <= ya && py >= yb ) ) ) return true;
+ return false;
+}
+
+QPoint Canvas::offset(int x, int y)
+{
+ // This funktion makes is easy to read since deviding int's is a weird thing:
+ // int x = 5 / 2, outputs: x = 2, with: 5 % 2 = 1 (the rest value)
+ if (x < 0) x = x - canvasWidth;
+ if (y < 0) y = y - canvasHeight;
+ QPoint offsetPoint( x / canvasWidth, y / canvasHeight);
+ return offsetPoint;
+}
+
+QPoint Canvas::translationFactor(double xa, double ya, double xb, double yb)
+{
+ // this class returns a QPoint which can be used to properly 'wrap' a line
+ QPoint crossPoint[4]; // under wicked circumstances we can need this
+ // namely when crossing both corners, we have 4 bordercrossings
+ QPoint translate[4];
+ int i = 0;
+ if ( (xb - xa) > -0.00001 && (xb - xa) < 0.00001 ) // check for an infinite tangent (direction coefficient)
+ {
+ i++;
+ translate[i] = QPoint( 0, 1 );
+ crossPoint[i] = QPoint( ROUND2INT(xa), 0 );
+ i++;
+ translate[i] = QPoint(0,-1 );
+ crossPoint[i] = QPoint( ROUND2INT(xa), canvasHeight );
+ }
+ else
+ {
+ // Here we find out what crossing points the line has with canvas border lines (lines are ENDLESS here)
+
+ // f(t) == (yb - ya) / (xb - xa) * t + ya - (A * xa) == A*t + B
+ double A = (yb - ya) / (xb - xa);
+ double B = ya - (A * xa);
+
+ double x_sT = -B / A; // A * x_sT + B == 0 => x_sT == -B / A
+ double x_sB = ( (double)(canvasHeight) - B ) / A; // A * x_sB + B == CH => x_sB == (CH - B) / A
+ double y_sL = B; // A * 0 + B == y_sL => y_sL == B
+ double y_sR = ( A * (double)(canvasWidth) ) + B; // A * CW + B == y_sR
+ // kdDebug(0)<<"Canvas::translationFactor; rc:"<<A<<", xTop:"<<x_sT<<", xBot:"<<x_sB<<", yLft:"<<y_sL<<", yRft:"<<y_sR<<". "<<endl;
+
+ // Here we find out what crossing points are on the borders AND on the linePIECES
+ // pointInRange only checks wether the crossing point of the ENDLESS line is on the line PIECE.
+ if ( 0 <= x_sT && x_sT <= canvasWidth && pointInRange(x_sT, 0, xa, ya, xb, yb) )
+ {
+ i++;
+ translate[i] = QPoint( 0, 1 );
+ crossPoint[i] = QPoint( ROUND2INT(x_sT), 0 );
+ }
+ if ( 0 <= x_sB && x_sB <= canvasWidth && pointInRange(x_sB, canvasHeight, xa, ya, xb, yb) )
+ {
+ i++;
+ translate[i] = QPoint( 0,-1 );
+ crossPoint[i] = QPoint( ROUND2INT(x_sB), ROUND2INT(canvasHeight) );
+ }
+ if ( 0 <= y_sL && y_sL <= canvasHeight && pointInRange(0, y_sL, xa, ya, xb, yb) )
+ {
+ i++;
+ translate[i] = QPoint( 1, 0 );
+ crossPoint[i] = QPoint( 0, ROUND2INT(y_sL) );
+ }
+ if ( 0 <= y_sR && y_sR <= canvasHeight && pointInRange(canvasWidth, y_sR, xa, ya, xb, yb) )
+ {
+ i++;
+ translate[i] = QPoint(-1, 0 );
+ crossPoint[i] = QPoint( ROUND2INT(canvasWidth), ROUND2INT(y_sR) );
+ }
+
+ if ( i == 0 )
+ {
+ // kdDebug(0)<<"Canvas::translationFactor: FIRST NO BORDER CROSSINGS DETECTED"<<endl;
+ QPoint returnValue = QPoint(0, 0); // initiate the returnValue
+ // Here a fallback if the line has no crossings points with any borders.
+ // This mostly happens because of unlucky rounding, when this happens the line is nearly
+ // crossing a corner of the canvas.
+ // This code make sure the line is tranlated back onto the canvas.
+ // The -2 and +2 was just something i learnt from examples... I HAVE NO PROOF FOR THIS!
+ // This, luckily, allmost never happens.
+ if ( -2 <= x_sT && x_sT <= (canvasWidth + 2) && pointInRange(x_sT, 0, xa, ya, xb, yb) )
+ {
+ returnValue = returnValue + QPoint(0, 1);
+ }
+ if ( -2 <= x_sB && x_sB <= (canvasWidth + 2) && pointInRange(x_sB, canvasHeight, xa, ya, xb, yb) )
+ {
+ returnValue = returnValue + QPoint(0,-1);
+ }
+ if ( -2 <= y_sL && y_sL <= (canvasHeight + 2) && pointInRange(0, y_sL, xa, ya, xb, yb) )
+ {
+ returnValue = returnValue + QPoint(1, 0);
+ }
+ if ( -2 <= y_sR && y_sR <= (canvasHeight + 2) && pointInRange(canvasWidth, y_sR, xa, ya, xb, yb) )
+ {
+ returnValue = returnValue + QPoint(-1, 0);
+ }
+
+ if ( returnValue == QPoint(0, 0) )
+ {
+ // kdDebug(0)<<"Canvas::translationFactor: *****This shouldn't happen (1) *****"<<endl;
+ // and this doesnt happen, that why +3 and -3 are ok values and the code above works.
+ }
+ return returnValue;
+ }
+ }
+
+ QPoint returnValue = QPoint(0, 0); // a new returnValue QPoint gets inited
+ if (i == 1)
+ {
+ // only one border crossing, this is normal when the start point
+ // is within the canvas and no corners are crossed
+ // kdDebug(0)<<"***only one border crossing!"<<endl;
+ return translate[1];
+ }
+ if (i > 1)
+ {
+ // more than one border crossing starting point if of the canvas
+ // we now have to find out which crossing occurs 'first' to know how to translate the line
+ // NOTE2SELF: the line does NOT have to start on the canvas!!
+ QPoint endPos( ROUND2INT(xb), ROUND2INT(yb));
+ int smallestSize = ( QPoint( ROUND2INT(xa), ROUND2INT(ya) ) - endPos ).manhattanLength();
+ // smallestSize is initiated to the total size of the line
+ for (int ii = 1; ii <= i; ii++)
+ {
+ int testSize = ( crossPoint[ii] - endPos ).manhattanLength(); // size till the crosspoint
+ if (testSize < smallestSize) // if testSize is smaller then...
+ {
+ smallestSize = testSize; // ...it becomes smallestSize
+ returnValue = translate[ii];
+ // and the returnValue is updated to the corresponing translaton factors
+ // kdDebug(0)<<"Canvas::translationFactor: UPDATED"<<endl;
+ }
+ else if (testSize == smallestSize) // this only happens on corners
+ {
+ // kdDebug(0)<<"Canvas::translationFactor: CORNER EXCEPTION"<<endl;
+ returnValue = QPoint(0, 0);
+ if (xb < 0) returnValue = returnValue + QPoint( 1, 0);
+ else if (xb > canvasWidth) returnValue = returnValue + QPoint(-1, 0);
+
+ if (yb < 0) returnValue = returnValue + QPoint( 0, 1);
+ else if (yb > canvasHeight) returnValue = returnValue + QPoint( 0,-1);
+
+ return returnValue;
+ }
+ }
+ // kdDebug(0)<<"Canvas::translationFactor: NOT RETURNED YET SO DOING IT NOW"<<endl;
+ return returnValue;
+ }
+ // kdDebug(0)<<"Canvas::translationFactor: *****This shouldn't happen (3) *****"<<endl;
+ return returnValue;
+}
+
+
+
+// Sprite related methods:
+
+void Canvas::loadSpriteFrames(QString name)
+{
+ // read the pixmaps name.0001.png, name.0002.png, ..., name.0035.png: the different rotations
+ // #0000 for 0 or 360, #0001 for 10, #0002 for 20, ..., #0018 for 180, etc.
+
+ // WARNING if the dir doesnt exists the app will crash!!!
+ // This will be fixed in qt3.3 and in the current qt-copy
+ QPixmap turtlePix = QPixmap(locate("data","kturtle/pics/turtle.0000.png") );
+ if ( turtlePix.isNull() )
+ {
+ KMessageBox::sorry( this,
+ i18n("The turtle picture could not be found. "
+ "Please check your installation."), i18n("Error") );
+ return;
+ }
+ QString spritePath = locate("data","kturtle/pics/"+name+".0000.png");
+ spritePath.remove(".0000.png");
+ spriteFrames = new QCanvasPixmapArray(spritePath+".%1.png", 36);
+ sprite = new QCanvasSprite(spriteFrames, canvas);
+ sprite->setZ(250);
+}
+
+void Canvas::updateSpritePos()
+{
+ sprite->move( posX - ( sprite->width() / 2 ), posY - ( sprite->height() / 2 ), -1 );
+}
+
+void Canvas::updateSpriteAngle()
+{
+ // get the direction back on the 1st circle
+ while (direction < 0 || direction >= 360)
+ {
+ if (direction >= 360) direction = direction - 360;
+ if (direction < 0) direction = direction + 360;
+ }
+ // convert to degrees, fix the direction, divide by 10 (for picnr), and round
+ int i = (int) ( direction / 10 );
+ // kdDebug(0)<<"########## direction = "<<direction<<"; int i = "<< i << endl;
+ // int i = (int) ( ( ( (-direction * 180) / PI ) / 10) + 0.000000001 );
+ sprite->setFrame(i);
+ updateSpritePos(); // pixmaps of different rotations have different sizes, so refresh
+}
+
+// END
+
+
+#include "canvas.moc"
diff --git a/kturtle/src/canvas.h b/kturtle/src/canvas.h
new file mode 100644
index 00000000..349e610d
--- /dev/null
+++ b/kturtle/src/canvas.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2003 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _CANVAS_H_
+#define _CANVAS_H_
+
+#include <qcanvas.h>
+
+
+class Canvas : public QCanvasView
+{
+ Q_OBJECT
+
+ public:
+ Canvas(QWidget *parent = 0, const char *name = 0);
+ ~Canvas();
+
+ QPixmap* canvas2Pixmap();
+
+
+ public slots:
+ void slotClear();
+ void slotClearSpriteToo();
+ void slotGo(double x, double y);
+ void slotGoX(double x);
+ void slotGoY(double y);
+ void slotForward(double x);
+ void slotBackward(double x);
+ void slotDirection(double deg);
+ void slotTurnLeft(double deg);
+ void slotTurnRight(double deg);
+ void slotCenter();
+ void slotSetPenWidth(int w);
+ void slotPenUp();
+ void slotPenDown();
+ void slotSetFgColor(int r, int g, int b);
+ void slotSetBgColor(int r, int g, int b);
+ void slotResizeCanvas(int x, int y);
+ void slotSpriteShow();
+ void slotSpriteHide();
+ void slotSpritePress();
+ void slotSpriteChange(int x);
+
+ void slotPrint(QString text);
+ void slotFontType(QString family, QString extra);
+ void slotFontSize(int px);
+ void slotWrapOn();
+ void slotWrapOff();
+ void slotReset();
+
+
+ signals:
+ void CanvasResized();
+
+
+ private:
+ void initValues();
+
+ void line(double xa, double ya, double xb, double yb);
+ void lineShell(double xa, double ya, double xb, double yb);
+ bool endlessLoop(QPoint begin, QPoint end);
+ bool pointInRange(double px, double py, double xa, double ya, double xb, double yb);
+ QPoint offset(int x, int y);
+ QPoint translationFactor(double xa, double ya, double xb, double yb);
+
+ void loadSpriteFrames(QString name);
+ void updateSpritePos();
+ void updateSpriteAngle();
+
+ QCanvas *canvas;
+ QPixmap pixmap;
+ QCanvasSprite *sprite;
+ QCanvasPixmapArray *spriteFrames;
+ QFont font;
+ double posX, posY;
+ int canvasWidth, canvasHeight;
+ int penWidth;
+ double direction;
+ int fgR, fgG, fgB;
+ bool pen;
+ bool wrap;
+ bool cutLoop;
+ QPoint prevStartPos3, prevStartPos2, prevStartPos1, prevEndPos3, prevEndPos2, prevEndPos1;
+};
+
+#endif // _CANVAS_H_
diff --git a/kturtle/src/dialogs.cpp b/kturtle/src/dialogs.cpp
new file mode 100644
index 00000000..044f36f4
--- /dev/null
+++ b/kturtle/src/dialogs.cpp
@@ -0,0 +1,320 @@
+/*
+ KTurtle, Copyright (C) 2003-04 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "dialogs.h"
+
+
+// BEGIN class ErrorMessage dialog
+
+ErrorMessage::ErrorMessage (QWidget *parent)
+ : KDialogBase (parent, "errorDialog", false, 0, KDialogBase::Close | KDialogBase::Help | KDialogBase::User1, KDialogBase::Close, true, i18n("Help on &Error") )
+{
+ connect( this, SIGNAL( user1Clicked() ), this, SLOT( showHelpOnError() ) );
+ connect( this, SIGNAL( helpClicked() ), this, SLOT( errorMessageHelp() ) );
+ setCaption( i18n("Error Dialog") );
+ setButtonWhatsThis( KDialogBase::Close, i18n("Closes this error dialog") );
+ setButtonWhatsThis( KDialogBase::Help, i18n("Click here to read more on this error dialog in KTurtle's Handbook.") );
+ setButtonTip( KDialogBase::Help, i18n("Click here for help using this error dialog") );
+ setButtonWhatsThis( KDialogBase::User1, i18n("Click here for help regarding the error you selected in the list. This button will not work when no error is selected.") );
+ setButtonTip( KDialogBase::User1, i18n("Click here for help regarding the error you selected.") );
+
+ QWidget *baseWidget = new QWidget(this);
+ setMainWidget(baseWidget);
+ baseLayout = new QVBoxLayout(baseWidget);
+
+ label = new QLabel(baseWidget);
+ label->setText( i18n("In this list you find the error(s) that resulted from running your Logo code. \nGood luck!") );
+ // \nYou can select an error and click the 'Help on Error' button for help.
+ label->setScaledContents(true);
+ baseLayout->addWidget(label);
+
+ spacer = new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Fixed );
+ baseLayout->addItem(spacer);
+
+ errTable = new QTable(0, 3, baseWidget);
+ errTable->setSelectionMode(QTable::SingleRow);
+ errTable->setReadOnly(true);
+ errTable->setShowGrid(false);
+ errTable->setFocusStyle(QTable::FollowStyle);
+ errTable->setLeftMargin(0);
+
+ errTable->horizontalHeader()->setLabel( 0, i18n("number") );
+ errTable->hideColumn(0); // needed to link with the errorData which stores the tokens, codes, etc.
+
+ errTable->horizontalHeader()->setLabel( 1, i18n("line") );
+ errTable->setColumnWidth(1, baseWidget->fontMetrics().width("88888") );
+
+ errTable->horizontalHeader()->setLabel( 2, i18n("description") );
+ errTable->setColumnStretchable(2, true);
+
+ baseLayout->addWidget(errTable);
+
+ // Since both help buttons are not working yet. Doc need a section on the Error Dialog!
+ enableButton(KDialogBase::Help, false);
+ enableButton(KDialogBase::User1, false);
+
+ errCount = 1;
+}
+
+
+void ErrorMessage::slotAddError(Token& t, const QString& s, uint c)
+{
+ errorData err;
+ err.code = c;
+ err.tok = t;
+ err.msg = s;
+ errList.append(err);
+
+ Token currentToken = err.tok; kdDebug(0)<<"ErrorMessage::slotAddError(); >> "<<err.msg<<" <<, token: '"<<currentToken.look<<"', @ ("<<currentToken.start.row<<", "<<currentToken.start.col<<") - ("<<currentToken.end.row<<", "<<currentToken.end.col<<"), tok-number:"<<currentToken.type<<endl;
+
+ errTable->insertRows(0);
+ errTable->setText( 0, 0, QString::number(errCount) ); // put the count in a hidden field for reference
+ errTable->setText( 0, 1, QString::number(err.tok.start.row) );
+ errTable->setText( 0, 2, err.msg );
+
+ errCount++;
+}
+
+
+bool ErrorMessage::containsErrors()
+{
+ if (errTable->numRows() != 0) return true;
+ return false;
+}
+
+void ErrorMessage::display()
+{
+ errTable->clearSelection();
+ enableButton (KDialogBase::User1, false);
+ errTable->sortColumn(0, true, true);
+ show();
+ connect( errTable, SIGNAL( selectionChanged() ), this, SLOT( updateSelection() ) );
+}
+
+void ErrorMessage::updateSelection()
+{
+ int i = errTable->text( errTable->currentRow(), 0 ).toInt(); // get the hidden errCount value
+ currentError = *errList.at(i - 1);
+ emit setSelection(currentError.tok.start.row, currentError.tok.start.col,
+ currentError.tok.end.row, currentError.tok.end.col);
+// #if 0 // FIXME
+// if ( tokenTypeNames[currentError.tok.type].isEmpty() ) enableButton(KDialogBase::User1, true);
+// else enableButton(KDialogBase::User1, false);
+// #endif
+}
+
+void ErrorMessage::showHelpOnError()
+{
+// #if 0 // FIXME
+// kapp->invokeHelp(tokenTypeNames[currentError.tok.type], "", "");
+// #endif
+}
+
+void ErrorMessage::errorMessageHelp()
+{
+ kapp->invokeHelp("anchorname", "", "");
+}
+
+// END
+
+
+
+// BEGIN class ColorPicker dialog
+
+ColorPicker::ColorPicker(QWidget *parent)
+ : KDialogBase(parent, "colorpicker", false, i18n("Color Picker"), KDialogBase::Close | KDialogBase::Help | KDialogBase::User1, KDialogBase::Close, true )
+{
+ // connect to help
+ connect( this, SIGNAL( helpClicked() ), SLOT( slotColorPickerHelp() ) );
+
+ // for toggling convenience
+ connect( this, SIGNAL( finished() ), SLOT( slotEmitVisibility() ) );
+
+ // Create the top level page and its layout
+ BaseWidget = new QWidget(this);
+ setMainWidget(BaseWidget);
+
+ // the User1 button:
+ setButtonText( KDialogBase::User1, i18n("Insert Color Code at Cursor") );
+ connect( this, SIGNAL( user1Clicked() ), SLOT( slotEmitColorCode() ) );
+
+ QVBoxLayout *vlayout = new QVBoxLayout(BaseWidget);
+
+ vlayout->addSpacing(5); // spacing on top
+
+ // the palette and value selector go into a H-box
+ QHBoxLayout *h1layout = new QHBoxLayout(BaseWidget);
+ vlayout->addLayout(h1layout);
+
+ h1layout->addSpacing(10); // space on the left border
+
+ hsSelector = new KHSSelector(BaseWidget); // the color (SH) selector
+ hsSelector->setMinimumSize(300, 150);
+ h1layout->addWidget(hsSelector);
+ connect( hsSelector, SIGNAL( valueChanged(int, int) ), SLOT( slotSelectorChanged(int, int) ) );
+
+ h1layout->addSpacing(5); // space in between
+
+ valuePal = new KValueSelector(BaseWidget); // the darkness (V) pal
+ valuePal->setFixedWidth(30);
+ h1layout->addWidget(valuePal);
+ connect( valuePal, SIGNAL( valueChanged(int) ), SLOT( slotPalChanged(int) ) );
+
+ vlayout->addSpacing(15); // space in between the top and the bottom widgets
+
+ // the patch and the codegenerator also go into a H-box
+ QHBoxLayout *h2layout = new QHBoxLayout(BaseWidget);
+ vlayout->addLayout(h2layout);
+
+ h2layout->addSpacing(10); // space on the left border
+
+ patch = new KColorPatch(BaseWidget); // the patch (color previewer)
+ patch->setFixedSize(50, 50);
+ h2layout->addWidget(patch);
+
+ h2layout->addSpacing(10); // space in between
+
+ // the label and the codegenerator go in a V-box
+ QVBoxLayout *v2layout = new QVBoxLayout(BaseWidget);
+ h2layout->addLayout(v2layout);
+
+ copyable = new QLabel(i18n("Color code:"), BaseWidget); // tha label
+ v2layout->addWidget(copyable);
+
+ colorcode = new QLineEdit(BaseWidget); // the code generator
+ colorcode->setReadOnly(true);
+ v2layout->addWidget(colorcode);
+ connect( colorcode, SIGNAL( selectionChanged() ), SLOT( slotReselect() ) );
+
+ h2layout->addSpacing(5); // spacing on the right border
+
+ vlayout->addSpacing(10); // spacing on the bottom
+
+ h = g = b = 0; // start with red
+ s = v = r = 255;
+
+ slotSelectorChanged(h, s); // update all at once
+}
+
+
+
+void ColorPicker::updateSelector()
+{
+ hsSelector->setValues(h, s);
+}
+
+void ColorPicker::updatePal()
+{
+ valuePal->setHue(h);
+ valuePal->setSaturation(s);
+ valuePal->setValue(v);
+ valuePal->updateContents();
+ valuePal->repaint(false);
+}
+
+void ColorPicker::updatePatch()
+{
+ patch->setColor(color);
+}
+
+void ColorPicker::updateColorCode()
+{
+ color.getRgb(&r, &g, &b);
+ colorcode->setText( QString("%1, %2, %3").arg(r).arg(g).arg(b) );
+ colorcode->selectAll();
+}
+
+void ColorPicker::slotSelectorChanged(int h_, int s_)
+{
+ h = h_;
+ s = s_;
+ color.setHsv(h, s, v);
+
+ //updateSelector(); // updated it self allready
+ updatePal();
+ updatePatch();
+ updateColorCode();
+}
+
+void ColorPicker::slotPalChanged(int v_)
+{
+ v = v_;
+ color.setHsv(h, s, v);
+
+ //updateSelector(); // only needed when H or S changes
+ //updatePal(); // updated it self allready
+ updatePatch();
+ updateColorCode();
+}
+
+void ColorPicker::slotReselect()
+{
+ // reselect by selectAll(), but make sure no looping occurs
+ disconnect( colorcode, SIGNAL( selectionChanged() ), 0, 0 );
+ colorcode->selectAll();
+ connect( colorcode, SIGNAL( selectionChanged() ), SLOT( slotReselect() ) );
+}
+
+void ColorPicker::slotEmitVisibility()
+{
+ // for toggling convenience
+ emit visible(false);
+}
+
+void ColorPicker::slotEmitColorCode()
+{
+ // convenience
+ emit ColorCode( colorcode->text() );
+}
+
+void ColorPicker::slotColorPickerHelp()
+{
+ kapp->invokeHelp("tools-color-picker", "", "");
+}
+
+// END
+
+
+
+// BEGIN class RestartOrBack dialog
+
+RestartOrBack::RestartOrBack (QWidget *parent)
+ : KDialogBase (parent, "rbDialog", true, 0, KDialogBase::User1 | KDialogBase::User2, KDialogBase::User2, false, i18n("&Restart"), i18n("&Back") )
+{
+ setPlainCaption( i18n("Finished Execution") );
+ setButtonWhatsThis( KDialogBase::User1, i18n("Click here to restart the current logo program.") );
+ setButtonWhatsThis( KDialogBase::User2, i18n("Click here to switch back to the edit mode.") );
+ QWidget *baseWidget = new QWidget(this);
+ setMainWidget(baseWidget);
+ baseLayout = new QVBoxLayout(baseWidget);
+
+ label = new QLabel(baseWidget);
+ label->setText( i18n("Execution was finished without errors.\nWhat do you want to do next?") );
+ label->setScaledContents(true);
+ baseLayout->addWidget(label);
+ disableResize();
+}
+
+// END
+
+
+#include "dialogs.moc"
diff --git a/kturtle/src/dialogs.h b/kturtle/src/dialogs.h
new file mode 100644
index 00000000..dd4f2474
--- /dev/null
+++ b/kturtle/src/dialogs.h
@@ -0,0 +1,165 @@
+/*
+ KTurtle, Copyright (C) 2003-04 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// This is one class for all custom dialogs that KTurtle uses.
+// Right now that are:
+// - ErrorMessage dialog, used to display the users coding errors
+// - ColorPicker dialog, used to easily pick color-codes and put them in the code
+// - RestartOrBack dialog, used when executing in fullscreenmode
+
+
+#ifndef _DIALOGS_H_
+#define _DIALOGS_H_
+
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qstring.h>
+#include <qtable.h>
+#include <qvaluelist.h>
+
+#include <kdialogbase.h>
+#include <kcolordialog.h>
+
+#include "token.h"
+
+
+// BEGIN ErrorMessage dialog HEADER
+
+struct errorData
+{
+ uint code;
+ Token tok;
+ QString msg;
+};
+
+
+class ErrorMessage : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ ErrorMessage(QWidget *parent);
+ ~ErrorMessage() {}
+
+ bool containsErrors();
+
+ void display();
+
+ public slots:
+ void slotAddError(Token&, const QString&, uint code);
+ void updateSelection();
+
+ private slots:
+ void showHelpOnError();
+ void errorMessageHelp();
+
+ signals:
+ void setCursor(uint row, uint column);
+ void setSelection(uint, uint, uint, uint);
+
+ private:
+ typedef QValueList<errorData> errorList;
+ errorList errList;
+ QTable *errTable;
+ uint errCount;
+ errorData currentError;
+
+ protected:
+ QDialog *dialog;
+ QVBoxLayout *baseLayout;
+ QLabel *label;
+ QSpacerItem *spacer;
+};
+
+// END
+
+
+
+// BEGIN ColorPicker dialog HEADER
+
+class ColorPicker : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ ColorPicker(QWidget *parent);
+ virtual ~ColorPicker() {}
+
+
+ signals:
+ void visible(bool); // for toggling convenience
+ void ColorCode(QString);
+
+
+ private:
+ void updateSelector();
+ void updatePal();
+ void updatePatch();
+ void updateColorCode();
+
+ QWidget *BaseWidget;
+ KHSSelector *hsSelector;
+ KValueSelector *valuePal;
+ QVBoxLayout *vlayout;
+ QHBoxLayout *h1layout;
+ QHBoxLayout *h2layout;
+ KColorPatch *patch;
+ QLabel *copyable;
+ QLineEdit *colorcode;
+ QColor color;
+ int h, s, v, r, g, b;
+
+
+ private slots:
+ void slotColorPickerHelp();
+
+
+ protected slots:
+ void slotSelectorChanged(int _h, int _s);
+ void slotPalChanged(int _v);
+ void slotReselect();
+
+ void slotEmitVisibility(); // for toggling convenience
+ void slotEmitColorCode(); // convenience
+};
+
+// END
+
+
+
+// BEGIN RestartOrBack dialog HEADER
+
+class RestartOrBack : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ RestartOrBack (QWidget *parent);
+ ~RestartOrBack() {}
+
+ protected:
+ QVBoxLayout *baseLayout;
+ QLabel *label;
+};
+
+// END
+
+
+#endif // _DIALOGS_H_
diff --git a/kturtle/src/executer.cpp b/kturtle/src/executer.cpp
new file mode 100644
index 00000000..f7058146
--- /dev/null
+++ b/kturtle/src/executer.cpp
@@ -0,0 +1,1116 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+// This file is originally written by Walter Scheppers, but almost
+// every aspect of it is slightly changed by Cies Breijs.
+
+
+#include <unistd.h> // for usleep();
+#include <stdlib.h>
+
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "executer.h"
+
+// this function is used in executer and canvas:
+#define ROUND2INT(x) ( (x) >= 0 ? (int)( (x) + .5 ) : (int)( (x) - .5 ) )
+
+
+Executer::Executer(TreeNode* tree)
+{
+ this->tree = tree;
+ functionTable.clear();
+ bBreak = false;
+ bReturn = false;
+}
+
+Executer::~Executer()
+{
+ emit Finished();
+}
+
+bool Executer::run()
+{
+ bBreak = false;
+ bReturn = false;
+ bPause = false;
+ bAbort = false;
+ symtable main;
+ symbolTables.push(main); // new symbol table for main block
+
+ TreeNode::const_iterator i;
+ for (i = tree->begin(); i != tree->end(); ++i)
+ {
+ if (bAbort) return false;
+ kapp->processEvents();
+ execute(*i);
+
+ symbolTables.pop(); //free up stack
+ }
+ return true;
+}
+
+void Executer::slowDown(TreeNode* node)
+{
+ switch (runSpeed)
+ {
+ case 1: // slow
+ startWaiting(0);
+ break;
+
+ case 2: // slower
+ startWaiting(250);
+ break;
+
+ case 3: // slowest
+ startWaiting(900);
+ break;
+
+ default:
+ kdDebug(0)<<"Executer: Wrong execution speed given"<<endl;
+ break;
+ }
+ Token tok = node->getToken();
+ emit setSelection(tok.start.row, tok.start.col, tok.end.row, tok.end.col);
+}
+
+void Executer::slotChangeSpeed(int speed)
+{
+ runSpeed = speed;
+}
+
+void Executer::pause()
+{
+ // The next line is within all loops of the Executer
+ // if (bAbort) return;
+ // mostly before
+ // kapp->processEvents();
+ // this to keep the GUI of KTurtle accessible while executing the logo code
+ // so the Abort button can be clicked, and will function
+ bPause = true;
+}
+
+void Executer::abort()
+{
+ // The next line is within all loops of the Executer
+ // if(bAbort) return;
+ // mostly before
+ // kapp->processEvents();
+ // this to keep the GUI of KTurtle accessible while executing the logo code
+ // so the Abort button can be clicked, and will function
+ bAbort = true;
+}
+
+
+void Executer::execute(TreeNode* node)
+{
+ switch ( node->getType() )
+ {
+ case blockNode : execBlock(node); break;
+ case forNode : execFor(node); break;
+ case forEachNode : execForEach(node); break;
+ case whileNode : execWhile(node); break;
+ case ifNode : execIf(node); break;
+ case assignNode : execAssign(node); break;
+ case expressionNode : execExpression(/*node*/); break;
+ case idNode : execId(node); break;
+ case constantNode : execConstant(/*node*/); break; // does nothing value allready set
+
+ case addNode : execAdd(node); break;
+ case mulNode : execMul(node); break;
+ case divNode : execDiv(node); break;
+ case subNode : execSub(node); break;
+ case minusNode : execMinus(node); break;
+
+ case nodeGE : execGE(node); break;
+ case nodeGT : execGT(node); break;
+ case nodeLE : execLE(node); break;
+ case nodeLT : execLT(node); break;
+ case nodeNE : execNE(node); break;
+ case nodeEQ : execEQ(node); break;
+
+ case andNode : execAnd(node); break;
+ case orNode : execOr(node); break;
+ case notNode : execNot(node); break;
+
+ case functionNode : createFunction(node); break;
+ case functionCallNode : execFunction(node); break;
+ case funcReturnNode : execRetFunction(node); break;
+ case returnNode : execReturn(node); break;
+ case breakNode : execBreak(/*node*/); break;
+
+ case runNode : execRun(node); break;
+
+ case ClearNode : execClear(node); break;
+ case GoNode : execGo(node); break;
+ case GoXNode : execGoX(node); break;
+ case GoYNode : execGoY(node); break;
+ case ForwardNode : execForward(node); break;
+ case BackwardNode : execBackward(node); break;
+ case DirectionNode : execDirection(node); break;
+ case TurnLeftNode : execTurnLeft(node); break;
+ case TurnRightNode : execTurnRight(node); break;
+ case CenterNode : execCenter(node); break;
+ case SetPenWidthNode : execSetPenWidth(node); break;
+ case PenUpNode : execPenUp(node); break;
+ case PenDownNode : execPenDown(node); break;
+ case SetFgColorNode : execSetFgColor(node); break;
+ case SetBgColorNode : execSetBgColor(node); break;
+ case ResizeCanvasNode : execResizeCanvas(node); break;
+ case SpriteShowNode : execSpriteShow(node); break;
+ case SpriteHideNode : execSpriteHide(node); break;
+ case SpritePressNode : execSpritePress(node); break;
+ case SpriteChangeNode : execSpriteChange(node); break;
+
+ case MessageNode : execMessage(node); break;
+ case InputWindowNode : execInputWindow(node); break;
+ case printNode : execPrint(node); break;
+ case FontTypeNode : execFontType(node); break;
+ case FontSizeNode : execFontSize(node); break;
+ case RepeatNode : execRepeat(node); break;
+ case RandomNode : execRandom(node); break;
+ case WaitNode : execWait(node); break;
+ case WrapOnNode : execWrapOn(node); break;
+ case WrapOffNode : execWrapOff(node); break;
+ case ResetNode : execReset(node); break;
+
+ case EndOfFileNode : break; // just do nothing is enough
+
+ case Unknown : // dont break but fallthrough to default
+
+ default:
+ kdDebug(0)<<"Found unsupported node named '"<<node->getLook()<<"' in the tree @ ("<<node->getRow()<<", "<<node->getCol()<<")"<<endl;
+ break;
+ }
+}
+
+
+void Executer::createFunction(TreeNode* node)
+{
+ QString funcname = node->getLook();
+ functionTable[funcname] = node; //store for later use
+}
+
+
+//execute a function
+void Executer::execFunction(TreeNode* node)
+{
+ QString funcname = node->getLook();
+
+ // locate function node
+ functable::iterator p = functionTable.find(funcname);
+ if ( p == functionTable.end() )
+ {
+ emit ErrorMsg(node->getToken(), i18n("Call to undefined function: %1.").arg(funcname), 5010);
+ return;
+ }
+
+ TreeNode* funcnode = p->second;
+ TreeNode* funcIds = funcnode->firstChild();
+ TreeNode* callparams = node->firstChild();
+
+ // check if number of parameters match
+ if ( callparams->size() != funcIds->size() )
+ {
+ emit ErrorMsg(node->getToken(), i18n("Call to function '%1' with wrong number of parameters.").arg(funcname), 5020);
+ return;
+ }
+
+ // pass parameters to function
+ // by adding them to it's symboltable and setting the values
+ TreeNode::iterator pfrom, pto = funcIds->begin();
+ symtable funcSymTable;
+
+ for (pfrom = callparams->begin(); pfrom != callparams->end(); ++pfrom )
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ // execute the parameters which can be expressions
+ execute(*pfrom);
+
+ QString idname = (*pto)->getLook();
+ funcSymTable[idname] = (*pfrom)->getValue();
+ ++pto;
+ }
+
+ symbolTables.push(funcSymTable); // use new symboltable for current function
+
+ // execute function statement block
+ bReturn = false; // set to true when return is called
+ execute( funcnode->secondChild() );
+ bReturn = false; // function execution done
+
+ symbolTables.pop(); // release function symboltable
+}
+
+
+// execute a function and expect and get return
+// value from stack
+// first child = function name
+// second child = parameters
+void Executer::execRetFunction(TreeNode* node)
+{
+ execFunction(node);
+ if (runStack.size() == 0)
+ {
+ emit ErrorMsg(node->getToken(), i18n("Function %1 did not return a value.").arg( node->getLook() ), 5030);
+ return;
+ }
+ node->setValue( runStack.top() ); // set return val
+ runStack.pop(); // remove from stack
+}
+
+
+void Executer::execReturn(TreeNode* node)
+{
+ execute( node->firstChild() ); // execute return expression
+ runStack.push( node->firstChild()->getValue() );
+ bReturn = true; // notify blocks of return
+}
+
+
+void Executer::execBreak(/*TreeNode* node*/)
+{
+ bBreak = true; // stops loop block execution
+}
+
+
+void Executer::execBlock(TreeNode* node)
+{
+ // execute all statements in block
+ TreeNode::iterator i;
+ for (i = node->begin(); i != node->end(); ++i)
+ {
+ if (runSpeed != 0) slowDown(*i);
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ execute(*i);
+
+ if (bReturn || bBreak) break; //jump out of block
+ }
+}
+
+
+void Executer::execForEach(TreeNode* node)
+{
+ // sorry, not fully implemented/tested yet
+ TreeNode* expr1 = node->firstChild();
+ TreeNode* expr2 = node->secondChild();
+ TreeNode* statements = node->thirdChild();
+
+ execute(expr1);
+ execute(expr2);
+
+ QString expStr1 = expr1->getValue().String();
+ QString expStr2 = expr2->getValue().String();
+
+ bBreak = false;
+
+ int i = expStr2.contains(expStr1, false);
+ for ( ; i > 0; i-- )
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ execute(statements);
+ if (bBreak || bReturn) break; //jump out loop
+ }
+ bBreak = false;
+}
+
+
+
+void Executer::execFor(TreeNode* node)
+{
+ TreeNode* id = node->firstChild();
+ TreeNode* startNode = node->secondChild();
+ TreeNode* stopNode = node->thirdChild();
+ TreeNode* statements = node->fourthChild();
+
+ QString name = id->getLook();
+
+ execute(startNode);
+ //assign startval to id
+ Value startVal = startNode->getValue();
+ ( symbolTables.top() )[ name ] = startVal;
+
+
+ execute(stopNode);
+ Value stopVal = stopNode->getValue();
+
+ if(node->size() == 4 ) //for loop without step part
+ {
+ bBreak = false;
+ for (double d = startVal.Number(); d <= stopVal.Number(); d = d + 1)
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+ ( symbolTables.top() )[name] = d;
+ execute( statements );
+ if (bBreak || bReturn) break; //jump out loop
+ }
+ bBreak = false;
+ }
+ else //for loop with step part
+ {
+ TreeNode* step = node->fourthChild();
+ statements = node->fifthChild();
+
+ execute(step);
+ Value stepVal = step->getValue();
+ bBreak = false;
+ if ( (stepVal.Number() >= 0.0) && (startVal.Number() <= stopVal.Number() ) )
+ {
+ for ( double d = startVal.Number(); d <= stopVal.Number(); d = d + stepVal.Number() )
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ (symbolTables.top() )[name] = d;
+ execute( statements );
+ if (bBreak || bReturn) break; //jump out loop
+ }
+ }
+ else if ( (stepVal.Number() < 0.0) && (startVal.Number() >= stopVal.Number() ) )
+ {
+ for (double d = startVal.Number(); d >= stopVal.Number(); d = d + stepVal.Number() )
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ ( symbolTables.top() )[name] = d;
+ execute(statements);
+ if (bBreak || bReturn) break; //jump out loop
+ }
+ }
+ bBreak = false;
+ }
+}
+
+
+
+void Executer::execRepeat(TreeNode* node)
+{
+ TreeNode* value = node->firstChild();
+ TreeNode* statements = node->secondChild();
+
+ bBreak = false;
+ execute(value);
+ for ( int i = ROUND2INT( value->getValue().Number() ); i > 0; i-- )
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ execute(statements);
+ if (bBreak || bReturn) break; //jump out loop
+ }
+ bBreak = false;
+}
+
+
+void Executer::execWhile(TreeNode* node)
+{
+ TreeNode* condition = node->firstChild();
+ TreeNode* statements = node->secondChild();
+
+ bBreak = false;
+ execute(condition);
+ while (condition->getValue().Number() != 0)
+ {
+ if (bAbort) return;
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ execute(statements);
+ if (bBreak || bReturn) break; //jump out loop
+ execute(condition);
+ }
+ bBreak = false;
+}
+
+
+void Executer::execIf(TreeNode* node)
+{
+ TreeNode* condition = node->firstChild();
+ TreeNode* ifblok = node->secondChild();
+
+ //determine if there is an else part
+ if (node->size() == 2) // no else
+ {
+ execute( condition );
+ if( condition->getValue().Number() != 0 ) execute(ifblok);
+ }
+ else // else part given
+ {
+ TreeNode* elseblok = node->thirdChild();
+ execute( condition );
+ if( condition->getValue().Number() != 0 ) execute(ifblok);
+ else execute( elseblok );
+ }
+}
+
+
+
+void Executer::execAssign(TreeNode* node)
+{
+ TreeNode* expr = node->firstChild();
+
+ execute(expr);
+ ( symbolTables.top() )[ node->getLook() ] = expr->getValue();
+}
+
+void Executer::execExpression(/*TreeNode* node*/)
+{
+ // execExpression is not implemented, because it should not be needed!
+}
+
+void Executer::execId(TreeNode* node)
+{
+ node->setValue( ( symbolTables.top() )[ node->getLook() ] );
+}
+
+void Executer::execConstant(/*TreeNode* node*/)
+{
+ // do nothing, value is already set
+}
+
+Value Executer::exec2getValue(TreeNode* node)
+{
+ execute(node);
+ return node->getValue();
+}
+
+
+void Executer::execAdd(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ if (left.Type() == numberValue && right.Type() == numberValue) node->setValue( left + right );
+ else node->setValue( left.String().append( right.String() ) );
+}
+
+
+void Executer::execMul(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ if (left.Type() == numberValue && right.Type() == numberValue) node->setValue( left * right );
+ else emit ErrorMsg(node->getToken(), i18n("Can only multiply numbers."), 9000);
+}
+
+
+void Executer::execDiv(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ if (left.Type() == numberValue && right.Type() == numberValue)
+ {
+ if (right.Number() == 0) emit ErrorMsg(node->getToken(), i18n("Cannot divide by zero."), 9000);
+ else node->setValue( left / right );
+ }
+ else emit ErrorMsg(node->getToken(), i18n("Can only divide numbers."), 9000);
+}
+
+
+void Executer::execSub(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ if (left.Type() == numberValue && right.Type() == numberValue)
+ node->setValue( left - right );
+
+ else emit ErrorMsg(node->getToken(), i18n("Can only subtract numbers."), 9000);
+}
+
+
+
+void Executer::execLT(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left < right );
+}
+
+void Executer::execLE(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left <= right );
+}
+
+void Executer::execGT(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left > right );
+}
+
+void Executer::execGE(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left >= right );
+}
+
+
+void Executer::execEQ(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left == right );
+}
+
+
+void Executer::execNE(TreeNode* node)
+{
+ Value left( exec2getValue( node->firstChild() ) );
+ Value right( exec2getValue( node->secondChild() ) );
+
+ node->setValue( left != right );
+}
+
+
+
+void Executer::execAnd(TreeNode* node)
+{
+ bool nl = exec2getValue( node->firstChild() ).Number() != 0;
+ bool nr = exec2getValue( node->secondChild() ).Number() != 0;
+ node->setValue( (double) (nl && nr) );
+}
+
+
+void Executer::execOr(TreeNode* node)
+{
+ bool nl = exec2getValue( node->firstChild() ).Number() != 0;
+ bool nr = exec2getValue( node->secondChild() ).Number() != 0;
+ node->setValue(nl || nr);
+}
+
+
+void Executer::execNot(TreeNode* node)
+{
+ node->setValue( exec2getValue( node->firstChild() ).Number() == 0 );
+}
+
+
+void Executer::execMinus(TreeNode* node)
+{
+ node->setValue( -exec2getValue( node->firstChild() ).Number() );
+}
+
+
+QString Executer::runCommand(const QString& command)
+{
+ FILE *pstream;
+
+ if ( ( pstream = popen( command.ascii(), "r" ) ) == NULL ) return ("");
+
+ QString Line;
+ char buf[100];
+
+ while( fgets(buf, sizeof(buf), pstream) !=NULL) {
+ if (bAbort) return ("");
+ kapp->processEvents();
+
+ Line += buf;
+ }
+ pclose(pstream);
+ return Line;
+}
+
+
+void Executer::execRun(TreeNode* node)
+{
+ QString cmd = exec2getValue( node->firstChild() ).String();
+ node->setValue( runCommand(cmd) );
+}
+
+
+
+
+void Executer::execClear(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit Clear();
+}
+
+void Executer::execCenter(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit Center();
+}
+
+void Executer::execPenUp(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit PenUp();
+}
+
+void Executer::execPenDown(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit PenDown();
+}
+
+void Executer::execSpriteShow(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit SpriteShow();
+}
+
+void Executer::execSpriteHide(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit SpriteHide();
+}
+
+void Executer::execSpritePress(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit SpritePress();
+}
+
+void Executer::execWrapOn(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit WrapOn();
+}
+
+void Executer::execWrapOff(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit WrapOff();
+}
+
+void Executer::execReset(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 0, 5060) ) emit Reset();
+}
+
+void Executer::execMessage(TreeNode* node)
+{
+ if ( checkParameterQuantity(node, 1, 5060) && checkParameterType(node, stringValue, 5060) )
+ emit MessageDialog( node->firstChild()->getValue().String() );
+}
+
+
+
+
+
+
+void Executer::execGoX(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit GoX( param1->getValue().Number() );
+ }
+}
+
+void Executer::execGoY(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit GoY( param1->getValue().Number() );
+ }
+}
+
+void Executer::execForward(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit Forward( param1->getValue().Number() );
+ }
+}
+
+void Executer::execBackward(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit Backward( param1->getValue().Number() );
+ }
+}
+
+void Executer::execDirection(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit Direction( param1->getValue().Number() );
+ }
+}
+
+void Executer::execTurnLeft(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit TurnLeft( param1->getValue().Number() );
+ }
+}
+
+void Executer::execTurnRight(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit TurnRight( param1->getValue().Number() );
+ }
+}
+
+void Executer::execSetPenWidth(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
+ if (x < 1 || x > 10000)
+ emit ErrorMsg(node->getToken(), i18n("The penwidth cannot be set to something smaller than 1, or bigger than 10000."), 6050);
+ else
+ emit SetPenWidth(x);
+ }
+}
+
+void Executer::execSpriteChange(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
+ emit SpriteChange(x);
+ }
+}
+
+void Executer::execFontSize(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int x = ROUND2INT( param1->getValue().Number() ); // pull the number value & round it to int
+ if ( x < 0 || x > 350 )
+ emit ErrorMsg(node->getToken(), i18n("The parameters of function %1 must be within range: 0 to 350.").arg( node->getLook() ), 5065);
+ else
+ emit FontSize(x);
+ }
+}
+
+
+
+
+
+
+void Executer::execGo(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 2, 5060) ) return;
+ TreeNode* nodeX = node->firstChild(); // getting
+ TreeNode* nodeY = node->secondChild();
+ execute(nodeX); // executing
+ execute(nodeY);
+
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ emit Go( nodeX->getValue().Number(), nodeY->getValue().Number() );
+ }
+}
+
+void Executer::execResizeCanvas(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 2, 5060) ) return;
+ TreeNode* nodeX = node->firstChild(); // getting
+ TreeNode* nodeY = node->secondChild();
+ execute(nodeX); // executing
+ execute(nodeY);
+
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int x = ROUND2INT( nodeX->getValue().Number() ); // converting & rounding to int
+ int y = ROUND2INT( nodeY->getValue().Number() );
+ if ( ( x < 1 || y < 1 ) || ( x > 10000 || y > 10000 ) )
+ emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 1 to 10000.").arg( node->getLook() ), 7030);
+ else
+ emit ResizeCanvas(x, y);
+ }
+}
+
+void Executer::execRandom(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 2, 5060) ) return;
+ TreeNode* nodeX = node->firstChild(); // getting
+ TreeNode* nodeY = node->secondChild();
+ execute(nodeX); // executing
+ execute(nodeY);
+
+ if ( !checkParameterType(node, numberValue, 5060) ) return;
+ double x = nodeX->getValue().Number();
+ double y = nodeY->getValue().Number();
+ double r = (double)( KApplication::random() ) / RAND_MAX;
+ node->setValue( r * ( y - x ) + x );
+}
+
+
+
+
+
+void Executer::execSetFgColor(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 3, 5060) ) return;
+ TreeNode* nodeR = node->firstChild(); // getting
+ TreeNode* nodeG = node->secondChild();
+ TreeNode* nodeB = node->thirdChild();
+ execute(nodeR); // executing
+ execute(nodeG);
+ execute(nodeB);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int r = ROUND2INT( nodeR->getValue().Number() ); // converting & rounding to int
+ int g = ROUND2INT( nodeG->getValue().Number() );
+ int b = ROUND2INT( nodeB->getValue().Number() );
+ if ( ( r < 0 || g < 0 || b < 0 ) || ( r > 255 || g > 255 || b > 255 ) )
+ emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 0 to 255.").arg( node->getLook() ), 6090);
+ else
+ emit SetFgColor(r, g, b);
+ }
+}
+
+void Executer::execSetBgColor(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 3, 5060) ) return;
+ TreeNode* nodeR = node->firstChild(); // getting
+ TreeNode* nodeG = node->secondChild();
+ TreeNode* nodeB = node->thirdChild();
+ execute(nodeR); // executing
+ execute(nodeG);
+ execute(nodeB);
+ if ( checkParameterType(node, numberValue, 5060) )
+ {
+ int r = ROUND2INT( nodeR->getValue().Number() ); // converting & rounding to int
+ int g = ROUND2INT( nodeG->getValue().Number() );
+ int b = ROUND2INT( nodeB->getValue().Number() );
+ if ( ( r < 0 || g < 0 || b < 0 ) || ( r > 255 || g > 255 || b > 255 ) )
+ emit ErrorMsg(node->getToken(), i18n("The parameters of the %1 command must be numbers in the range: 0 to 255.").arg( node->getLook() ), 6090);
+ else
+ emit SetBgColor(r, g, b);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+void Executer::execInputWindow(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+
+ QString value = node->firstChild()->getValue().String();
+ emit InputDialog(value);
+
+ node->setType(constantNode);
+ if ( value.isEmpty() ) node->getValue().resetValue(); // set value back to empty
+ else
+ {
+ bool ok = true;
+ double num = value.toDouble(&ok); // to see if the value from the InpDialog is a float
+ if (ok) node->setValue(num);
+ else node->setValue(value);
+ }
+}
+
+void Executer::execPrint(TreeNode* node)
+{
+ if (node->size() == 0)
+ {
+ emit ErrorMsg(node->getToken(), i18n("The print command needs input"), 5050);
+ return;
+ }
+ TreeNode::iterator i;
+ QString str = "";
+ for (i = node->begin(); i != node->end(); ++i)
+ {
+ execute(*i); // execute expression
+ str = str + (*i)->getValue().String();
+ }
+ emit Print(str);
+}
+
+void Executer::execFontType(TreeNode* node)
+{
+ // if not 2 params go staight to the checkParam, diplay the error, and return to prevent a crash
+ if ( !checkParameterQuantity(node, 2, 5060) && !checkParameterType(node, stringValue, 5060) ) return;
+
+ QString extra;
+ if (node->size() == 2) QString extra = node->secondChild()->getValue().String();
+ QString family = node->firstChild()->getValue().String();
+ emit FontType(family, extra);
+}
+
+
+void Executer::execWait(TreeNode* node)
+{
+ if ( !checkParameterQuantity(node, 1, 5060) ) return;
+ TreeNode* param1 = node->firstChild();
+ execute(param1);
+ if ( !checkParameterType(node, numberValue, 5060) ) return;
+ int msec = (int)( 1000 * param1->getValue().Number() );
+ startWaiting(msec);
+}
+
+void Executer::startWaiting(int msec)
+{
+ bStopWaiting = false;
+ // call a timer that sets stopWaiting to true when it runs
+ QTimer::singleShot( msec, this, SLOT( slotStopWaiting() ) );
+ while (bStopWaiting == false)
+ {
+ if (bAbort) return; // waits need to be interrupted by the stop action
+ if (bPause) startPausing();
+ kapp->processEvents();
+
+ // only 10 times per second is enough... else the CPU gets 100% loaded ( not nice :)
+ usleep(100000);
+ }
+}
+
+void Executer::slotStopWaiting()
+{
+ bStopWaiting = true;
+}
+
+void Executer::startPausing()
+{
+ while (bPause == true)
+ {
+ if (bAbort) return; // waits need to be interrupted by the stop action
+ kapp->processEvents();
+ // only 10 times per second is enough... else the CPU gets 100% loaded ( not nice :)
+ usleep(100000);
+ }
+}
+
+void Executer::slotStopPausing()
+{
+ bPause = false;
+}
+
+
+
+
+bool Executer::checkParameterQuantity(TreeNode* node, uint quantity, int errorCode)
+{
+ if (quantity == 0)
+ {
+ if (node->size() == 0) return true; // thats easy!
+ emit ErrorMsg(node->getToken(), i18n("The %1 command accepts no parameters.").arg( node->getLook() ), errorCode);
+ return false;
+ }
+
+ uint nodeSize = node->size();
+ if (nodeSize != 0) // when all parameters are forgotten the parser puts a Unknown/tokEOL param, catch this:
+ if (node->firstChild()->getToken().type == tokEOL) nodeSize = 0;
+
+ if (nodeSize != quantity)
+ {
+ if (nodeSize < quantity)
+ {
+ 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);
+ }
+ else
+ {
+ 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);
+ }
+ return false;
+ }
+ return true; // if all tests passed
+}
+
+
+bool Executer::checkParameterType(TreeNode* node, int valueType, int errorCode)
+{
+ uint quantity = node->size();
+ uint ii = 1;
+ TreeNode::iterator i = node->begin();
+ while ( i != node->end() && ii <= quantity )
+ {
+ if ( (*i)->getValue().Type() != valueType )
+ {
+ switch (valueType)
+ {
+ case stringValue:
+ if (quantity == 1)
+ emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts a string as its parameter.").arg( node->getLook() ), errorCode);
+ else
+ emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts strings as its parameters.").arg( node->getLook() ), errorCode);
+ break;
+
+ case numberValue:
+ if (quantity == 1)
+ emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts a number as its parameter.").arg( node->getLook() ), errorCode);
+ else
+ emit ErrorMsg(node->getToken(), i18n("The %1 command only accepts numbers as its parameters.").arg( node->getLook() ), errorCode);
+ break;
+ }
+ return false;
+ }
+ ++i;
+ ii++;
+ }
+ return true; // if all tests passed
+}
+
+#include "executer.moc"
diff --git a/kturtle/src/executer.h b/kturtle/src/executer.h
new file mode 100644
index 00000000..ac9a1f1b
--- /dev/null
+++ b/kturtle/src/executer.h
@@ -0,0 +1,186 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _EXECUTER_H_
+#define _EXECUTER_H_
+
+#include <stack>
+#include <map>
+
+#include "token.h"
+#include "treenode.h"
+
+
+typedef map<QString,Value> symtable;
+typedef map<QString,TreeNode*> functable;
+
+typedef stack<Value> runstack;
+
+
+class Executer : public QObject
+{
+ Q_OBJECT
+
+ public:
+ Executer(TreeNode*);
+ virtual ~Executer();
+
+ bool run();
+ void pause();
+ void abort();
+
+
+ signals:
+ void Finished();
+ void ErrorMsg(Token&, const QString&, uint code);
+ void setSelection(uint, uint, uint, uint);
+
+ void InputDialog(QString& value);
+ void MessageDialog(QString text);
+
+ void Clear();
+ void Go(double x, double y);
+ void GoX(double x);
+ void GoY(double y);
+ void Forward(double x);
+ void Backward(double x);
+ void Direction(double x);
+ void TurnLeft(double x);
+ void TurnRight(double x);
+ void Center();
+ void SetPenWidth(int w);
+ void PenUp();
+ void PenDown();
+ void SetFgColor(int r, int g, int b);
+ void SetBgColor(int r, int g, int b);
+ void ResizeCanvas(int x, int y);
+ void SpriteShow();
+ void SpriteHide();
+ void SpritePress();
+ void SpriteChange(int x);
+ void Print(QString text);
+ void FontType(QString family, QString extra);
+ void FontSize(int px);
+ void WrapOn();
+ void WrapOff();
+ void Reset();
+
+
+ private:
+ void execute (TreeNode*);
+
+ void execBlock (TreeNode*);
+ void execFor (TreeNode*);
+ void execForEach (TreeNode*);
+ void execWhile (TreeNode*);
+ void execIf (TreeNode*);
+ void execAssign (TreeNode*);
+ void execExpression (/*TreeNode*/);
+ void execId (TreeNode*);
+ void execConstant (/*TreeNode*/);
+
+ void createFunction (TreeNode*);
+ void execFunction (TreeNode*);
+ void execRetFunction (TreeNode*);
+ void execReturn (TreeNode*);
+ void execBreak (/*TreeNode*/);
+
+ void execAdd (TreeNode*);
+ void execMul (TreeNode*);
+ void execDiv (TreeNode*);
+ void execSub (TreeNode*);
+ void execNot (TreeNode*);
+
+ void execGE (TreeNode*);
+ void execGT (TreeNode*);
+ void execLE (TreeNode*);
+ void execLT (TreeNode*);
+ void execNE (TreeNode*);
+ void execEQ (TreeNode*);
+
+ void execAnd (TreeNode*);
+ void execOr (TreeNode*);
+ void execMinus (TreeNode*);
+
+ void execRun (TreeNode*);
+
+ void execClear (TreeNode*);
+ void execGo (TreeNode*);
+ void execGoX (TreeNode*);
+ void execGoY (TreeNode*);
+ void execForward (TreeNode*);
+ void execBackward (TreeNode*);
+ void execDirection (TreeNode*);
+ void execTurnLeft (TreeNode*);
+ void execTurnRight (TreeNode*);
+ void execCenter (TreeNode*);
+ void execSetPenWidth (TreeNode*);
+ void execPenUp (TreeNode*);
+ void execPenDown (TreeNode*);
+ void execSetFgColor (TreeNode*);
+ void execSetBgColor (TreeNode*);
+ void execResizeCanvas (TreeNode*);
+ void execSpriteShow (TreeNode*);
+ void execSpriteHide (TreeNode*);
+ void execSpritePress (TreeNode*);
+ void execSpriteChange (TreeNode*);
+
+ void execMessage (TreeNode*);
+ void execInputWindow (TreeNode*);
+ void execPrint (TreeNode*);
+ void execFontType (TreeNode*);
+ void execFontSize (TreeNode*);
+ void execRepeat (TreeNode*);
+ void execRandom (TreeNode*);
+ void execWait (TreeNode*);
+ void execWrapOn (TreeNode*);
+ void execWrapOff (TreeNode*);
+ void execReset (TreeNode*);
+
+ Value exec2getValue (TreeNode*);
+
+ QString runCommand(const QString&);
+
+ bool checkParameterQuantity(TreeNode*, uint quantity, int errorCode);
+ bool checkParameterType(TreeNode*, int valueType, int errorCode);
+
+ void slowDown(TreeNode*);
+ void startWaiting(int msec);
+ void startPausing();
+
+ // private locals
+ TreeNode* tree;
+ stack<symtable> symbolTables;
+ functable functionTable; // keep track of functionNode's
+ runstack runStack; // stores parameters and return value of functions
+
+ int runSpeed;
+ bool bReturn; // used for return statements
+ bool bBreak; // used for break statement
+ bool bPause; // used to pause execution
+ bool bAbort; // used to abort execution
+ bool bStopWaiting; // used for wait-command
+
+
+ private slots:
+ void slotStopWaiting();
+ void slotChangeSpeed(int speed);
+ void slotStopPausing();
+};
+
+#endif // _EXECUTER_H_
diff --git a/kturtle/src/hi16-app-kturtle.png b/kturtle/src/hi16-app-kturtle.png
new file mode 100644
index 00000000..dd4a9575
--- /dev/null
+++ b/kturtle/src/hi16-app-kturtle.png
Binary files differ
diff --git a/kturtle/src/hi32-app-kturtle.png b/kturtle/src/hi32-app-kturtle.png
new file mode 100644
index 00000000..959c933e
--- /dev/null
+++ b/kturtle/src/hi32-app-kturtle.png
Binary files differ
diff --git a/kturtle/src/kturtle.cpp b/kturtle/src/kturtle.cpp
new file mode 100644
index 00000000..2cc7c5ff
--- /dev/null
+++ b/kturtle/src/kturtle.cpp
@@ -0,0 +1,1181 @@
+/*
+ * KTurtle, Copyright (C) 2003-04 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+// BEGIN includes and defines
+
+#include <stdlib.h>
+
+#include <qbutton.h>
+#include <qregexp.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kconfigdialog.h>
+#include <kdebug.h>
+#include <kedittoolbar.h>
+#include <kfiledialog.h>
+#include <kimageio.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kmenubar.h>
+#include <kprinter.h>
+#include <ksavefile.h>
+#include <kstatusbar.h>
+
+#include <ktexteditor/clipboardinterface.h>
+#include <ktexteditor/cursorinterface.h>
+#include <ktexteditor/editorchooser.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/highlightinginterface.h>
+#include <ktexteditor/printinterface.h>
+#include <ktexteditor/selectioninterface.h>
+#include <ktexteditor/undointerface.h>
+#include <ktexteditor/viewcursorinterface.h>
+#include <ktexteditor/encodinginterface.h>
+
+#include "lexer.h"
+#include "settings.h"
+#include "translate.h"
+
+#include "kturtle.h"
+
+// StatusBar field IDs
+#define IDS_STATUS 0
+#define IDS_LINECOLUMN 2
+#define IDS_INS 3
+#define IDS_LANG 4
+
+// END
+
+
+
+// BEGIN constructor and destructor
+
+MainWindow::MainWindow(KTextEditor::Document *document) : editor(0)
+{
+ // the initial values
+ CurrentFile = KURL(); // fill with empty URL
+ setCaption( i18n("Untitled") );
+ picker = 0; // for the colorpickerdialog
+ executing = false;
+ b_fullscreen = false;
+
+ // set the shell's ui resource file
+ if (!document)
+ {
+ if ( !(document = KTextEditor::EditorChooser::createDocument(0,"KTextEditor::Document") ) )
+ {
+ KMessageBox::error( this, i18n("A KDE text-editor component could not be found;\n"
+ "please check your KDE installation.") );
+ kapp->exit(1);
+ }
+ // docList.append(doc);
+ }
+ doc = document;
+
+ setupCanvas();
+ setupEditor();
+
+ setupStatusBar();
+ setupActions();
+ createShellGUI(true);
+ setMinimumSize(200,200);
+
+ // init with more usefull size, stolen from kwite (they stole it from konq)
+ if ( !initialGeometrySet() && !kapp->config()->hasGroup("MainWindow Settings") ) resize(640, 480);
+
+ KConfig *config = kapp->config();
+ readConfig(config);
+}
+
+MainWindow::~MainWindow()
+{
+ delete editor->document();
+}
+
+// END
+
+
+
+// BEGIN setup's (actions, editor, statusbar, canvas)
+
+void MainWindow::setupActions()
+{
+ KActionCollection *ac = actionCollection(); // abbreviation
+
+ // File actions
+ KStdAction::openNew(this, SLOT(slotNewFile()), ac);
+ openExAction = new KAction(i18n("Open Exa&mples..."), "bookmark_folder", CTRL+Key_E, this, SLOT(slotOpenExample()), ac, "open_examples");
+ KStdAction::open(this, SLOT(slotOpenFile()), ac);
+ m_recentFiles = KStdAction::openRecent(this, SLOT(slotOpenFile(const KURL&)), ac);
+ KStdAction::save(this, SLOT(slotSaveFile()), ac);
+ KStdAction::saveAs(this, SLOT(slotSaveAs()), ac);
+ new KAction(i18n("Save &Canvas..."), 0, 0, this, SLOT(slotSaveCanvas()), ac, "save_canvas");
+ speed = new KSelectAction(i18n("Execution Speed"), 0, ALT+Key_S, this, SLOT( slotChangeSpeed() ), ac, "speed");
+ QStringList speeds; speeds << i18n("Full Speed") << i18n("Slow") << i18n("Slower") << i18n("Slowest");
+ speed->setItems(speeds);
+ speed->setCurrentItem(0);
+ run = new KAction(i18n("&Execute Commands"), "gear", ALT+Key_Return, this, SLOT( slotExecute() ), ac, "run");
+ pause = new KToggleAction(i18n("Pause E&xecution"), "player_pause", Key_Pause, this, SLOT( slotPauseExecution() ), ac, "pause");
+ pause->setChecked(false);
+ pause->setEnabled(false);
+ stop = new KAction(i18n("Stop E&xecution"), "stop", Key_Escape, this, SLOT( slotAbortExecution() ), ac, "stop");
+ stop->setEnabled(false);
+ KStdAction::print(this, SLOT(slotPrint()), ac);
+ KStdAction::quit(this, SLOT(close()), ac);
+
+ // Edit actions
+ KStdAction::undo(this, SLOT(slotUndo()), ac);
+ KStdAction::redo(this, SLOT(slotRedo()), ac);
+ KStdAction::cut(this, SLOT(slotCut()), ac);
+ KStdAction::copy(this, SLOT(slotCopy()), ac);
+ KStdAction::paste(this, SLOT(slotPaste()), ac);
+ KStdAction::selectAll(this, SLOT(slotSelectAll()), ac);
+ KStdAction::deselect(this, SLOT(slotClearSelection()), ac);
+ new KToggleAction(i18n("Toggle Insert"), Key_Insert, this, SLOT(slotToggleInsert()), ac, "set_insert");
+ KStdAction::find(this, SLOT(slotFind()), ac);
+ KStdAction::findNext(this, SLOT(slotFindNext()), ac);
+ KStdAction::findPrev(this, SLOT(slotFindPrevious()), ac);
+ KStdAction::replace(this, SLOT(slotReplace()), ac);
+
+ // View actions
+ new KToggleAction(i18n("Show &Line Numbers"), 0, Key_F11, this, SLOT(slotToggleLineNumbers()), ac, "line_numbers");
+ m_fullscreen = KStdAction::fullScreen(this, SLOT(slotToggleFullscreen()), ac, this, "full_screen");
+ m_fullscreen->setChecked(b_fullscreen);
+
+ // Tools actions
+ colorpicker = new KToggleAction(i18n("&Color Picker"), "colorize", ALT+Key_C, this, SLOT(slotColorPicker()), ac, "color_picker");
+ new KAction(i18n("&Indent"), "indent", CTRL+Key_I, this, SLOT(slotIndent()), ac, "edit_indent");
+ new KAction(i18n("&Unindent"), "unindent", CTRL+SHIFT+Key_I, this, SLOT(slotUnIndent()), ac, "edit_unindent");
+ new KAction(i18n("Cl&ean Indentation"), 0, 0, this, SLOT(slotCleanIndent()), ac, "edit_cleanIndent");
+ new KAction(i18n("Co&mment"), 0, CTRL+Key_D, this, SLOT(slotComment()), ac, "edit_comment");
+ new KAction(i18n("Unc&omment"), 0, CTRL+SHIFT+Key_D, this, SLOT(slotUnComment()), ac, "edit_uncomment");
+
+ // Settings actions
+ KStdAction::preferences( this, SLOT(slotSettings()), ac );
+ new KAction(i18n("&Configure Editor..."), "configure", 0, this, SLOT(slotEditor()), ac, "set_confdlg");
+
+ // Help actions
+ ContextHelp = new KAction(0, 0, Key_F2, this, SLOT(slotContextHelp()), ac, "context_help");
+ slotContextHelpUpdate(); // this sets the label of this action
+
+ // other
+ setXMLFile("kturtleui.rc");
+ setupGUI();
+}
+
+void MainWindow::setupEditor()
+{
+ editorDock = new QDockWindow(this);
+ editorDock->setNewLine(true);
+ editorDock->setFixedExtentWidth(250);
+ editorDock->setFixedExtentHeight(150);
+ editorDock->setResizeEnabled(true);
+ editorDock->setFrameShape(QFrame::ToolBarPanel);
+ QWhatsThis::add( editorDock, i18n( "This is the code editor, here you type the Logo commands to instruct the turtle. You can also open an existing Logo program with File->Open Examples... or File->Open." ) );
+ moveDockWindow(editorDock, Qt::DockLeft);
+ editor = doc->createView (editorDock, 0L);
+ // editorInterface is the editor interface which allows us to access the text in the part
+ editorInterface = dynamic_cast<KTextEditor::EditInterface*>(doc);
+ dynamic_cast<KTextEditor::EncodingInterface*>(doc)->setEncoding("UTF-8");
+ editorDock->setWidget(editor);
+
+ // default the highlightstyle to "logo" using the needed i18n
+ kdDebug(0)<<"The HighlightStyle for the Code Editor: "<<Settings::logoLanguage()<<endl;
+ slotSetHighlightstyle( Settings::logoLanguage() );
+
+ // allow the cursor position to be indicated in the statusbar
+ connect( editor, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorStatusBar()) );
+ // and update the context help menu item
+ connect( editor, SIGNAL(cursorPositionChanged()), this, SLOT(slotContextHelpUpdate()) );
+
+ translate = new Translate();
+}
+
+void MainWindow::setupStatusBar()
+{
+ statusBar()->insertItem("", IDS_STATUS, 1, false);
+ statusBar()->setItemAlignment(IDS_STATUS, AlignLeft);
+ statusBar()->insertItem("", IDS_LANG, 0, true);
+ statusBar()->insertItem("", IDS_LINECOLUMN, 0, true);
+ statusBar()->insertItem("", IDS_INS, 0, true);
+
+ // fill the statusbar
+ slotStatusBar(i18n("Welcome to KTurtle..."), IDS_STATUS); // the message part
+ slotStatusBar(i18n("Line: %1 Column: %2").arg(1).arg(1), IDS_LINECOLUMN);
+ slotStatusBar(i18n("INS"), IDS_INS);
+}
+
+void MainWindow::setupCanvas()
+{
+ baseWidget = new QWidget(this);
+ setCentralWidget(baseWidget);
+ baseLayout = new QGridLayout(baseWidget, 0, 0);
+ canvasView = new Canvas(baseWidget);
+ baseLayout->addWidget(canvasView, 0, 0, AlignCenter);
+ baseLayout->setRowStretch(0, 1); // this apperntly fixes a pre-usefull scrollbars bug
+ baseLayout->setColStretch(0, 1);
+ QWhatsThis::add( canvasView, i18n("This is the canvas, here the turtle draws a picture.") );
+ canvasView->show();
+ connect( canvasView, SIGNAL( CanvasResized() ), this, SLOT( slotUpdateCanvas() ) );
+}
+
+// END
+
+
+
+// BEGIN staturbar related functions
+
+void MainWindow::slotStatusBar(QString text, int id)
+{
+ text = " " + text + " "; // help the layout
+ statusBar()->changeItem(text, id);
+}
+
+void MainWindow::slotCursorStatusBar()
+{
+ uint cursorLine;
+ uint cursorCol;
+ dynamic_cast<KTextEditor::ViewCursorInterface*>(editor)->cursorPositionReal(&cursorLine, &cursorCol);
+ QString linenumber = i18n(" Line: %1 Column: %2 ").arg(cursorLine + 1).arg(cursorCol + 1);
+ statusBar()->changeItem(linenumber, IDS_LINECOLUMN);
+}
+
+// END
+
+
+
+// BEGIN file menu related fuctions (new, open, save()as, image, print, quit)
+
+void MainWindow::slotNewFile()
+{
+ if ( !editor->document()->isModified() && CurrentFile.isEmpty() ) return; // do nothing when nothing can be done
+ if ( editor->document()->isModified() )
+ {
+ int result = KMessageBox::warningContinueCancel( this,
+ i18n("The program you are currently working on is not saved. "
+ "By continuing you may lose the changes you have made."),
+ i18n("Unsaved File"), i18n("&Discard Changes") );
+ if (result != KMessageBox::Continue) return;
+ }
+ editorInterface->clear(); // clear the editor
+ canvasView->slotClear(); // clear the view
+ editor->document()->setModified(false);
+ CurrentFile = KURL();
+ setCaption( i18n("Untitled") );
+ slotStatusBar(i18n("New file... Happy coding!"), IDS_STATUS);
+}
+
+
+
+void MainWindow::slotOpenFile(const KURL &urlRef)
+{
+ KURL url = urlRef;
+ if ( url.isEmpty() )
+ {
+ url = KFileDialog::getOpenURL( QString(":logo_dir"), QString("*.logo|") + i18n("Logo Files"), this, i18n("Open Logo File") );
+ }
+ loadFile(url);
+}
+
+void MainWindow::slotOpenExample()
+{
+ KURL url;
+ url.setPath( locate("data", "kturtle/examples/" + Settings::logoLanguage() + "/") );
+ url = KFileDialog::getOpenURL( url.path(), QString("*.logo|") + i18n("Logo Examples Files"), this, i18n("Open Logo Example File") );
+ loadFile(url);
+}
+
+void MainWindow::loadFile(const KURL &url)
+{
+ if ( !url.isEmpty() )
+ {
+ QFile file( url.path() );
+ if ( file.open(IO_ReadOnly) )
+ {
+ if ( editor->document()->isModified() )
+ {
+ int result = KMessageBox::warningContinueCancel( this,
+ i18n("The program you are currently working on is not saved. "
+ "By continuing you may lose the changes you have made."),
+ i18n("Unsaved File"), i18n("&Discard Changes") );
+ if (result != KMessageBox::Continue)
+ {
+ slotStatusBar(i18n("Opening aborted, nothing opened."), IDS_STATUS);
+ return;
+ }
+ }
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ editorInterface->setText( stream.read() );
+ file.close();
+ m_recentFiles->addURL(url);
+ setCaption( url.fileName() );
+ slotStatusBar(i18n("Opened file: %1").arg( url.fileName() ), IDS_STATUS);
+ editor->document()->setModified(false);
+ CurrentFile = url;
+ return;
+ }
+ else
+ {
+ KMessageBox::error( this,
+ i18n("KTurtle was unable to open: \n%1.").arg( url.prettyURL() ),
+ i18n("Open Error") );
+ slotStatusBar(i18n("Opening aborted because of error."), IDS_STATUS);
+ return;
+ }
+ }
+ slotStatusBar(i18n("Opening aborted."), IDS_STATUS); // fallback
+}
+
+void MainWindow::slotSaveFile()
+{
+ writeFile(CurrentFile);
+}
+
+void MainWindow::slotSaveAs()
+{
+ KURL url;
+ while (true)
+ {
+ url = KFileDialog::getSaveURL( QString(":logo_dir"), QString("*.logo|") + i18n("Logo Files"), this, i18n("Save As") );
+ if ( url.isEmpty() ) // cancelled the save dialog
+ {
+ slotStatusBar(i18n("Saving aborted."), IDS_STATUS);
+ return;
+ }
+ if ( QFile( url.path() ).exists() )
+ {
+ int result = KMessageBox::warningContinueCancel ( this,
+ i18n("A program named \"%1\" already exists in this folder. "
+ "Do you want to overwrite it?").arg( url.fileName() ),
+ i18n("Overwrite?"), i18n("&Overwrite") );
+ if (result != KMessageBox::Continue) return;
+ }
+ break;
+ }
+ writeFile(url);
+}
+
+void MainWindow::writeFile(const KURL &url)
+{
+ if ( url.isEmpty() ) slotSaveAs();
+ else
+ {
+ editor->document()->saveAs(url); // use the KateParts method for saving
+ loadFile(url); // reload the file as utf8 otherwise display weird chars
+ setCaption( url.fileName() );
+ slotStatusBar(i18n("Saved to: %1").arg( url.fileName() ), IDS_STATUS);
+ m_recentFiles->addURL(url);
+ editor->document()->setModified(false);
+ CurrentFile = url;
+ }
+}
+
+
+
+void MainWindow::slotSaveCanvas()
+{
+ KURL url;
+ while (true)
+ {
+ url = KFileDialog::getSaveURL( QString(":logo_dir"), QString("*.png|") +
+ i18n("Pictures"), this, i18n("Save Canvas as Picture") );
+ if ( url.isEmpty() ) return; // when cancelled the KFiledialog?
+ if ( QFile( url.path() ).exists() )
+ {
+ int result = KMessageBox::warningContinueCancel( this,
+ i18n("A picture named \"%1\" already in this folder. "
+ "Do you want to overwrite it?").arg( url.fileName() ),
+ i18n("Overwrite?"), i18n("&Overwrite") );
+ if (result != KMessageBox::Continue) return;
+ }
+ break;
+ }
+
+ QString type( KImageIO::type( url.path() ) );
+ if ( type.isNull() ) type = "PNG";
+ bool ok = false;
+ QPixmap* pixmap = canvasView->canvas2Pixmap();
+ if ( url.isLocalFile() )
+ {
+ KSaveFile saveFile( url.path() );
+ if ( saveFile.status() == 0 )
+ {
+ if ( pixmap->save( saveFile.file(), type.latin1() ) ) ok = saveFile.close();
+ }
+ }
+ if (!ok)
+ {
+ kdWarning() << "KTurtle was unable to save the canvas drawing" << endl;
+ KMessageBox::error(this,
+ i18n("KTurtle was unable to save the image to: \n%1.").arg( url.prettyURL() ),
+ i18n("Unable to Save Image") );
+ slotStatusBar(i18n("Could not save image."), IDS_STATUS);
+ return;
+ }
+ slotStatusBar(i18n("Saved canvas to: %1").arg( url.fileName() ), IDS_STATUS);
+}
+
+
+
+void MainWindow::slotPrint()
+{
+ int result = KMessageBox::questionYesNoCancel( this,
+ i18n("Do you want to print the Logo code or the canvas?"),
+ i18n("What to Print?"), i18n("Print &Logo Code"), i18n("Print &Canvas") );
+ if (result == KMessageBox::Yes)
+ {
+ dynamic_cast<KTextEditor::PrintInterface*>(doc)->printDialog();
+ return;
+ }
+ if (result == KMessageBox::No)
+ {
+ KPrinter printer;
+ if ( printer.setup(this) )
+ {
+ QPainter painter(&printer);
+ QPixmap *CanvasPic = canvasView->canvas2Pixmap();
+ painter.drawPixmap(0, 0, *CanvasPic);
+ }
+ return;
+ }
+ slotStatusBar(i18n("Printing aborted."), IDS_STATUS);
+}
+
+
+
+bool MainWindow::queryClose()
+{
+ if ( editor->document()->isModified() )
+ {
+ slotStatusBar(i18n("Quitting KTurtle..."), IDS_STATUS);
+ // make sure the dialog looks good with new -- unnamed -- files.
+ int result = KMessageBox::warningYesNoCancel( this,
+ i18n("The program you are currently working on is not saved. "
+ "By quitting KTurtle you may lose the changes you have made."),
+ i18n("Unsaved File"), i18n("&Save"), i18n("Discard Changes && &Quit") );
+ if (result == KMessageBox::Cancel)
+ {
+ slotStatusBar(i18n("Quitting aborted."), IDS_STATUS);
+ return false;
+ }
+ else if (result == KMessageBox::Yes)
+ {
+ slotSaveFile();
+ if ( CurrentFile.isEmpty() )
+ {
+ // when saveAs get cancelled or X-ed it should not quit
+ slotStatusBar(i18n("Quitting aborted."), IDS_STATUS);
+ return false;
+ }
+ }
+ }
+ KConfig *config = kapp->config();
+ config->setGroup("General Options");
+ m_recentFiles->saveEntries(config, "Recent Files");
+ config->sync();
+ return true;
+}
+
+// END
+
+
+
+// BEGIN run related functions
+
+void MainWindow::slotExecute()
+{
+ if (b_fullscreen) // check if execution should be execution in 'fullscreen' mode
+ {
+ editorDock->hide();
+ statusBar()->hide();
+ menuBar()->hide();
+ toolBar()->hide();
+ }
+
+ run->setEnabled(false); // set action indications
+ pause->setEnabled(true);
+ stop->setEnabled(true);
+
+ // start paring
+ slotStatusBar(i18n("Parsing commands..."), IDS_STATUS);
+ kdDebug(0)<<"############## PARSING STARTED ##############"<<endl;
+ kapp->processEvents();
+ errMsg = new ErrorMessage(this); // create an empty errorDialog
+ QString txt = editorInterface->text() + "\x0a\x0a"; // parser expects input to have 2 delimiting newlines
+ QTextIStream in(&txt); // create the stream
+ Parser parser(in); // pass the reference to the stream to the parse object
+ connect(&parser, SIGNAL( ErrorMsg(Token&, const QString&, uint) ),
+ errMsg, SLOT( slotAddError(Token&, const QString&, uint) ) );
+ connect( errMsg, SIGNAL(setSelection(uint, uint, uint, uint) ),
+ this, SLOT(slotSetSelection(uint, uint, uint, uint) ) );
+ parser.parse(); // and GO!
+ TreeNode* root = parser.getTree(); // when finished parsing get the nodeTree
+ kdDebug(0)<<"############## PARSING FINISHED ##############"<<endl;
+
+ kdDebug(0)<<"TreeNode::showTree():"<<endl;
+ root->showTree(root); // show nodeTree, this is a DEBUG OPTION (but nice)
+
+ // start execution
+ slotStatusBar(i18n("Executing commands..."), IDS_STATUS);
+ kdDebug(0)<<"############## EXECUTION STARTED ##############"<<endl;
+ exe = new Executer(root); // make Executer object, 'exe', and pass it the nodeTree
+
+ connect(this, SIGNAL( changeSpeed(int) ), exe, SLOT(slotChangeSpeed(int) ) );
+ connect(this, SIGNAL( unpauseExecution() ), exe, SLOT( slotStopPausing() ) );
+ connect( exe, SIGNAL( setSelection(uint, uint, uint, uint) ),
+ this, SLOT ( slotSetSelection(uint, uint, uint, uint) ) );
+ connect( exe, SIGNAL( ErrorMsg(Token&, const QString&, uint) ),
+ errMsg, SLOT ( slotAddError(Token&, const QString&, uint) ) );
+ connect( exe, SIGNAL( InputDialog(QString&) ), this, SLOT( slotInputDialog(QString&) ) );
+ connect( exe, SIGNAL( MessageDialog(QString) ), this, SLOT( slotMessageDialog(QString) ) );
+
+ // Connect the signals form Executer to the slots from Canvas:
+ connect( exe, SIGNAL( Clear() ), canvasView, SLOT( slotClear() ) );
+ connect( exe, SIGNAL( Go(double, double) ), canvasView, SLOT( slotGo(double, double) ) );
+ connect( exe, SIGNAL( GoX(double) ), canvasView, SLOT( slotGoX(double) ) );
+ connect( exe, SIGNAL( GoY(double) ), canvasView, SLOT( slotGoY(double) ) );
+ connect( exe, SIGNAL( Forward(double) ), canvasView, SLOT( slotForward(double) ) );
+ connect( exe, SIGNAL( Backward(double) ), canvasView, SLOT( slotBackward(double) ) );
+ connect( exe, SIGNAL( Direction(double) ), canvasView, SLOT( slotDirection(double) ) );
+ connect( exe, SIGNAL( TurnLeft(double) ), canvasView, SLOT( slotTurnLeft(double) ) );
+ connect( exe, SIGNAL( TurnRight(double) ), canvasView, SLOT( slotTurnRight(double) ) );
+ connect( exe, SIGNAL( Center() ), canvasView, SLOT( slotCenter() ) );
+ connect( exe, SIGNAL( SetPenWidth(int) ), canvasView, SLOT( slotSetPenWidth(int) ) );
+ connect( exe, SIGNAL( PenUp() ), canvasView, SLOT( slotPenUp() ) );
+ connect( exe, SIGNAL( PenDown() ), canvasView, SLOT( slotPenDown() ) );
+ connect( exe, SIGNAL( SetFgColor(int, int, int) ), canvasView, SLOT( slotSetFgColor(int, int, int) ) );
+ connect( exe, SIGNAL( SetBgColor(int, int, int) ), canvasView, SLOT( slotSetBgColor(int, int, int) ) );
+ connect( exe, SIGNAL( ResizeCanvas(int, int) ), canvasView, SLOT( slotResizeCanvas(int, int) ) );
+ connect( exe, SIGNAL( SpriteShow() ), canvasView, SLOT( slotSpriteShow() ) );
+ connect( exe, SIGNAL( SpriteHide() ), canvasView, SLOT( slotSpriteHide() ) );
+ connect( exe, SIGNAL( SpritePress() ), canvasView, SLOT( slotSpritePress() ) );
+ connect( exe, SIGNAL( SpriteChange(int) ), canvasView, SLOT( slotSpriteChange(int) ) );
+ connect( exe, SIGNAL( Print(QString) ), canvasView, SLOT( slotPrint(QString) ) );
+ connect( exe, SIGNAL( FontType(QString, QString) ), canvasView, SLOT( slotFontType(QString, QString) ) );
+ connect( exe, SIGNAL( FontSize(int) ), canvasView, SLOT( slotFontSize(int) ) );
+ connect( exe, SIGNAL( WrapOn() ), canvasView, SLOT( slotWrapOn() ) );
+ connect( exe, SIGNAL( WrapOff() ), canvasView, SLOT( slotWrapOff() ) );
+ connect( exe, SIGNAL( Reset() ), canvasView, SLOT( slotReset() ) );
+
+ // START EXECUTION on the selected speed, and use the feedbacked boolean value
+ slotChangeSpeed();
+ if ( exe->run() ) slotStatusBar(i18n("Done."), IDS_STATUS);
+ else slotStatusBar(i18n("Execution aborted."), IDS_STATUS);
+ finishExecution();
+
+ delete exe; // clean-up
+
+ if ( errMsg->containsErrors() ) errMsg->display(); // if errors show them
+}
+
+void MainWindow::slotPauseExecution()
+{
+ if ( pause->isChecked() )
+ {
+ exe->pause();
+ slotStatusBar(i18n("Execution paused."), IDS_STATUS);
+ }
+ else
+ {
+ emit unpauseExecution();
+ slotStatusBar(i18n("Executing commands..."), IDS_STATUS);
+ }
+}
+
+void MainWindow::slotAbortExecution()
+{
+ // To abort the executor, this can for instance be handy when the
+ // executer got stuck in a user made endless loops...
+ // to keep the program responding to interrupts like this, all the
+ // loops have possible breaks. This activates them breaks:
+ exe->abort();
+}
+
+void MainWindow::finishExecution()
+{
+ kdDebug(0)<<"############## EXECUTION FINISHED ##############"<<endl;
+ executing = false;
+ pause->setEnabled(false);
+ pause->setChecked(false);
+ run->setEnabled(true);
+ stop->setEnabled(false);
+
+ // if execution finished on FullSpeed the selection does not match the last executed command -> clear-it
+ if (speed->currentItem() == 0) slotClearSelection();
+
+ // if coming from fullscreen-mode show the editor, menu- and statusbar
+ if (b_fullscreen) QTimer::singleShot( 1000, this, SLOT( slotFinishedFullScreenExecution() ) );
+}
+
+void MainWindow::slotChangeSpeed()
+{
+ emit changeSpeed( speed->currentItem() );
+}
+
+
+// slots for logo functions that need to use the MainWindow class:
+
+void MainWindow::slotInputDialog(QString& value)
+{
+ value = KInputDialog::getText(i18n("Input"), value);
+}
+
+void MainWindow::slotMessageDialog(QString text)
+{
+ KMessageBox::information( this, text, i18n("Message") );
+}
+
+// END
+
+
+
+// BEGIN editor connections (undo, redo, cut, copy, paste, cursor, selections, find, replace, linenumbers etc.)
+
+void MainWindow::slotEditor()
+{
+ KAction *a = editor->actionCollection()->action("set_confdlg");
+ a->activate();
+}
+
+void MainWindow::slotSetHighlightstyle(QString langCode)
+{
+ KTextEditor::HighlightingInterface *hli = dynamic_cast<KTextEditor::HighlightingInterface*>(doc);
+ for (uint i = 0; i < hli->hlModeCount(); i++)
+ {
+ if (hli->hlModeName(i) == langCode)
+ {
+ hli->setHlMode(i);
+ return;
+ }
+ }
+ // and the fallback:
+ for (uint i = 0; i < hli->hlModeCount(); i++)
+ {
+ if(hli->hlModeName(i) == "en_US") hli->setHlMode(i);
+ }
+}
+
+
+void MainWindow::slotUndo()
+{
+ dynamic_cast<KTextEditor::UndoInterface*>(doc)->undo();
+}
+
+void MainWindow::slotRedo()
+{
+ dynamic_cast<KTextEditor::UndoInterface*>(doc)->redo();
+}
+
+
+void MainWindow::slotCut()
+{
+ dynamic_cast<KTextEditor::ClipboardInterface*>(editor)->cut();
+}
+
+void MainWindow::slotCopy()
+{
+ dynamic_cast<KTextEditor::ClipboardInterface*>(editor)->copy();
+}
+
+void MainWindow::slotPaste()
+{
+ dynamic_cast<KTextEditor::ClipboardInterface*>(editor)->paste();
+}
+
+
+void MainWindow::slotSelectAll()
+{
+ dynamic_cast<KTextEditor::SelectionInterface*>(doc)->selectAll();
+}
+
+void MainWindow::slotClearSelection()
+{
+ dynamic_cast<KTextEditor::SelectionInterface*>(doc)->clearSelection();
+}
+
+void MainWindow::slotFind()
+{
+ KAction *a = editor->actionCollection()->action("edit_find");
+ a->activate();
+}
+
+void MainWindow::slotFindNext()
+{
+ KAction *a = editor->actionCollection()->action("edit_find_next");
+ a->activate();
+}
+
+void MainWindow::slotFindPrevious()
+{
+ KAction *a = editor->actionCollection()->action("edit_find_prev");
+ a->activate();
+}
+
+void MainWindow::slotReplace()
+{
+ KAction* a = editor->actionCollection()->action("edit_replace");
+ a->activate();
+}
+
+void MainWindow::slotToggleInsert()
+{
+ KToggleAction *a = dynamic_cast<KToggleAction*>(editor->actionCollection()->action("set_insert"));
+ a->activate();
+ if (a) statusBar()->changeItem(a->isChecked() ? i18n(" OVR ") : i18n(" INS "), IDS_INS);
+}
+
+void MainWindow::slotIndent()
+{
+ KAction *a = editor->actionCollection()->action("tools_indent");
+ a->activate();
+}
+
+void MainWindow::slotUnIndent()
+{
+ KAction *a = editor->actionCollection()->action("tools_unindent");
+ a->activate();
+}
+
+void MainWindow::slotCleanIndent()
+{
+ KAction *a = editor->actionCollection()->action("tools_cleanIndent");
+ a->activate();
+}
+
+void MainWindow::slotComment()
+{
+ KAction *a = editor->actionCollection()->action("tools_comment");
+ a->activate();
+}
+
+void MainWindow::slotUnComment()
+{
+ KAction *a = editor->actionCollection()->action("tools_uncomment");
+ a->activate();
+}
+
+void MainWindow::slotToggleLineNumbers()
+{
+ KToggleAction *a = dynamic_cast<KToggleAction*>( editor->actionCollection()->action("view_line_numbers") );
+ a->activate();
+}
+
+void MainWindow::slotInsertText(QString str)
+{
+ uint StartLine, StartCol, EndLine, EndCol;
+ dynamic_cast<KTextEditor::ViewCursorInterface*>(editor)->cursorPositionReal(&StartLine, &StartCol);
+ dynamic_cast<KTextEditor::EditInterface*>(doc)->insertText(StartLine, StartCol, str);
+ dynamic_cast<KTextEditor::ViewCursorInterface*>(editor)->cursorPositionReal(&EndLine, &EndCol);
+ dynamic_cast<KTextEditor::SelectionInterface*>(doc)->setSelection(StartLine, StartCol, EndLine, EndCol);
+}
+
+void MainWindow::slotSetCursorPos(uint row, uint col)
+{
+ dynamic_cast<KTextEditor::ViewCursorInterface*>(editor)->setCursorPositionReal(row - 1, col);
+ // kdDebug(0)<<"Cursor set to: ("<<row-1<<", "<<col<<")"<<endl;
+}
+
+void MainWindow::slotSetSelection(uint StartLine, uint StartCol, uint EndLine, uint EndCol)
+{
+ dynamic_cast<KTextEditor::SelectionInterface*>(doc)->setSelection(StartLine - 1, StartCol - 1, EndLine - 1, EndCol - 1);
+ // kdDebug(0)<<"Selection set to: ("<<StartLine<<", "<<StartCol<<", "<<EndLine<<", "<<EndCol<<")"<<endl;
+}
+// END
+
+
+
+// BEGIN fullscreen functions
+
+void MainWindow::slotToggleFullscreen()
+{
+ if (!b_fullscreen) showFullScreen(); // both calls will generate event triggering updateFullScreen()
+ else if ( isFullScreen() ) showNormal();
+}
+
+bool MainWindow::event(QEvent* e)
+{
+ // executes updateFullScreen() after a ShowFullScreen or ShowNormal event got triggered
+ if (e->type() == QEvent::ShowFullScreen || e->type() == QEvent::ShowNormal) updateFullScreen();
+ return KMainWindow::event(e);
+}
+
+void MainWindow::updateFullScreen()
+{
+ if (isFullScreen() == b_fullscreen) return;
+ b_fullscreen = isFullScreen();
+ if (m_fullscreen) m_fullscreen->setChecked(b_fullscreen);
+}
+
+void MainWindow::slotFinishedFullScreenExecution()
+{
+ restartOrBackDialog = new RestartOrBack(this); // we have to make some to delete some
+ if ( errMsg->containsErrors() ) slotBackToFullScreen(); // straight back to edit if there where errors
+ else
+ {
+ connect( restartOrBackDialog, SIGNAL( user1Clicked() ), this, SLOT( slotRestartFullScreen() ) );
+ connect( restartOrBackDialog, SIGNAL( user2Clicked() ), this, SLOT( slotBackToFullScreen() ) );
+ connect( restartOrBackDialog, SIGNAL( finished() ), this, SLOT( slotBackToFullScreen() ) );
+ restartOrBackDialog->show();
+ restartOrBackDialog->move(50, 50);
+ }
+}
+
+void MainWindow::slotBackToFullScreen()
+{
+ delete restartOrBackDialog;
+ editorDock->show();
+ statusBar()->show();
+ menuBar()->show();
+ toolBar()->show();
+}
+
+void MainWindow::slotRestartFullScreen()
+{
+ delete restartOrBackDialog;
+ slotExecute();
+}
+
+// END
+
+
+
+// BEGIN configuration related functions
+
+void MainWindow::slotSettings()
+{
+ // Check if there is already a dialog, if so bring it to the foreground.
+ if ( KConfigDialog::showDialog("settings") ) return;
+
+ // Create a new dialog with the same name as the above checking code.
+ KConfigDialog *dialog = new KConfigDialog(this, "settings", Settings::self() );
+ // connect the help
+ connect( dialog, SIGNAL( helpClicked() ), this, SLOT( slotSettingsHelp() ) );
+
+ // making the filling for the 'General' settings dept.
+ general = new QWidget();
+ QGridLayout *generalLayout = new QGridLayout( general, 1, 1, 11, 6, "generalLayout");
+ WidthHeightBox = new QGroupBox( i18n("Initial Canvas Size"), general );
+ WidthHeightBox->setColumnLayout(0, Qt::Vertical );
+ WidthHeightBox->layout()->setSpacing( 6 );
+ WidthHeightBox->layout()->setMargin( 11 );
+ QVBoxLayout *WidthHeightBoxLayout = new QVBoxLayout( WidthHeightBox->layout() );
+ WidthHeightBoxLayout->setAlignment( Qt::AlignTop );
+ QHBoxLayout *layout3 = new QHBoxLayout( 0, 0, 6, "layout3");
+ QVBoxLayout *layout2 = new QVBoxLayout( 0, 0, 6, "layout2");
+
+ QVBoxLayout *layout1 = new QVBoxLayout( 0, 0, 6, "layout1");
+
+ kcfg_CanvasWidth = new KIntNumInput( WidthHeightBox, "kcfg_CanvasWidth" );
+ kcfg_CanvasWidth->setValue( 400 );
+ kcfg_CanvasWidth->setMinValue( 1 );
+ kcfg_CanvasWidth->setReferencePoint( 1 );
+ layout1->addWidget( kcfg_CanvasWidth );
+
+ kcfg_CanvasHeight = new KIntNumInput( WidthHeightBox, "kcfg_CanvasHeight" );
+ kcfg_CanvasHeight->setValue( 300 );
+ kcfg_CanvasHeight->setMinValue( 1 );
+ kcfg_CanvasHeight->setReferencePoint( 1 );
+ layout1->addWidget( kcfg_CanvasHeight );
+
+ WidthLabel = new QLabel( kcfg_CanvasWidth, i18n("Canvas &width:"), WidthHeightBox );
+ layout2->addWidget( WidthLabel );
+ HeightLabel = new QLabel( kcfg_CanvasHeight, i18n("Ca&nvas height:"), WidthHeightBox );
+ layout2->addWidget( HeightLabel );
+ layout3->addLayout( layout2 );
+
+ layout3->addLayout( layout1 );
+ WidthHeightBoxLayout->addLayout( layout3 );
+ QLabel* WidthHeightLabel = new QLabel(i18n("You need to restart before these settings have effect"), WidthHeightBox);
+ WidthHeightBoxLayout->addWidget( WidthHeightLabel );
+ generalLayout->addWidget( WidthHeightBox, 0, 0 );
+ general->resize( QSize(234, 109).expandedTo(minimumSizeHint()) );
+
+ dialog->addPage( general, i18n("General"), "package_settings", i18n("General Settings") );
+
+ // making the filling for the 'Language' settings dept.
+ QWidget *language = new QWidget();
+ QGridLayout *languageLayout = new QGridLayout( language, 1, 1, 11, 6, "Form1Layout");
+ QGroupBox *groupBox1 = new QGroupBox( language, "groupBox1" );
+ groupBox1->setColumnLayout(0, Qt::Vertical );
+ groupBox1->layout()->setSpacing( 6 );
+ groupBox1->layout()->setMargin( 11 );
+ QGridLayout *groupBox1Layout = new QGridLayout( groupBox1->layout() );
+ groupBox1Layout->setAlignment( Qt::AlignTop );
+
+ QVBoxLayout *layout4 = new QVBoxLayout( 0, 0, 6, "layout4");
+
+ kcfg_LanguageComboBox = new KComboBox(groupBox1, "kcfg_LanguageComboBox");
+ kcfg_LanguageComboBox->setEditable(false);
+ QStringList LogoLanguageList = Settings::logoLanguageList();
+ // Add the full language names to the items
+ for ( QStringList::Iterator it = LogoLanguageList.begin(); it != LogoLanguageList.end(); ++it ) {
+ *it = KGlobal::locale()->twoAlphaToLanguageName( (*it).left(2) ) + " (" + *it + ")";
+ }
+ kcfg_LanguageComboBox->insertStringList(LogoLanguageList);
+
+ LanguageLabel = new QLabel(kcfg_LanguageComboBox, i18n("&Select the language for the Logo commands:"), groupBox1);
+ layout4->addWidget( LanguageLabel );
+ layout4->addWidget( kcfg_LanguageComboBox );
+ LanguageLabel->setBuddy( kcfg_LanguageComboBox );
+
+ groupBox1Layout->addLayout( layout4, 0, 0 );
+ languageLayout->addWidget( groupBox1, 0, 0 );
+ language->resize( QSize(373, 80).expandedTo(minimumSizeHint()) );
+
+ dialog->addPage( language, i18n("Language"), "locale", i18n("Language Settings") );
+
+ // When the user clicks OK or Apply we want to update our settings.
+ connect( dialog, SIGNAL( settingsChanged() ), this, SLOT( slotUpdateSettings() ) );
+
+ // Display the dialog is there where errors.
+ dialog->setInitialSize( QSize(550, 300) );
+ dialog->show();
+}
+
+void MainWindow::slotUpdateSettings()
+{
+ // get the selected language as a language code
+ QString selectedLogoLanguage = kcfg_LanguageComboBox->currentText().section( "(", -1, -1 ).remove(")");
+ // update the settings
+ Settings::setLogoLanguage( selectedLogoLanguage );
+ Settings::setLanguageComboBox( kcfg_LanguageComboBox->currentItem() );
+ Settings::writeConfig();
+ // set the HLstyle
+ slotSetHighlightstyle( selectedLogoLanguage );
+ // set the statusbar to display the language as just updated
+ // TODO maybe this language name can be more pretty by not using ".left(2)", ie "American English" would than be possible... [if this is possible this should be fixed at more places.]
+ KConfig entry(locate("locale", "all_languages"));
+ entry.setGroup(Settings::logoLanguage().left(2));
+ slotStatusBar(i18n("Command language: %1").arg( entry.readEntry("Name") ), IDS_LANG);
+
+ delete translate; // to update the currently used language
+ translate = new Translate();
+}
+
+void MainWindow::readConfig(KConfig *config)
+{
+ config->setGroup("General Options");
+ m_recentFiles->loadEntries(config, "Recent Files");
+ KConfig entry(locate("locale", "all_languages"));
+ entry.setGroup(Settings::logoLanguage().left(2));
+ slotStatusBar(i18n("Command language: %1").arg( entry.readEntry("Name") ), IDS_LANG);
+}
+
+void MainWindow::slotSettingsHelp()
+{
+ kapp->invokeHelp("settings-configure", "", "");
+}
+
+// END
+
+
+
+// BEGIN help related functions
+
+void MainWindow::slotContextHelp()
+{
+// somehow the 'anchor' parameter of invokeHelp is not working correcctly (yet)
+
+// this is/was appearently a bug in KHTML that Waldo Bastian kindly and quikly fixed.
+
+// Ooh... and we also want a DCOPmethod to close the sidebar since it over-informs...
+// Ooh3... we want fancy help (using KHTML) @ errormessage dialog
+// Ooh4... And we might also have to keep track of the KHelpCenter instance we open so
+// we will not end up with loads of them
+//
+
+// IDEA!!: put all the keyword in a i18n("...") this will make translating them a lot easier!!!
+// MAYBE THIS IS ALSO POSSIBLE FOR THE INTERPRETER!!!!
+// this should be discussed with translators (and please think of the highlight-themes too (since
+// right now thay can probably be translated with a simple perl script
+
+ kdDebug(0)<<"help requested on this text: "<<helpKeyword<<endl;
+
+ QString helpWord;
+ if ( helpKeyword == i18n("<no keyword>") )
+ {
+ KMessageBox::information( this, i18n("There is currently no text under the cursor to get help on."), i18n("Nothing Under Cursor") );
+ return;
+ }
+ else if ( helpKeyword == i18n("<number>") ) helpWord = "number";
+ else if ( helpKeyword == i18n("<string>") ) helpWord = "string";
+ else if ( helpKeyword == i18n("<assignment>") ) helpWord = "assignment";
+ else if ( helpKeyword == i18n("<question>") ) helpWord = "questions";
+ else if ( helpKeyword == i18n("<name>") ) helpWord = "name";
+ else if ( helpKeyword == i18n("<comment>") ) helpWord = "comment";
+ else
+ {
+ // make lowercase
+ helpWord = helpKeyword.lower();
+ // if the key is an alias translate that alias to a key
+ if ( !translate->alias2key(helpKeyword).isEmpty() ) helpWord = translate->alias2key(helpKeyword);
+ else if ( !translate->name2key (helpKeyword).isEmpty() ) helpWord = translate->name2key (helpKeyword);
+
+ // at this point helpKeyword should contain a valid
+ // section/anchor-id that can be used found in the doc
+ // if not... who cares :)... well let's put an debugMsg for that occasion:
+ else kdDebug(0)<<"Error in MainWindow::slotContextHelp: could not translate \""<<helpKeyword<<"\""<<endl;
+ }
+
+ kdDebug(0)<<"trying to open a help page using this keyword: "<<helpWord<<endl;
+
+ kapp->invokeHelp(helpWord, "", "");
+
+ QString help2statusBar;
+ if ( helpKeyword.startsWith("<") ) help2statusBar = helpKeyword;
+ else help2statusBar = i18n("\"%1\"").arg(helpKeyword);
+ slotStatusBar(i18n("Displaying help on %1").arg(help2statusBar), IDS_STATUS);
+}
+
+void MainWindow::slotContextHelpUpdate()
+{
+ uint row, col;
+ dynamic_cast<KTextEditor::ViewCursorInterface*>(editor)->cursorPositionReal(&row, &col);
+ QString line = dynamic_cast<KTextEditor::EditInterface*>(doc)->textLine(row);
+
+ // two shortcuts so we dont do all the CPU intensive regexp stuff when it not needed
+ if ( line.stripWhiteSpace().startsWith("#") )
+ {
+ helpKeyword = i18n("<comment>");
+ ContextHelp->setText( i18n("Help on: %1").arg(helpKeyword) );
+ return;
+ }
+ if ( line.stripWhiteSpace().isEmpty() || line.mid(col-1,2).stripWhiteSpace().isEmpty() )
+ {
+ helpKeyword = i18n("<no keyword>");
+ ContextHelp->setText( i18n("Help on: %1").arg(helpKeyword) );
+ return;
+ }
+
+ int start, length, pos;
+
+ pos = 0;
+ if ( line.contains('"') )
+ {
+ QRegExp delimitedStrings("(\"[^\"\\\\\\r\\n]*(\\\\.[^\"\\\\\\r\\n]*)*\")");
+ while ( delimitedStrings.search(line, pos) != -1 )
+ {
+ // kdDebug(0)<<"stringsearch: >>"<<pos<<"<<"<<endl;
+ start = delimitedStrings.search(line, pos);
+ length = delimitedStrings.matchedLength(); // the length of the last matched string, or -1 if there was no match
+ if ( col >= (uint)start && col < (uint)(start+length) )
+ {
+ helpKeyword = i18n("<string>");
+ ContextHelp->setText( i18n("Help on: %1").arg(helpKeyword) );
+ return;
+ }
+ pos += (length <= 0 ? 1 : length);
+ }
+ }
+
+
+ // except for "strings" this regexp effectively separates logo code in 'words' (in a very broad meaning)
+ QRegExp splitter("(([^ ,+\\-*/()=<>[!]|(?!==|<=|>=|!=))*)|(([ ,+\\-*/()=<>[!]|==|<=|>=|!=))");
+
+ pos = 0;
+ while (splitter.search(line, pos) != -1)
+ {
+ start = splitter.search(line, pos);
+ length = splitter.matchedLength();
+ if ( col < (uint)start ) break;
+ if ( col >= (uint)start && col < (uint)(start+length) )
+ {
+ QString cursorWord = line.mid( (uint)start, (uint)length );
+ kdDebug(0)<<"cursorWord: '"<<cursorWord<<"'"<<endl;
+
+ kdDebug(0)<<"(translate->name2key( cursorWord.lower() )): '"<<translate->name2key( cursorWord.lower() )<<"'"<<endl;
+ kdDebug(0)<<"(translate->alias2key( cursorWord.lower() )): '"<<translate->alias2key( cursorWord.lower() )<<"'"<<endl;
+
+ if ( cursorWord.stripWhiteSpace().isEmpty() ) helpKeyword = i18n("<no keyword>");
+
+ else if ( !translate->name2key( cursorWord.lower() ).isEmpty() ) helpKeyword = cursorWord;
+ else if ( !translate->alias2key( cursorWord.lower() ).isEmpty() ) helpKeyword = cursorWord;
+
+ else if ( cursorWord.find( QRegExp("[\\d.]+") ) == 0 ) helpKeyword = i18n("<number>");
+
+ else if ( cursorWord.find( QRegExp("[+\\-*/\\(\\)]") ) == 0 ) helpKeyword = i18n("<math>");
+
+ else if ( cursorWord == QString("=") ) helpKeyword = i18n("<assignment>");
+
+ else if ( cursorWord.find( QRegExp("==|<|>|<=|>=|!=") ) == 0 ) helpKeyword = i18n("<question>");
+
+ // if we come here we either have an ID of some sort or an error
+ // all we can do is try to catch some errors (TODO) and then...
+
+ else helpKeyword = i18n("<name>");
+
+ ContextHelp->setText( i18n("Help on: %1").arg(helpKeyword) );
+ return;
+ }
+ pos += (length <= 0 ? 1 : length); // the pos had to be increased with at least one
+ }
+
+ // we allready cached some in the beginning of this method; yet its still needed as fall-through
+ helpKeyword = i18n("<no keyword>");
+ ContextHelp->setText( i18n("Help on: %1").arg(helpKeyword) );
+}
+
+// END
+
+
+
+// BEGIN misc. functions
+
+void MainWindow::slotColorPicker()
+{
+ // in the constructor picker is initialised as 0
+ // if picker is 0 when this funktion is called a colorpickerdialog is created and connected
+ if (picker == 0)
+ {
+ picker = new ColorPicker(this);
+ if(picker == 0) return; // safety
+ connect( picker, SIGNAL( visible(bool) ), colorpicker, SLOT( setChecked(bool) ) );
+ connect( picker, SIGNAL( ColorCode(QString) ), this, SLOT( slotInsertText(QString) ) );
+ }
+ // if picker is not 0, there is a colorpickerdialog which only needs to be shown OR hidden
+ if ( picker->isHidden() )
+ {
+ picker->show();
+ colorpicker->setChecked(true);
+ }
+ else
+ {
+ picker->hide();
+ colorpicker->setChecked(false);
+ }
+}
+
+void MainWindow::slotUpdateCanvas()
+{
+ // fixes a non updateing bug
+ // I tried doing this by connecting Canvas's resized to baseWidget's update...
+ // but i had no luck :( ... this worked though :)
+ canvasView->hide();
+ canvasView->show();
+}
+
+// END
+
+
+#include "kturtle.moc"
diff --git a/kturtle/src/kturtle.desktop b/kturtle/src/kturtle.desktop
new file mode 100644
index 00000000..0b541e05
--- /dev/null
+++ b/kturtle/src/kturtle.desktop
@@ -0,0 +1,124 @@
+[Desktop Entry]
+DocPath=kturtle/index.html
+Name=KTurtle
+Name[af]=KSkilpad
+Name[bn]=কে-টার্টল
+Name[fi]=Konna
+Name[hi]=के-टर्टल
+Name[hr]=KKornjača
+Name[is]=KSkjaldbaka
+Name[ne]=केडीई टर्टल
+Name[sv]=Kturtle
+Name[tg]=KСангпушт
+GenericName=Logo Programming Environment
+GenericName[af]=Logo Programmeeromgewing
+GenericName[be]=Асяроддзе праграмавання на мове Logo
+GenericName[bg]=Програмиране на Лого
+GenericName[bn]=লোগো প্রোগ্রামিং
+GenericName[bs]=Logo programsko okruženje
+GenericName[ca]=Entorn de programació de Logo
+GenericName[cs]=Logo programovací prostředí
+GenericName[csb]=Òkrãżi do programòwania w Logo
+GenericName[cy]=Amgylchedd Rhaglennu Logo
+GenericName[da]=Logo programmeringsmiljø
+GenericName[de]=Logo-Programmierumgebung
+GenericName[el]=Περιβάλλον προγραμματισμού σε Logo
+GenericName[es]=Entorno de programación de Logo
+GenericName[et]=Logo programmeerimise keskkond
+GenericName[eu]=Logo programazio ingurunea
+GenericName[fa]=محیط برنامه‌سازی لوگو
+GenericName[fi]=Logo-ohjelmointiympäristö
+GenericName[fr]=Environnement de programmation en Logo
+GenericName[ga]=Timpeallacht Ríomhchláraithe Logo
+GenericName[gl]=Ambiente de Programación en Logo
+GenericName[he]=סביבת תכנות לשפת לוגו
+GenericName[hi]=लोगो डेवलपमेंट माहौल.
+GenericName[hr]=Okruženje za programiranje logotipa
+GenericName[hu]=Logo-programozás
+GenericName[is]=Logo forritunarumhverfi
+GenericName[it]=Ambiente di programmazione Logo
+GenericName[ja]=ロゴプログラミング環境
+GenericName[ka]=პროგრამირება "ლოგოზე"
+GenericName[km]=បរិស្ថាន​កម្មវិធី​រូប​សញ្ញា
+GenericName[lt]=Logo programavimo aplinka
+GenericName[nb]=Programmeringsmiljø for Logo
+GenericName[nds]="Logo"-Programmsmeed
+GenericName[ne]=लोगो प्रोग्रामिङ परिवेश
+GenericName[nl]=Logo programmeeromgeving
+GenericName[nn]=Programmeringsmiljø for Logo
+GenericName[pl]=Środowisko do programowania w Logo
+GenericName[pt]=Ambiente de Programação em Logo
+GenericName[pt_BR]=Ambiente de programação Logo
+GenericName[ru]=Обучение программированию на языке Лого
+GenericName[sk]=Programovacie prostredie pre Logo
+GenericName[sl]=Programsko okolje za Logo
+GenericName[sr]=Програмерско окружење за Logo
+GenericName[sr@Latn]=Programersko okruženje za Logo
+GenericName[sv]=Logo-programmeringsmiljö
+GenericName[ta]=சிண்ண நிரல் உருவாக சூழல்
+GenericName[tg]=Муҳити барноманависии Logo
+GenericName[tr]=Logo Programlama Ortamı
+GenericName[uk]=Середовище програмування на мові Logo
+GenericName[vi]=Môi trường Lập trình Logo
+GenericName[zh_CN]=Logo 编程环境
+GenericName[zh_TW]=Logo 程式環境
+Exec=kturtle -caption "%c" %i %m
+Icon=kturtle
+Type=Application
+Comment=A KDE Logo programming environment
+Comment[af]='n KDE Logo programmeeromgewing
+Comment[be]=Асяроддзе KDE для праграмавання на мове Logo
+Comment[bg]=Среда за програмиране на Лого
+Comment[bn]=কেডিই'র লোগো প্রোগ্রামিং
+Comment[bs]=KDE programsko okruženje za Logo
+Comment[ca]=Un entorn de programació de Logo per a KDE
+Comment[cs]=KDE Logo programovací prostředí
+Comment[csb]=Òkrãżi do programòwania w Logo dla KDE
+Comment[cy]=Amgylchedd Rhaglennu Logo KDE
+Comment[da]=Et KDE Logo programmeringsmiljø
+Comment[de]=Eine KDE-Programmierumgebung für Logo
+Comment[el]=Ένα περιβάλλον προγραμματισμού σε Logo για το KDE
+Comment[eo]=KDE Logo-lingva programa ĉirkaŭaĵo
+Comment[es]=Un entorno de programación de Logo para KDE
+Comment[et]=KDE Logo programmeerimise keskkond
+Comment[eu]=KDE-ren Logo programazio ingurune bat
+Comment[fa]=محیط برنامه‌سازی لوگوKDE
+Comment[fi]=KDE Logo-ohjelmointiympäristö
+Comment[fr]=Un environnement de programmation en Logo pour KDE
+Comment[ga]=Timpeallacht ríomhchláraithe Logo le haghaidh KDE
+Comment[gl]=Ambiente de programación en Logo para KDE
+Comment[he]=סביבצ עבודה של KDE לשפת לוגו
+Comment[hi]=केडीई हेतु लोगो प्रोग्रामिंग माहौल
+Comment[hr]=KDE okruženje za programiranje logotipa
+Comment[hu]=KDE-alapú Logo-programozási környezet
+Comment[is]=KDE Logo forritunarumhverfi
+Comment[it]=Ambiente di programmazione Logo per KDE
+Comment[ja]=KDE ロゴプログラミング環境
+Comment[ka]=KDE "ლოგოზე" პროგრამირების გარემო
+Comment[km]=បរិស្ថាន​កម្មវិធី​រូប​សញ្ញា​របស់ KDE
+Comment[lt]=KDE Logo programavimo aplinka
+Comment[nb]=Et KDE-miljø for Logo-programmering
+Comment[nds]=En KDE-Programmsmeed för "Logo"
+Comment[ne]= KDE लोगो प्रोग्रामिङ परिवेश
+Comment[nl]=Logo-programmeeromgeving voor KDE
+Comment[nn]=Eit KDE-miljø for Logo-programmering
+Comment[pl]=Środowisko do programowania w Logo dla KDE
+Comment[pt]=Ambiente de programação em Logo para o KDE
+Comment[pt_BR]=Um ambiente KDE de programação Logo
+Comment[ru]=Обучение программированию на языке Лого
+Comment[sk]=KDE programovacie prostredie pre Logo
+Comment[sl]=Okolje za programiranje v jeziku Logo za KDE
+Comment[sr]=KDE програмерско окружење за Logo
+Comment[sr@Latn]=KDE programersko okruženje za Logo
+Comment[sv]=Logo-programmeringsmiljö för KDE
+Comment[ta]=ஒரு KDE சின்னத்தின் நிரலாக்க சூழல்
+Comment[tg]=Муҳити барноманависии KDE Logo
+Comment[tr]=Bir KDE Logo programlama ortamı
+Comment[uk]=KDE середовище програмування на мові Logo
+Comment[vi]=Một môi trường lập trình Logo cho KDE
+Comment[zh_CN]=KDE Logo 编程环境
+Comment[zh_TW]=KDE 的 Logo 程式設計環境
+Path=
+Terminal=false
+X-KDE-StartupNotify=true
+Categories=Qt;KDE;Education;
diff --git a/kturtle/src/kturtle.h b/kturtle/src/kturtle.h
new file mode 100644
index 00000000..8ffd55df
--- /dev/null
+++ b/kturtle/src/kturtle.h
@@ -0,0 +1,182 @@
+/*
+ Copyright (C) 2003-04 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _KTURTLE_H_
+#define _KTURTLE_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <qgroupbox.h>
+
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <knuminput.h>
+
+#include <kparts/mainwindow.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/view.h>
+
+#include "canvas.h"
+#include "dialogs.h"
+#include "executer.h"
+#include "parser.h"
+
+
+class KRecentFilesAction;
+
+
+class MainWindow : public KParts::MainWindow
+{
+ Q_OBJECT
+
+ public:
+ MainWindow(KTextEditor::Document* = 0L);
+ virtual ~MainWindow();
+
+
+ signals:
+ void changeSpeed(int speed);
+ void unpauseExecution();
+
+
+ protected slots:
+ void slotNewFile();
+ void slotOpenFile(const KURL& url = NULL);
+ void slotOpenExample();
+ void slotSaveFile();
+ void slotSaveAs();
+ void slotSaveCanvas();
+ void slotPrint();
+
+ void slotExecute();
+ void slotPauseExecution();
+ void slotAbortExecution();
+ void slotChangeSpeed();
+ void slotInputDialog(QString& value);
+ void slotMessageDialog(QString text);
+
+ void slotEditor();
+ void slotSetHighlightstyle(QString langCode);
+ void slotUndo();
+ void slotRedo();
+ void slotCut();
+ void slotCopy();
+ void slotPaste();
+ void slotSelectAll();
+ void slotClearSelection();
+ void slotFind();
+ void slotFindNext();
+ void slotFindPrevious();
+ void slotReplace();
+ void slotToggleInsert();
+ void slotInsertText(QString);
+ void slotToggleLineNumbers();
+ void slotIndent();
+ void slotUnIndent();
+ void slotCleanIndent();
+ void slotComment();
+ void slotUnComment();
+ void slotSetCursorPos(uint row, uint column);
+ void slotSetSelection(uint StartLine, uint StartCol, uint EndLine, uint EndCol);
+
+ void slotSettings();
+ void slotUpdateSettings();
+ void slotSettingsHelp();
+
+ void slotContextHelp();
+ void slotContextHelpUpdate();
+
+ void slotStatusBar(QString text, int place);
+ void slotCursorStatusBar();
+
+ void slotToggleFullscreen();
+ void slotFinishedFullScreenExecution();
+ void slotRestartFullScreen();
+ void slotBackToFullScreen();
+
+ void slotColorPicker();
+ void slotUpdateCanvas();
+
+
+ protected:
+ void setupActions();
+ void setupEditor();
+ void setupCanvas();
+ void setupStatusBar();
+
+ void loadFile(const KURL& url);
+ void writeFile(const KURL& url);
+ bool queryClose();
+
+ void finishExecution();
+ void readConfig(KConfig *config);
+
+ void updateFullScreen();
+ virtual bool event(QEvent* e);
+
+ Canvas *canvasView;
+ QWidget *baseWidget;
+ QGridLayout *baseLayout;
+ QDockWindow *editorDock;
+ Executer *exe;
+ ErrorMessage *errMsg;
+ ColorPicker *picker;
+ RestartOrBack *restartOrBackDialog;
+
+ KAction *run;
+ KAction *stop;
+ KAction *openExAction;
+ KAction *openFileAction;
+ KAction *newAction;
+ KAction *ContextHelp;
+ KToggleAction *pause;
+ KToggleAction *m_fullscreen;
+ KToggleAction *colorpicker;
+ KSelectAction *speed;
+ KRecentFilesAction *m_recentFiles;
+
+ KTextEditor::View *view() const { return editor; }
+ KTextEditor::EditInterface *editorInterface;
+ KTextEditor::Document *doc;
+ KTextEditor::View *editor;
+
+ bool executing;
+ bool b_fullscreen;
+ bool b_editorShown;
+
+ QString helpKeyword;
+ Translate *translate;
+ KURL CurrentFile;
+
+ // configuration related
+ QWidget *general;
+ QWidget *language;
+ QGroupBox *WidthHeightBox;
+ QLabel *WidthLabel;
+ QLabel *HeightLabel;
+ KIntNumInput *kcfg_CanvasWidth;
+ KIntNumInput *kcfg_CanvasHeight;
+ KComboBox *kcfg_LanguageComboBox;
+ QLabel *LanguageLabel;
+};
+
+
+#endif // _KTURTLE_H_
diff --git a/kturtle/src/kturtle.kcfg b/kturtle/src/kturtle.kcfg
new file mode 100644
index 00000000..1dba5092
--- /dev/null
+++ b/kturtle/src/kturtle.kcfg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+<kcfgfile name="kturtlerc"/>
+
+ <group name="general">
+ <entry name="CanvasWidth" type="Int">
+ <label>The width of the canvas in pixels</label>
+ <default>300</default>
+ </entry>
+ <entry name="CanvasHeight" type="Int">
+ <label>The height of the canvas in pixels</label>
+ <default>250</default>
+ </entry>
+ </group>
+
+
+ <group name="language">
+ <entry name="LogoLanguageList" type="StringList">
+ <label>The list of the available languages for the Logo commands</label>
+ <code>
+
+ // This StringList (LogoLanguageList) is a list of all possible language codes all possible [en_US, fr, nl, etc.]. It is used to (1) find the LogoLanguage variable (that is defined later on), and (2) in the Settings dialog to fill the language ComboBox. Better not to dupe this code. The LogoLanguageList is made pretty in the slotSettings class of kturtle.cpp.
+
+ // We assume keyword and highlight files come in pairs (if not there will be no highlight style)
+
+ QStringList xmlFiles = KGlobal::dirs()->findAllResources("data", "kturtle/data/*.xml");
+ QStringList LogoLanguageList;
+ QString xmlTranslationFiles; // for debug purposes
+ for ( QStringList::Iterator it = xmlFiles.begin(); it != xmlFiles.end(); ++it ) {
+ QString xmlFile(*it);
+ xmlTranslationFiles += xmlFile.section('.', -2, -2).append(", "); // for debug purposes
+ // build list of language codes (en_US, nl, etc.)
+ LogoLanguageList += xmlFile.section('.', -2, -2);
+ }
+ kdDebug(0) &lt;&lt; "Available translations of Logo: "&lt;&lt; xmlTranslationFiles &lt;&lt;endl;
+ LogoLanguageList.sort();
+
+ </code>
+ <default code="true">LogoLanguageList</default>
+ </entry>
+
+
+ <entry name="LogoLanguage" type="String">
+ <label>The language of the Logo commands</label>
+ <code>
+
+ // This is the String (LogoLanguage) that actually gets picked up by the app to know what XML files (for HLstyle and Logo language) to use. It is not directly changeable by the ComboBox but is translated from the Ints that ComboBox LogoLanguageList emits. It is better to have the logic that changes the Ints to Strings at the settings dept.
+
+ // The KconfigXT framework makes shure the value that is saved in the kturtlerc file will be used in stead of the defaultLanguage that we find here.
+
+ // Get the desktops language
+ KConfigBase *globalConf = KGlobal::config();
+ globalConf->setGroup("Locale");
+ QString desktopLanguage = globalConf->readEntry("Language");
+ kdDebug(0) &lt;&lt; "desktopLanguage: "&lt;&lt; desktopLanguage &lt;&lt;endl;
+
+ QString defaultLanguage = "en_US"; // init to the fall back value
+ int itemCount = 0; // for the LanguageComboBox
+ for (QStringList::Iterator it = LogoLanguageList.begin(); it != LogoLanguageList.end(); ++it ) {
+ QString testLanguage(*it);
+ if (testLanguage == desktopLanguage) { // exact match
+ defaultLanguage = testLanguage;
+ break;
+ } else if ( testLanguage.left(2) == desktopLanguage.left(2) ) { // close match (different dialect)
+ // The default language must still be one of the kturtle languages.
+ // defaultLanguage = testLanguage.left(2);
+ defaultLanguage = testLanguage;
+ break;
+ }
+ itemCount++;
+ }
+ kdDebug(0) &lt;&lt; "Logo command language: "&lt;&lt; defaultLanguage &lt;&lt;endl;
+
+ </code>
+ <default code="true">defaultLanguage</default>
+ </entry>
+
+
+ <entry name="LanguageComboBox" type="Int">
+ <label>The value of the ComboBox</label>
+ <code>
+
+ // This is the parameter that actually gets changed (and emits the signal to the dialog to enable the Apply and Defaults buttons). This value is saved in the kturtlerc file but is never used.
+
+ </code>
+ <default code="true">itemCount</default>
+ </entry>
+
+ </group>
+</kcfg>
diff --git a/kturtle/src/kturtleui.rc b/kturtle/src/kturtleui.rc
new file mode 100644
index 00000000..d5180799
--- /dev/null
+++ b/kturtle/src/kturtleui.rc
@@ -0,0 +1,97 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kturtle" version="2" >
+<MenuBar>
+ <Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_new" />
+ <Action name="file_open" />
+ <Action name="file_open_recent" />
+ <Action name="open_examples" />
+ <Separator />
+ <Action name="file_save" />
+ <Action name="file_save_as" />
+ <Action name="save_canvas" />
+ <Separator />
+ <Action name="speed" />
+ <Action name="run" />
+ <Action name="pause" />
+ <Action name="stop" />
+ <Separator />
+ <Action name="file_print" />
+ <Separator />
+ <Action name="file_quit" />
+ </Menu>
+
+ <Menu name="edit" noMerge="1"><text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ <Separator />
+ <Action name="edit_cut" />
+ <Action name="edit_copy" />
+ <Action name="edit_paste" />
+ <Separator />
+ <Action name="edit_find" />
+ <Action name="edit_find_next" />
+ <Action name="edit_replace" />
+ </Menu>
+
+ <Menu name="view" noMerge="1"><text>&amp;View</text>
+ <Action name="full_screen" />
+ <Separator />
+ <Action name="line_numbers" />
+ </Menu>
+
+ <Menu name="tools" noMerge="1"><text>&amp;Tools</text>
+ <Action name="color_picker" />
+ <Separator />
+ <Action name="edit_indent" />
+ <Action name="edit_unindent" />
+ <Action name="edit_cleanIndent" />
+ <Separator />
+ <Action name="edit_comment" />
+ <Action name="edit_uncomment" />
+ </Menu>
+
+ <Menu name="settings" noMerge="1"><text>&amp;Settings</text>
+ <Merge name="StandardToolBarMenuHandler" />
+ <Action name="options_show_statusbar"/>
+ <Separator />
+ <Menu name="Advanced settings"><text>&amp;Advanced Settings</text>
+ <Action name="set_confdlg" />
+ <Action name="options_configure_keybinding"/>
+ <Action name="options_configure_toolbars"/>
+ </Menu>
+ <Action name="options_configure"/>
+ </Menu>
+
+ <Menu name="help"><text>&amp;Help</text>
+ <Action name="context_help" />
+ </Menu>
+ </MenuBar>
+
+<ToolBar name="mainToolBar" noMerge="1" fullWidth="true" >
+ <Action name="file_new" />
+ <Action name="file_open" />
+ <Separator />
+ <Action name="file_save" />
+ <Action name="file_save_as" />
+ <Separator />
+ <Action name="file_print" />
+ <Separator />
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ <Separator />
+ <Action name="edit_cut" />
+ <Action name="edit_copy" />
+ <Action name="edit_paste" />
+ <Separator />
+ <Action name="color_picker" />
+ <Separator />
+ <Action name="full_screen" />
+ <Separator />
+ <Action name="speed" />
+ <Action name="run" />
+ <Action name="pause" />
+ <Action name="stop" />
+</ToolBar>
+
+</kpartgui>
diff --git a/kturtle/src/lexer.cpp b/kturtle/src/lexer.cpp
new file mode 100644
index 00000000..1a480641
--- /dev/null
+++ b/kturtle/src/lexer.cpp
@@ -0,0 +1,411 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <qdom.h>
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "settings.h"
+
+#include "lexer.h"
+
+
+Lexer::Lexer(QTextIStream& iStream)
+{
+ inputStream = &iStream;
+ row = 1;
+ col = 1;
+ prevCol = 1;
+ translate = new Translate();
+}
+
+
+Token Lexer::lex()
+{
+ skipSpaces(); // skips the white space that it quite likely (indentation) infront of the Token
+
+ Token currentToken;
+ currentToken.type = tokNotSet; // not really needed
+ currentToken.look = "";
+ currentToken.value = 0;
+ currentToken.start.row = row;
+ currentToken.start.col = col;
+
+ QChar currentChar = getChar();
+
+ if ( inputStream->atEnd() )
+ {
+ kdDebug(0)<<"Lexer::lex(), got EOF."<<endl;
+ currentToken.type = tokEOF;
+ currentToken.look = "EOF";
+ ungetChar(currentChar); // unget the currentChar and fix the row/col values
+ return currentToken;
+ }
+
+ if (currentChar == '#')
+ {
+ while ( !inputStream->atEnd() && !(currentChar == '\x0a' || currentChar == '\n') )
+ currentChar = getChar();
+ }
+
+ // if (currentChar.category() == QChar::Separator_Line) somehow doesnt work
+ if (currentChar == '\x0a' || currentChar == '\n')
+ {
+ currentToken.type = tokEOL;
+ currentToken.look = "EOL";
+ }
+ else if (currentChar.isLetter() || currentChar == '[' || currentChar == ']')
+ {
+ ungetChar(currentChar);
+ // sets currentToken.look by reference, and set the currentToken.type to tokUnknown
+ currentToken.type = getWord(currentToken.look);
+ setTokenType(currentToken); // gets the actual tokenType
+ }
+ else if ( currentChar.isNumber() )
+ {
+ ungetChar(currentChar);
+ // set currentToken.value/look by reference, and set the currentToken.type to tokNumber
+ currentToken.type = getNumber(currentToken.value, currentToken.look);
+ }
+ else if (currentChar == '>')
+ {
+ currentChar = getChar();
+ if (currentChar == '=')
+ {
+ currentToken.type = tokGe;
+ currentToken.look = ">=";
+ }
+ else
+ {
+ ungetChar(currentChar);
+ currentToken.type = tokGt;
+ currentToken.look = ">";
+ }
+ }
+ else if (currentChar == '<')
+ {
+ currentChar = getChar();
+ if ( currentChar == '=' )
+ {
+ currentToken.type = tokLe;
+ currentToken.look = "<=";
+ }
+ else
+ {
+ ungetChar(currentChar);
+ currentToken.type = tokLt;
+ currentToken.look = ">";
+ }
+ }
+ else if (currentChar == '!')
+ {
+ currentChar = getChar();
+ if (currentChar == '=')
+ {
+ currentToken.type = tokNe;
+ currentToken.look = "!=";
+ }
+ else
+ {
+ ungetChar(currentChar);
+ currentToken.type = tokNot;
+ currentToken.look = "!";
+ }
+ }
+ else if (currentChar == '=')
+ {
+ currentChar = getChar();
+ if (currentChar == '=')
+ {
+ currentToken.type = tokEq;
+ currentToken.look = "==";
+ }
+ else
+ {
+ ungetChar(currentChar);
+ currentToken.type = tokAssign;
+ currentToken.look = "=";
+ }
+ }
+ else if (currentChar == '(')
+ {
+ currentToken.type = tokBraceOpen;
+ currentToken.look = "(";
+ }
+ else if (currentChar == ')')
+ {
+ currentToken.type = tokBraceClose;
+ currentToken.look = ")";
+ }
+ else if (currentChar == '+')
+ {
+ currentToken.type = tokPlus;
+ currentToken.look = "+";
+ }
+ else if (currentChar == '-')
+ {
+ currentToken.type = tokMinus;
+ currentToken.look = "-";
+ }
+ else if (currentChar == '*')
+ {
+ currentToken.type = tokMul;
+ currentToken.look = "*";
+ }
+ else if (currentChar == '/')
+ {
+ currentToken.type = tokDev;
+ currentToken.look = "/";
+ }
+ else if (currentChar == ',')
+ {
+ currentToken.type = tokComma;
+ currentToken.look = ",";
+ }
+ else if (currentChar == '"')
+ {
+ getString(currentToken);
+ }
+ else
+ {
+ currentToken.type = tokUnknown;
+ currentToken.look = currentChar;
+ }
+
+ currentToken.end.row = row;
+ currentToken.end.col = col;
+ return currentToken;
+}
+
+
+
+// PRIVATEs
+
+QChar Lexer::getChar()
+{
+ QChar c;
+ if ( !putBackChar.isNull() )
+ {
+ c = putBackChar; // use the char that is stored to be put back
+ // kdDebug(0)<<"Lexer::getChar(), restored: '"<<c<<"' @ ("<<row<<", "<<col<<")"<<endl;
+ putBackChar = QChar(); // and set putBackChar back to NULL
+ if (c == '\x0a' || c == '\n')
+ {
+ row++;
+ prevCol = col;
+ col = 1;
+ }
+ else
+ {
+ col++;
+ }
+ }
+ else
+ {
+ *inputStream >> c; // take a QChar of the inputStream
+ // kdDebug(0)<<"Lexer::getChar(): '"<<c<<"' @ ("<<row<<", "<<col<<")"<<endl;
+ if (c == '\x0a' || c == '\n')
+ {
+ row++;
+ prevCol = col;
+ col = 1;
+ }
+ else
+ {
+ col++;
+ }
+ }
+ return c;
+}
+
+void Lexer::ungetChar(QChar c)
+{
+ if (c == '\x0a' || c == '\n')
+ {
+ row--;
+ col = prevCol;
+ }
+ else
+ {
+ col--;
+ }
+ putBackChar = c;
+ // kdDebug(0)<<"Lexer::ungetChar(), saved char: '"<<c<<"' and steped back to ("<<row<<", "<<col<<")"<<endl;
+}
+
+int Lexer::getWord(QString& word)
+{
+ // kdDebug(0)<<"Lexer::getWord()"<<endl;
+ QChar currentChar = getChar();
+ if ( currentChar.isLetter() || currentChar == '[' || currentChar == ']' ) {
+ while ( ( currentChar.isLetterOrNumber() || currentChar == '_' || currentChar == '[' || currentChar == ']' ) && !inputStream->atEnd() )
+ {
+ word += currentChar;
+ currentChar = getChar();
+ }
+ kdDebug(0)<<"Lexer::getWord(), got NAME: '"<<word<<"'"<<endl;
+ ungetChar(currentChar); //read one too much
+ return tokUnknown; // returns tokUnknown, actual token is to be determained later in Lexer::setTokenType
+ }
+ else return tokError;
+}
+
+void Lexer::setTokenType(Token& currentToken)
+{
+ if (currentToken.type == tokUnknown)
+ {
+ // make lowercase copy of the word as it was found in the inputStream
+ QString k = currentToken.look.lower();
+ // if the key is an alias translate that alias to a key
+ if ( !translate->alias2key(k).isEmpty() ) k = translate->alias2key(k);
+
+ if (k == translate->name2key("begin") ) currentToken.type = tokBegin;
+ else if (k == translate->name2key("end") ) currentToken.type = tokEnd;
+ else if (k == translate->name2key("while") ) currentToken.type = tokWhile;
+ else if (k == translate->name2key("if") ) currentToken.type = tokIf;
+ else if (k == translate->name2key("else") ) currentToken.type = tokElse;
+ else if (k == translate->name2key("for") ) currentToken.type = tokFor;
+ else if (k == translate->name2key("to") ) currentToken.type = tokTo;
+ else if (k == translate->name2key("step") ) currentToken.type = tokStep;
+ else if (k == translate->name2key("and") ) currentToken.type = tokAnd;
+ else if (k == translate->name2key("or") ) currentToken.type = tokOr;
+ else if (k == translate->name2key("not") ) currentToken.type = tokNot;
+ else if (k == translate->name2key("return") ) currentToken.type = tokReturn;
+ else if (k == translate->name2key("break") ) currentToken.type = tokBreak;
+ else if (k == translate->name2key("run") ) currentToken.type = tokRun;
+ else if (k == translate->name2key("foreach") ) currentToken.type = tokForEach;
+ else if (k == translate->name2key("in") ) currentToken.type = tokIn;
+
+ else if (k == translate->name2key("learn") ) currentToken.type = tokLearn;
+
+ else if (k == translate->name2key("clear") ) currentToken.type = tokClear;
+ else if (k == translate->name2key("go") ) currentToken.type = tokGo;
+ else if (k == translate->name2key("gox") ) currentToken.type = tokGoX;
+ else if (k == translate->name2key("goy") ) currentToken.type = tokGoY;
+ else if (k == translate->name2key("forward") ) currentToken.type = tokForward;
+ else if (k == translate->name2key("backward") ) currentToken.type = tokBackward;
+ else if (k == translate->name2key("direction") ) currentToken.type = tokDirection;
+ else if (k == translate->name2key("turnleft") ) currentToken.type = tokTurnLeft;
+ else if (k == translate->name2key("turnright") ) currentToken.type = tokTurnRight;
+ else if (k == translate->name2key("center") ) currentToken.type = tokCenter;
+ else if (k == translate->name2key("setpenwidth") ) currentToken.type = tokSetPenWidth;
+ else if (k == translate->name2key("penup") ) currentToken.type = tokPenUp;
+ else if (k == translate->name2key("pendown") ) currentToken.type = tokPenDown;
+ else if (k == translate->name2key("setfgcolor") ) currentToken.type = tokSetFgColor;
+ else if (k == translate->name2key("setbgcolor") ) currentToken.type = tokSetBgColor;
+ else if (k == translate->name2key("resizecanvas") ) currentToken.type = tokResizeCanvas;
+ else if (k == translate->name2key("spriteshow") ) currentToken.type = tokSpriteShow;
+ else if (k == translate->name2key("spritehide") ) currentToken.type = tokSpriteHide;
+ else if (k == translate->name2key("spritepress") ) currentToken.type = tokSpritePress;
+ else if (k == translate->name2key("spritechange") ) currentToken.type = tokSpriteChange;
+
+ else if (k == translate->name2key("do") ) currentToken.type = tokDo; // dummy commands
+
+ else if (k == translate->name2key("message") ) currentToken.type = tokMessage;
+ else if (k == translate->name2key("inputwindow") ) currentToken.type = tokInputWindow;
+ else if (k == translate->name2key("print") ) currentToken.type = tokPrint;
+ else if (k == translate->name2key("fonttype") ) currentToken.type = tokFontType;
+ else if (k == translate->name2key("fontsize") ) currentToken.type = tokFontSize;
+ else if (k == translate->name2key("repeat") ) currentToken.type = tokRepeat;
+ else if (k == translate->name2key("random") ) currentToken.type = tokRandom;
+ else if (k == translate->name2key("wait") ) currentToken.type = tokWait;
+ else if (k == translate->name2key("wrapon") ) currentToken.type = tokWrapOn;
+ else if (k == translate->name2key("wrapoff") ) currentToken.type = tokWrapOff;
+ else if (k == translate->name2key("reset") ) currentToken.type = tokReset;
+ else
+ {
+ kdDebug(0)<<"Lexer::setTokenType, found UNKNOWN word @ ("<<currentToken.start.row<<", "<<currentToken.start.col<<"), can be anything"<<endl;
+ // t.type = tokUnknown; is allready
+ }
+
+ kdDebug(0)<<"Lexer::setTokenType, found tok-number: '"<<currentToken.type<<"' with the key: '"<<k<<"' @ ("<<currentToken.start.row<<", "<<currentToken.start.col<<")"<<endl;
+ }
+}
+
+
+void Lexer::skipSpaces()
+{
+ // kdDebug(0)<<"Lexer::skipSpaces(), skipping SPACES."<<endl;
+ QChar currentChar = getChar();
+ // when the Separator_* groups can be identified in the QChar thing would be easier
+ while ( !inputStream->atEnd() && ( currentChar.isSpace() && !(currentChar == '\x0a' || currentChar == '\n') ) )
+ {
+ currentChar = getChar();
+ }
+ ungetChar(currentChar); // unget the tokEOL we likely just found
+}
+
+
+int Lexer::getNumber(Value& num, QString& look)
+{
+ // by reference the value (Value) and look part are set
+ // kdDebug(0)<<"Lexer::getNumber()"<<endl;
+ bool hasPoint = false;
+ QChar currentChar = getChar();
+ if ( currentChar.isNumber() )
+ {
+ while ( ( currentChar.isNumber() || (currentChar == '.' && !hasPoint) ) && !inputStream->atEnd() )
+ {
+ if (currentChar == '.')
+ {
+ hasPoint = true;
+ }
+ look += currentChar;
+ currentChar = getChar();
+ }
+ ungetChar(currentChar); //read one too much
+ num.setNumber( look.toDouble() );
+ kdDebug(0)<<"Lexer::getNumber(), got NUMBER: '"<<num.Number()<<"'"<<endl;
+ return tokNumber;
+ }
+ else return tokError;
+}
+
+void Lexer::getString(Token& currentToken)
+{
+ QString str = "\""; // start with a " cauz it just got lost
+ QChar currentChar = QChar(); // start empty
+ while ( currentChar != '"' && !(currentChar == '\x0a' || currentChar == '\n') && !inputStream->atEnd() )
+ {
+ currentChar = getChar();
+ if (currentChar == '\\') // escape sequence
+ {
+ currentChar = getChar();
+ switch (currentChar)
+ {
+ case 'n': str += '\n'; break;
+ case 't': str += '\t'; break;
+ case 'f': str += '\f'; break;
+ case '"': str += '"'; break;
+ }
+ }
+ else if (currentChar == '\x0a' || currentChar == '\n') // if the user forgot to delimit the string
+ {
+ ungetChar(currentChar);
+ break;
+ }
+ else str += currentChar;
+ }
+ currentToken.type = tokString;
+ currentToken.look = str;
+
+ kdDebug(0)<<"Lexer::getStringConstant, got STRINGCONSTANT: "<<currentToken.look<<"'"<<endl;
+}
+
diff --git a/kturtle/src/lexer.h b/kturtle/src/lexer.h
new file mode 100644
index 00000000..49317f8e
--- /dev/null
+++ b/kturtle/src/lexer.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _LEXER_H_
+#define _LEXER_H_
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+#include "token.h"
+#include "translate.h"
+#include "value.h"
+
+
+class Lexer
+{
+ public:
+ Lexer(QTextIStream&);
+ ~Lexer() {}
+
+ Token lex(); // returns the next Token, skipping spaces
+
+
+ private:
+ QChar getChar();
+ void ungetChar(QChar);
+ int getWord(QString&);
+ void skipSpaces();
+ void setTokenType(Token&);
+ int getNumber(Value&, QString&);
+ void getString(Token&);
+
+ QTextIStream *inputStream;
+ Translate *translate;
+ uint row, col, prevCol;
+ QChar putBackChar;
+};
+
+
+#endif // _LEXER_H_
+
+
diff --git a/kturtle/src/main.cpp b/kturtle/src/main.cpp
new file mode 100644
index 00000000..d9bf7eab
--- /dev/null
+++ b/kturtle/src/main.cpp
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2003 Cies Breijs <cies # kde ! nl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+
+#include "kturtle.h"
+
+
+static const char description[] =
+ I18N_NOOP("Educational Programming Environment using the Logo programming language");
+
+static const char version[] = "0.6";
+
+static const char copyright[] = I18N_NOOP("(C) 2003 The KTurtle Authors");
+
+static const char website[] = "http://edu.kde.org/kturtle";
+
+static KCmdLineOptions options[] =
+{
+/// @todo so some about the command line arguments... Something like:
+// { "e <argument>", I18N_NOOP( "sets the folder with the examples to <argument>" ), 0 }
+// { "t <argument>", I18N_NOOP( "sets the xml file containing the translatiosns of the Logo commands" ), 0 }
+// { "h <argument>", I18N_NOOP( "sets the xml file containing the highlightstyle" ), 0 }
+// { "+[URL]", I18N_NOOP( "A Logo file to open" ), 0 },
+ KCmdLineLastOption
+};
+
+
+int main(int argc, char **argv)
+{
+ KAboutData about("kturtle", I18N_NOOP("KTurtle"), version, description, KAboutData::License_GPL, copyright, 0, website);
+ about.addAuthor("Cies Breijs",
+ I18N_NOOP("Main developer and initiator"),
+ "cies # kde.nl");
+ about.addAuthor("Anne-Marie Mahfouf",
+ I18N_NOOP("Big contributor, supporter and fan"),
+ "annemarie.mahfouf # free.fr");
+ about.addAuthor("Walter Schreppers",
+ I18N_NOOP("Author of \"wsbasic\" (wsbasic.sf.net) the base for the interpreter of KTurtle"),
+ "Walter.Schreppers # ua.ac.be");
+ about.addCredit("Matthias Meßmer",
+ I18N_NOOP("German Data Files"),
+ "bmlmessmer # web.de");
+ about.addCredit("Burkhard Lück",
+ I18N_NOOP("German Data Files"),
+ "lueck # hube-lueck.de");
+ about.addCredit("Stefan Asserhäll",
+ I18N_NOOP("Swedish Data Files"),
+ "stefan.asserhall # telia.com");
+ about.addCredit("Jure Repinc",
+ I18N_NOOP("Slovenian Data Files"),
+ "jlp # holodeck1.com");
+ about.addCredit("Chusslove Illich",
+ I18N_NOOP("Serbian (Latin and Cyrillic) Data Files"),
+ "caslav.ilic # gmx.net");
+ about.addCredit("Pino Toscano",
+ I18N_NOOP("Italian Data Files"),
+ "toscano.pino # tiscali.it");
+ about.addCredit("Andy Potter",
+ I18N_NOOP("British English Data Files"),
+ "A.J.Potter # rhul.ac.uk");
+ about.addCredit("Rafael Beccar",
+ I18N_NOOP("Spanish Data Files"),
+ "rafael.beccar # kdemail.net");
+ about.addCredit("Riverson Rios",
+ I18N_NOOP("Brazilian Portuguese Data Files"),
+ "riverson # ccv.ufc.br");
+ about.addCredit("Karl Ove Hufthammer",
+ I18N_NOOP("Norwegian Nynorsk and Bokmål Data files"), "karl # huftis.org");
+ about.addCredit("Albert Astals Cid",
+ I18N_NOOP("Parser Cyrillic support"),
+ "astals11 # terra.es");
+ KCmdLineArgs::init(argc, argv, &about);
+ KCmdLineArgs::addCmdLineOptions( options );
+ KApplication app;
+ MainWindow *mainwindow = 0;
+
+ if ( app.isRestored() )
+ {
+ RESTORE(MainWindow);
+ }
+ else
+ {
+ // no session... just start up normally
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ /// @todo do something with the command line args here
+
+ mainwindow = new MainWindow();
+ app.setMainWidget(mainwindow);
+ mainwindow->show();
+
+ args->clear();
+ }
+
+ // mainwindow has WDestructiveClose flag by default, so it will delete itself.
+ return app.exec();
+}
diff --git a/kturtle/src/parser.cpp b/kturtle/src/parser.cpp
new file mode 100644
index 00000000..ca1fafd7
--- /dev/null
+++ b/kturtle/src/parser.cpp
@@ -0,0 +1,1084 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+// This file is originally written by Walter Scheppers, but allmost
+// allmost every aspect of it is heavily changed by Cies Breijs.
+
+
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "parser.h"
+
+
+Parser::Parser(QTextIStream& in)
+{
+ lexer = new Lexer(in);
+ tree = new TreeNode();
+}
+
+Parser::~Parser()
+{
+ delete lexer;
+}
+
+void Parser::parse()
+{
+ tree = Program(); // the first node that keeps the lexer running till finished/error
+}
+
+void Parser::getToken()
+{
+ currentToken = lexer->lex(); // stores a Token, obtained though the lexer, in 'currentToken'
+ row = currentToken.start.row; // these will have to leave eventually, all should be passed on by the Token
+ col = currentToken.start.col;
+ kdDebug(0)<<"Parser::getToken(), got a token: '"<<currentToken.look<<"', @ ("<<currentToken.start.row<<", "<<currentToken.start.col<<") - ("<<currentToken.end.row<<", "<<currentToken.end.col<<"), tok-number:"<<currentToken.type<<endl;
+}
+
+TreeNode* Parser::Program()
+{
+ Token emptyToken;
+ emptyToken.type = tokNotSet;
+ emptyToken.look = "";
+ emptyToken.start.row = 0;
+ emptyToken.start.col = 0;
+ emptyToken.end.row = 0;
+ emptyToken.end.col = 0;
+
+ TreeNode* program = new TreeNode(emptyToken, programNode, "program");
+ TreeNode* block = new TreeNode(emptyToken, blockNode, "block");
+
+ getToken();
+
+ // this is the main parse loop
+ kdDebug(0)<<"Parser::Program(): entering main parse loop..."<<endl;
+ while (currentToken.type != tokEOF) // currentToken.type returns the type of the currentToken
+ {
+ kdDebug(0)<<"Parser::Program(), [main parse loop]: looking for next statement..."<<endl;
+ block->appendChild( Statement() );
+ while (currentToken.type == tokEOL) getToken(); // newlines between statements are allowed
+ // runs statement related code, stores the returned TreeNode* in the nodetree
+ // note: Statement() allways gets a new Token with getToken() before it returns
+ }
+ program->appendChild(block);
+ kdDebug(0)<<"Parser::Program(): leaving main parse loop..."<<endl;
+
+ return program;
+}
+
+void Parser::matchToken(int expectedToken)
+{
+ if (currentToken.type == expectedToken)
+ {
+ getToken(); // get a new token
+ return;
+ }
+
+ switch (expectedToken)
+ {
+ case tokEOL:
+ Error(currentToken, i18n("Unexpected intruction after the '%1' command, please use only one instruction per line").arg(preservedToken.look), 1010);
+ break;
+
+ case tokBegin:
+ Error(preservedToken, i18n("Expected '['"), 1010);
+ break;
+
+ case tokTo:
+ Error(currentToken, i18n("Expected 'to' after the '%1' command").arg(preservedToken.look), 1010);
+ break;
+
+ case tokAssign:
+ Error(currentToken, i18n("Expected '=' after the '%1' command").arg(preservedToken.look), 1010);
+ break;
+
+ case tokEnd:
+ Error(currentToken, i18n("Expected ']' after the '%1' command").arg(preservedToken.look), 1010);
+ break;
+
+ case tokUnknown:
+ Error(preservedToken, i18n("Expected a name after the '%1' command").arg(preservedToken.look), 1010);
+ break;
+
+ default:
+ Error(currentToken, i18n("UNDEFINED ERROR NR %1: please send this Logo script to the KTurtle developers").arg(expectedToken), 1010);
+ break;
+ }
+}
+
+
+void Parser::appendParameters(TreeNode* node)
+{
+ node->appendChild( Expression() ); // append the first papameter
+ while (currentToken.type == tokComma)
+ {
+ matchToken(tokComma); // push through the comma
+ if (currentToken.type == tokEOL) return; // catch forgotten expressions, like "go 10, "
+ node->appendChild( Expression() );
+ }
+}
+
+
+TreeNode* Parser::getId()
+{
+ TreeNode* n = new TreeNode(currentToken, idNode);
+ n->setLook(currentToken.look);
+ matchToken(tokUnknown); // Id's are ofcouse not yet known
+ return n;
+}
+
+
+
+TreeNode* Parser::FunctionCall(Token maybeFunctionCall)
+{
+ kdDebug(0)<<"Parser::FunctionCall() [using identifier: '"<<maybeFunctionCall.look<<"']"<<endl;
+ TreeNode* fcall = new TreeNode(maybeFunctionCall, functionCallNode);
+
+ TreeNode* paramList = new TreeNode(currentToken, idListNode, "idlist");
+ // if (currentToken.type != tokEOL && currentToken.type != tokEOF)
+ if (currentToken.type == tokNumber ||
+ currentToken.type == tokString ||
+ currentToken.type == tokUnknown) // only if there is a possible parameter given after the call...
+ {
+ TreeNode* expr = Expression();
+ if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020);
+ else paramList->appendChild(expr);
+ while (currentToken.type == tokComma)
+ {
+ matchToken(tokComma);
+ expr = Expression();
+ if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020);
+ else paramList->appendChild(expr);
+ }
+ }
+ fcall->appendChild(paramList);
+
+ return fcall;
+}
+
+
+TreeNode* Parser::Factor()
+{
+ TreeNode* node;
+ Token rememberedToken = currentToken;
+ switch (currentToken.type)
+ {
+ case tokBraceOpen:
+ matchToken(tokBraceOpen);
+ node = Expression();
+ matchToken(tokBraceClose);
+ break;
+
+ case tokUnknown:
+ node = getId();
+ if (learnedFunctionList.contains(rememberedToken.look) > 0) // is function call
+ {
+ delete node;
+ node = FunctionCall(rememberedToken);
+ node->setType(funcReturnNode); // expect returned value on stack
+ }
+ break;
+
+ case tokString:
+ node = new TreeNode(currentToken, constantNode);
+ { // extra scope to localize the QString 'str'
+ QString str = currentToken.look;
+ if ( currentToken.look.endsWith("\"") )
+ {
+ // cut off the quotes and store the value
+ str.remove(0, 1).truncate( currentToken.look.length() - 2 );
+ }
+ else // problems but we need to keep it moving
+ {
+ str.remove(0, 1); // cut off the first quote only
+ Error(currentToken, i18n("String text not properly delimited with a ' \" ' (double quote)"), 1060);
+ }
+ node->setValue(str);
+ }
+ matchToken(tokString);
+ break;
+
+ case tokNumber:
+ node = new TreeNode(currentToken, constantNode);
+ node->setValue(currentToken.value);
+ matchToken(tokNumber);
+ break;
+
+ case tokRun:
+ node = ExternalRun();
+ break;
+
+ case tokInputWindow:
+ node = InputWindow();
+ break;
+
+ case tokRandom:
+ node = Random();
+ break;
+
+ case tokEOL:
+ node = new TreeNode(currentToken, Unknown);
+ break;
+
+ default:
+ QString s = currentToken.look;
+ if ( s.isEmpty() || currentToken.type == tokEOF )
+ {
+ Error(currentToken, i18n("INTERNAL ERROR NR %1: please sent this Logo script to KTurtle developers").arg(1), 1020);
+ // if this error occurs the see the Parser::Repeat for the good solution using 'preservedToken'
+ }
+ else
+ {
+ Error(currentToken, i18n("Cannot understand '%1', expected an expression after the '%2' command").arg(s).arg(preservedToken.look), 1020);
+ }
+ node = new TreeNode(currentToken, Unknown);
+ getToken();
+ break;
+ }
+ return node;
+}
+
+
+TreeNode* Parser::signedFactor()
+{
+ // see if there is a tokPlus, tokMinus or tokNot infront of the factor
+ TreeNode* node;
+ switch (currentToken.type)
+ {
+ case tokPlus:
+ matchToken(tokPlus);
+ return Factor();
+ break;
+
+ case tokMinus:
+ preservedToken = currentToken;
+ matchToken(tokMinus);
+ node = Factor();
+ if (node->getType() == constantNode)
+ {
+ // in case of just a constant (-3) situation
+ Value num = node->getValue();
+ num.setNumber( -num.Number() );
+ node->setValue(num);
+ return node;
+ }
+ else
+ {
+ // in case of a variable or other situation (-a)
+ TreeNode* minus = new TreeNode(preservedToken, minusNode);
+ minus->appendChild(node);
+ return minus;
+ }
+ break;
+
+ case tokNot:
+ preservedToken = currentToken;
+ matchToken(tokNot);
+ node = Factor();
+ { // extra scope needed to localize not_Node
+ TreeNode* not_Node = new TreeNode(preservedToken, notNode);
+ not_Node->appendChild(node);
+ return not_Node;
+ }
+ break;
+
+ default:
+ // fall-through safety
+ return Factor();
+ break;
+ }
+}
+
+
+
+TreeNode* Parser::Term()
+{
+ TreeNode* termNode = signedFactor();
+ TreeNode* pos = termNode;
+ TreeNode* left = NULL;
+ TreeNode* right = NULL;
+
+ while ( (currentToken.type == tokMul) || (currentToken.type == tokDev) || (currentToken.type == tokAnd) )
+ {
+ // while is is a multiplicative operator do...
+ left = pos;
+ pos = new TreeNode(currentToken, Unknown);
+ pos->appendChild(left);
+
+ switch (currentToken.type)
+ {
+ case tokMul:
+ matchToken(tokMul);
+ right = signedFactor();
+ pos->setType(mulNode);
+ break;
+
+ case tokDev:
+ matchToken(tokDev);
+ right = signedFactor();
+ pos->setType(divNode);
+ break;
+
+ case tokAnd:
+ matchToken(tokAnd);
+ right = signedFactor();
+ pos->setType(andNode);
+ break;
+
+ default:
+ Error(currentToken, i18n("Expected '*' or '/'"), 1030);
+ getToken();
+ return pos;
+ break;
+ }
+ if (right != NULL) pos->appendChild(right);
+ termNode = pos;
+ }
+ return termNode;
+}
+
+
+bool Parser::isAddOp(Token t)
+{
+ return ( (t.type == tokPlus) ||
+ (t.type == tokMinus) ||
+ (t.type == tokGt) ||
+ (t.type == tokGe) ||
+ (t.type == tokLt) ||
+ (t.type == tokLe) ||
+ (t.type == tokEq) ||
+ (t.type == tokNe) ||
+
+ (t.type == tokOr) ||
+ (t.type == tokGe) );
+}
+
+
+/*---------------------------------------------------------------*/
+/* Parse and Translate an Expression */
+TreeNode* Parser::Expression()
+{
+ TreeNode* retExp = Term(); // preset the base-TreeNode as it eventually will be returned
+ TreeNode* pos = retExp;
+ TreeNode* left = NULL;
+ TreeNode* right = NULL;
+
+ while ( isAddOp(currentToken) )
+ {
+ left = pos;
+ pos = new TreeNode(currentToken, Unknown);
+ pos->appendChild(left);
+ switch (currentToken.type)
+ {
+ case tokPlus:
+ matchToken(tokPlus);
+ right = Term();
+ pos->setType(addNode);
+ break;
+
+ case tokMinus:
+ matchToken(tokMinus);
+ right = Term();
+ pos->setType(subNode);
+ break;
+
+ case tokGt:
+ matchToken(tokGt);
+ right = Term();
+ pos->setType(nodeGT);
+ break;
+
+ case tokLt:
+ matchToken(tokLt);
+ right = Term();
+ pos->setType(nodeLT);
+ break;
+
+ case tokGe:
+ matchToken(tokGe);
+ right = Term();
+ pos->setType(nodeGE);
+ break;
+
+ case tokLe:
+ matchToken(tokLe);
+ right = Term();
+ pos->setType(nodeLE);
+ break;
+
+ case tokEq:
+ matchToken(tokEq);
+ right = Term();
+ pos->setType(nodeEQ);
+ break;
+
+ case tokNe:
+ matchToken(tokNe);
+ right = Term();
+ pos->setType(nodeNE);
+ break;
+
+ case tokOr:
+ matchToken(tokOr);
+ right = Term();
+ pos->setType(orNode);
+ break;
+
+ default:
+ Error(currentToken, i18n("Expected '*' or '/'"), 1040);
+ getToken();
+ return pos;
+ break;
+ }
+ if (right != NULL) pos->appendChild(right);
+ retExp = pos;
+ }
+ return retExp;
+}
+
+
+TreeNode* Parser::Assignment(Token t)
+{
+ TreeNode* node = new TreeNode(t, assignNode);
+ matchToken(tokAssign); // match the '='
+
+ // the child is the expression or RHV of assignment
+ TreeNode* expr = NULL;
+// if (currentToken.type == tokUnknown) expr = Other(); // in case of an functioncall
+// else expr = Expression(); -------> fuctioncalls get caught in Expression() and co.
+
+ expr = Expression();
+
+ node->appendChild(expr);
+
+ return node;
+}
+
+
+TreeNode* Parser::Statement()
+{
+ kdDebug(0)<<"Parser::Statement()"<<endl;
+ while (currentToken.type == tokEOL) getToken(); // statements can allways start on newlines
+ switch (currentToken.type)
+ {
+ case tokLearn : return Learn(); break;
+
+ case tokIf : return If(); break;
+ case tokFor : return For(); break;
+ case tokForEach : return ForEach(); break;
+ case tokWhile : return While(); break;
+ case tokRun : return ExternalRun(); break;
+ case tokReturn : return Return(); break;
+ case tokBreak : return Break(); break;
+ case tokUnknown : return Other(); break; //assignment or function call
+
+ case tokClear : return Clear(); break;
+ case tokGo : return Go(); break;
+ case tokGoX : return GoX(); break;
+ case tokGoY : return GoY(); break;
+ case tokForward : return Forward(); break;
+ case tokBackward : return Backward(); break;
+ case tokDirection : return Direction(); break;
+ case tokTurnLeft : return TurnLeft(); break;
+ case tokTurnRight : return TurnRight(); break;
+ case tokCenter : return Center(); break;
+ case tokSetPenWidth : return SetPenWidth(); break;
+ case tokPenUp : return PenUp(); break;
+ case tokPenDown : return PenDown(); break;
+ case tokSetFgColor : return SetFgColor(); break;
+ case tokSetBgColor : return SetBgColor(); break;
+ case tokResizeCanvas : return ResizeCanvas(); break;
+ case tokSpriteShow : return SpriteShow(); break;
+ case tokSpriteHide : return SpriteHide(); break;
+ case tokSpritePress : return SpritePress(); break;
+ case tokSpriteChange : return SpriteChange(); break;
+
+ case tokPrint : return Print(); break;
+ case tokInputWindow : return InputWindow(); break;
+ case tokMessage : return Message(); break;
+ case tokFontType : return FontType(); break;
+ case tokFontSize : return FontSize(); break;
+ case tokRepeat : return Repeat(); break;
+ case tokRandom : return Random(); break;
+ case tokWait : return Wait(); break;
+ case tokWrapOn : return WrapOn(); break;
+ case tokWrapOff : return WrapOff(); break;
+ case tokReset : return Reset(); break;
+
+ case tokEOF : return EndOfFile(); break;
+
+ case tokEnd : Error(currentToken, i18n("Cannot understand ']'"), 1050);
+ getToken();
+ return new TreeNode(currentToken, Unknown);
+ break;
+
+ case tokBegin : Error(currentToken, i18n("Cannot understand '['"), 1050);
+ getToken();
+ return new TreeNode(currentToken, Unknown);
+ break;
+
+ default : break;
+ }
+ if (currentToken.type != tokEnd)
+ {
+ Error(currentToken, i18n("Cannot understand '%1'").arg(currentToken.look), 1060);
+ }
+
+ getToken();
+ return new TreeNode(currentToken, Unknown); // fall-though for unknowns
+}
+
+
+TreeNode* Parser::Block()
+{
+ TreeNode* block = new TreeNode(currentToken, blockNode, "block");
+
+ while (currentToken.type == tokEOL) getToken(); // skip newlines
+ matchToken(tokBegin);
+ while (currentToken.type == tokEOL) getToken(); // skip newlines
+ while ( (currentToken.type != tokEnd) && (currentToken.type != tokEOF) )
+ {
+ block->appendChild( Statement() );
+ while (currentToken.type == tokEOL) getToken(); // blocks can have newlines between their statements
+ }
+ matchToken(tokEnd);
+ return block;
+}
+
+
+//
+// Turtle Funktions
+//
+
+// Functions that take NO arguments
+
+TreeNode* Parser::Clear()
+{
+ TreeNode* node = new TreeNode(currentToken, ClearNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Center()
+{
+ TreeNode* node = new TreeNode(currentToken, CenterNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::PenUp()
+{
+ TreeNode* node = new TreeNode(currentToken, PenUpNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::PenDown()
+{
+ TreeNode* node = new TreeNode(currentToken, PenDownNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::SpriteShow()
+{
+ TreeNode* node = new TreeNode(currentToken, SpriteShowNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::SpriteHide()
+{
+ TreeNode* node = new TreeNode(currentToken, SpriteHideNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::SpritePress()
+{
+ TreeNode* node = new TreeNode(currentToken, SpritePressNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::WrapOn()
+{
+ TreeNode* node = new TreeNode(currentToken, WrapOnNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::WrapOff()
+{
+ TreeNode* node = new TreeNode(currentToken, WrapOffNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Reset()
+{
+ TreeNode* node = new TreeNode(currentToken, ResetNode);
+ preservedToken = currentToken;
+ getToken();
+ matchToken(tokEOL);
+ return node;
+}
+
+
+
+
+// Functions that take 1 arguments
+
+TreeNode* Parser::GoX()
+{
+ TreeNode* node = new TreeNode(currentToken, GoXNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+
+TreeNode* Parser::GoY()
+{
+ TreeNode* node = new TreeNode(currentToken, GoYNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+
+TreeNode* Parser::Forward()
+{
+ TreeNode* node = new TreeNode(currentToken, ForwardNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+
+TreeNode* Parser::Backward()
+{
+ TreeNode* node = new TreeNode(currentToken, BackwardNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Direction()
+{
+ TreeNode* node = new TreeNode(currentToken, DirectionNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::TurnLeft()
+{
+ TreeNode* node = new TreeNode(currentToken, TurnLeftNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::TurnRight()
+{
+ TreeNode* node = new TreeNode(currentToken, TurnRightNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::SetPenWidth()
+{
+ TreeNode* node = new TreeNode(currentToken, SetPenWidthNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Message()
+{
+ TreeNode* node = new TreeNode(currentToken, MessageNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::InputWindow()
+{
+ TreeNode* node = new TreeNode(currentToken, InputWindowNode);
+ preservedToken = currentToken;
+ getToken();
+ node->appendChild( Expression() );
+ // matchToken(tokEOL); this command can return values so can be used as expression/parameter
+ return node;
+}
+
+TreeNode* Parser::SpriteChange()
+{
+ TreeNode* node = new TreeNode(currentToken, SpriteChangeNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::FontType()
+{
+ TreeNode* node = new TreeNode(currentToken, FontTypeNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::FontSize()
+{
+ TreeNode* node = new TreeNode(currentToken, FontSizeNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Wait()
+{
+ TreeNode* node = new TreeNode(currentToken, WaitNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::ExternalRun()
+{
+ TreeNode* node = new TreeNode(currentToken, runNode);
+ preservedToken = currentToken;
+ getToken();
+ node->appendChild( Expression() );
+ // matchToken(tokEOL); this command can return values so can be used as expression/parameter
+ return node;
+}
+
+
+
+// Functions that take 2 arguments
+
+TreeNode* Parser::Go()
+{
+ TreeNode* node = new TreeNode(currentToken, GoNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::ResizeCanvas()
+{
+ TreeNode* node = new TreeNode(currentToken, ResizeCanvasNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Random()
+{
+ TreeNode* node = new TreeNode(currentToken, RandomNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ // matchToken(tokEOL); this command can return values so can be used as expression/parameter
+ return node;
+}
+
+
+
+
+// Functions that take 3 arguments
+
+TreeNode* Parser::SetFgColor()
+{
+ TreeNode* node = new TreeNode(currentToken, SetFgColorNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::SetBgColor()
+{
+ TreeNode* node = new TreeNode(currentToken, SetBgColorNode);
+ preservedToken = currentToken;
+ getToken();
+ appendParameters(node);
+ matchToken(tokEOL);
+ return node;
+}
+
+
+
+
+// Weirdo's (learn, execution controllers, print, and Other()s)
+
+TreeNode* Parser::Learn()
+{
+ preservedToken = currentToken;
+ matchToken(tokLearn); // skip the 'dummy' command
+ TreeNode* func = new TreeNode(currentToken, functionNode);
+ getToken(); // get the token after the function's name
+
+ TreeNode* idList = new TreeNode(currentToken, idListNode, "idlist");
+ if (currentToken.type != tokBegin)
+ {
+ if (currentToken.type == tokUnknown) idList->appendChild( getId() );
+ else
+ {
+ Error(currentToken, "Expected a parameter name or a '[' after the learn command.", 3030);
+ getToken(); // this recovers from the error
+ }
+
+ while (currentToken.type == tokComma)
+ {
+ matchToken(tokComma);
+ idList->appendChild( getId() );
+ }
+ }
+ func->appendChild(idList);
+
+ learnedFunctionList.append( func->getLook() ); // publish the function
+
+ func->appendChild( Block() );
+
+ return func;
+}
+
+
+TreeNode* Parser::If()
+{
+ TreeNode* node = new TreeNode(currentToken, ifNode);
+ preservedToken = currentToken;
+ matchToken(tokIf);
+
+ node->appendChild( Expression() );
+
+ if (currentToken.type == tokDo) getToken(); // skip dummy word 'do'
+
+ if (currentToken.type == tokBegin) node->appendChild( Block() ); // if followed by a block
+ else node->appendChild( Statement() ); // if followed by single statement
+
+ while (currentToken.type == tokEOL) getToken(); // allow the else keyword to be on later lines
+
+ if (currentToken.type == tokElse) // else part
+ {
+ matchToken(tokElse);
+ while (currentToken.type == tokEOL) getToken();
+ if (currentToken.type == tokDo) getToken(); // next word
+
+ if(currentToken.type == tokBegin) node->appendChild( Block() ); // else is followed by block
+ else node->appendChild( Statement() );
+ }
+
+ return node;
+}
+
+
+TreeNode* Parser::While()
+{
+ TreeNode* node = new TreeNode(currentToken, whileNode);
+ preservedToken = currentToken;
+ matchToken(tokWhile);
+ node->appendChild( Expression() );
+ node->appendChild( Block() );
+ return node;
+}
+
+
+TreeNode* Parser::For()
+{
+ TreeNode* fNode = new TreeNode(currentToken, forNode);
+ preservedToken = currentToken;
+ matchToken(tokFor);
+ fNode->appendChild( getId() ); // loop id
+ matchToken(tokAssign);
+
+ fNode->appendChild( Expression() ); // start value expression
+ matchToken(tokTo);
+ fNode->appendChild( Expression() ); // stop value expression
+
+ if (currentToken.type == tokStep)
+ {
+ matchToken(tokStep);
+ fNode->appendChild( Expression() ); //step expression
+ }
+
+ while (currentToken.type == tokEOL) getToken(); // newlines are allowed
+ if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block
+ else fNode->appendChild( Statement() ); // while followed by single statement
+
+ return fNode;
+}
+
+
+TreeNode* Parser::Repeat()
+{
+ TreeNode* node = new TreeNode(currentToken, RepeatNode);
+ preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost
+ matchToken(tokRepeat);
+ node->appendChild( Expression() );
+ node->appendChild( Block() );
+ return node;
+}
+
+
+
+TreeNode* Parser::ForEach()
+{
+ TreeNode* fNode = new TreeNode(currentToken, forEachNode);
+ preservedToken = currentToken;
+ matchToken(tokForEach);
+
+ fNode->appendChild( Expression() );
+ matchToken(tokIn);
+ fNode->appendChild( Expression() );
+
+ if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block
+ else fNode->appendChild( Statement() ); // while followed by single statement
+
+ return fNode;
+}
+
+TreeNode* Parser::Print()
+{
+ TreeNode* node = new TreeNode(currentToken, printNode);
+ preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost
+ getToken();
+ if (currentToken.type == tokEOL) return node; // print called without expressions
+ node->appendChild( Expression() ); // first expression
+ // following strings or expressions
+ while (currentToken.type == tokComma)
+ {
+ getToken(); // the comma
+ node->appendChild( Expression() );
+ }
+ matchToken(tokEOL);
+ return node;
+}
+
+TreeNode* Parser::Return()
+{
+ TreeNode* ret = new TreeNode(currentToken, returnNode);
+ matchToken(tokReturn);
+
+ ret->appendChild( Expression() );
+
+ return ret;
+}
+
+TreeNode* Parser::Break()
+{
+ TreeNode* brk = new TreeNode(currentToken, breakNode);
+ matchToken(tokBreak);
+
+ return brk;
+}
+
+TreeNode* Parser::EndOfFile()
+{
+ TreeNode* node = new TreeNode(currentToken, EndOfFileNode);
+ return node;
+}
+
+TreeNode* Parser::Other()
+{
+ // this is either an assignment or a function call!
+ kdDebug(0)<<"Parser::Other()"<<endl;
+ Token rememberedToken = currentToken; // preserve token, else Match() will make sure it gets lost
+ matchToken(tokUnknown);
+
+ if (currentToken.type == tokAssign) return Assignment(rememberedToken);
+ else if (learnedFunctionList.contains(rememberedToken.look) > 0)
+ {
+ TreeNode* node;
+ node = FunctionCall(rememberedToken);
+// node->setType(funcReturnNode);
+ return node;
+ }
+
+ Error(rememberedToken, i18n("'%1' is neither a Logo command nor a learned command.").arg(rememberedToken.look), 1020);
+ TreeNode* errNode = new TreeNode(rememberedToken, Unknown);
+
+ // skip the rest of the line
+ while (currentToken.type != tokEOL) getToken();
+
+ return errNode;
+}
+
+
+void Parser::Error(Token& t, const QString& s, uint code)
+{
+ emit ErrorMsg(t, s, code);
+}
+
+
+#include "parser.moc"
diff --git a/kturtle/src/parser.h b/kturtle/src/parser.h
new file mode 100644
index 00000000..28be566f
--- /dev/null
+++ b/kturtle/src/parser.h
@@ -0,0 +1,126 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _PARSER_H_
+#define _PARSER_H_
+
+#include <qobject.h>
+
+#include "lexer.h"
+#include "treenode.h"
+
+
+class Parser : public QObject
+{
+ Q_OBJECT
+
+ public:
+ Parser(QTextIStream& in);
+ virtual ~Parser();
+
+ void parse();
+ TreeNode* getTree() const { return tree; }
+
+
+ signals:
+ void ErrorMsg(Token&, const QString&, uint code);
+
+
+ private:
+ bool isAddOp(Token);
+ bool isMulOp(Token);
+
+ void getToken();
+ void matchToken(int tokenType);
+ void appendParameters(TreeNode* node);
+ void Error(Token&, const QString& s, uint code);
+
+ TreeNode* Program();
+ TreeNode* ParamList();
+ TreeNode* Block();
+ TreeNode* Statement();
+
+ TreeNode* ExternalRun();
+
+ TreeNode* getId();
+ TreeNode* signedFactor();
+ TreeNode* Factor();
+ TreeNode* Term();
+ TreeNode* Expression();
+
+ TreeNode* Assignment(Token);
+ TreeNode* FunctionCall(Token);
+ TreeNode* Other();
+
+ TreeNode* While();
+ TreeNode* For();
+ TreeNode* ForEach();
+ TreeNode* If();
+ TreeNode* Return();
+ TreeNode* Break();
+
+ TreeNode* Clear();
+ TreeNode* Go();
+ TreeNode* GoX();
+ TreeNode* GoY();
+ TreeNode* Forward();
+ TreeNode* Backward();
+ TreeNode* Direction();
+ TreeNode* TurnLeft();
+ TreeNode* TurnRight();
+ TreeNode* Center();
+ TreeNode* SetPenWidth();
+ TreeNode* PenUp();
+ TreeNode* PenDown();
+ TreeNode* SetFgColor();
+ TreeNode* SetBgColor();
+ TreeNode* ResizeCanvas();
+ TreeNode* SpriteShow();
+ TreeNode* SpriteHide();
+ TreeNode* SpritePress();
+ TreeNode* SpriteChange();
+
+ TreeNode* Message();
+ TreeNode* InputWindow();
+ TreeNode* Print();
+ TreeNode* FontType();
+ TreeNode* FontSize();
+ TreeNode* Repeat();
+ TreeNode* Random();
+ TreeNode* Wait();
+ TreeNode* WrapOn();
+ TreeNode* WrapOff();
+ TreeNode* Reset();
+
+ TreeNode* LineBreak();
+ TreeNode* EndOfFile();
+
+ TreeNode* Learn();
+
+ //private locals
+ Lexer *lexer;
+ TreeNode *tree;
+ Token currentToken;
+ Token preservedToken; // to preserve the currentToken so it wont get lost
+ uint row;
+ uint col;
+ QStringList learnedFunctionList;
+};
+
+#endif // _PARSER_H_
diff --git a/kturtle/src/pics/Makefile.am b/kturtle/src/pics/Makefile.am
new file mode 100644
index 00000000..2d3c312f
--- /dev/null
+++ b/kturtle/src/pics/Makefile.am
@@ -0,0 +1,8 @@
+picsdir = $(kde_datadir)/kturtle/pics
+pics_DATA = turtle.0000.png turtle.0006.png turtle.0012.png turtle.0018.png turtle.0024.png turtle.0030.png \
+turtle.0001.png turtle.0007.png turtle.0013.png turtle.0019.png turtle.0025.png turtle.0031.png \
+turtle.0002.png turtle.0008.png turtle.0014.png turtle.0020.png turtle.0026.png turtle.0032.png \
+turtle.0003.png turtle.0009.png turtle.0015.png turtle.0021.png turtle.0027.png turtle.0033.png \
+turtle.0004.png turtle.0010.png turtle.0016.png turtle.0022.png turtle.0028.png turtle.0034.png \
+turtle.0005.png turtle.0011.png turtle.0017.png turtle.0023.png turtle.0029.png turtle.0035.png
+EXTRA_DIST = $(pics_DATA)
diff --git a/kturtle/src/pics/turtle.0000.png b/kturtle/src/pics/turtle.0000.png
new file mode 100644
index 00000000..5bdf2768
--- /dev/null
+++ b/kturtle/src/pics/turtle.0000.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0001.png b/kturtle/src/pics/turtle.0001.png
new file mode 100644
index 00000000..c6a17d5c
--- /dev/null
+++ b/kturtle/src/pics/turtle.0001.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0002.png b/kturtle/src/pics/turtle.0002.png
new file mode 100644
index 00000000..27419fcb
--- /dev/null
+++ b/kturtle/src/pics/turtle.0002.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0003.png b/kturtle/src/pics/turtle.0003.png
new file mode 100644
index 00000000..e8949259
--- /dev/null
+++ b/kturtle/src/pics/turtle.0003.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0004.png b/kturtle/src/pics/turtle.0004.png
new file mode 100644
index 00000000..0cb37fcd
--- /dev/null
+++ b/kturtle/src/pics/turtle.0004.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0005.png b/kturtle/src/pics/turtle.0005.png
new file mode 100644
index 00000000..b809ef2e
--- /dev/null
+++ b/kturtle/src/pics/turtle.0005.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0006.png b/kturtle/src/pics/turtle.0006.png
new file mode 100644
index 00000000..927d4bd8
--- /dev/null
+++ b/kturtle/src/pics/turtle.0006.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0007.png b/kturtle/src/pics/turtle.0007.png
new file mode 100644
index 00000000..18578690
--- /dev/null
+++ b/kturtle/src/pics/turtle.0007.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0008.png b/kturtle/src/pics/turtle.0008.png
new file mode 100644
index 00000000..4015a21e
--- /dev/null
+++ b/kturtle/src/pics/turtle.0008.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0009.png b/kturtle/src/pics/turtle.0009.png
new file mode 100644
index 00000000..6d0d55c6
--- /dev/null
+++ b/kturtle/src/pics/turtle.0009.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0010.png b/kturtle/src/pics/turtle.0010.png
new file mode 100644
index 00000000..19d4bbce
--- /dev/null
+++ b/kturtle/src/pics/turtle.0010.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0011.png b/kturtle/src/pics/turtle.0011.png
new file mode 100644
index 00000000..e5f08140
--- /dev/null
+++ b/kturtle/src/pics/turtle.0011.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0012.png b/kturtle/src/pics/turtle.0012.png
new file mode 100644
index 00000000..f317f4b5
--- /dev/null
+++ b/kturtle/src/pics/turtle.0012.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0013.png b/kturtle/src/pics/turtle.0013.png
new file mode 100644
index 00000000..cce82a0f
--- /dev/null
+++ b/kturtle/src/pics/turtle.0013.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0014.png b/kturtle/src/pics/turtle.0014.png
new file mode 100644
index 00000000..3b3c9687
--- /dev/null
+++ b/kturtle/src/pics/turtle.0014.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0015.png b/kturtle/src/pics/turtle.0015.png
new file mode 100644
index 00000000..08b2e0aa
--- /dev/null
+++ b/kturtle/src/pics/turtle.0015.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0016.png b/kturtle/src/pics/turtle.0016.png
new file mode 100644
index 00000000..ad66fc98
--- /dev/null
+++ b/kturtle/src/pics/turtle.0016.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0017.png b/kturtle/src/pics/turtle.0017.png
new file mode 100644
index 00000000..a81d01c8
--- /dev/null
+++ b/kturtle/src/pics/turtle.0017.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0018.png b/kturtle/src/pics/turtle.0018.png
new file mode 100644
index 00000000..f28eb0bd
--- /dev/null
+++ b/kturtle/src/pics/turtle.0018.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0019.png b/kturtle/src/pics/turtle.0019.png
new file mode 100644
index 00000000..1307d50b
--- /dev/null
+++ b/kturtle/src/pics/turtle.0019.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0020.png b/kturtle/src/pics/turtle.0020.png
new file mode 100644
index 00000000..a2232c03
--- /dev/null
+++ b/kturtle/src/pics/turtle.0020.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0021.png b/kturtle/src/pics/turtle.0021.png
new file mode 100644
index 00000000..bc0f6150
--- /dev/null
+++ b/kturtle/src/pics/turtle.0021.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0022.png b/kturtle/src/pics/turtle.0022.png
new file mode 100644
index 00000000..f65b47b3
--- /dev/null
+++ b/kturtle/src/pics/turtle.0022.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0023.png b/kturtle/src/pics/turtle.0023.png
new file mode 100644
index 00000000..8e5efab1
--- /dev/null
+++ b/kturtle/src/pics/turtle.0023.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0024.png b/kturtle/src/pics/turtle.0024.png
new file mode 100644
index 00000000..396a7ec1
--- /dev/null
+++ b/kturtle/src/pics/turtle.0024.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0025.png b/kturtle/src/pics/turtle.0025.png
new file mode 100644
index 00000000..a1ecd51e
--- /dev/null
+++ b/kturtle/src/pics/turtle.0025.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0026.png b/kturtle/src/pics/turtle.0026.png
new file mode 100644
index 00000000..f73f8167
--- /dev/null
+++ b/kturtle/src/pics/turtle.0026.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0027.png b/kturtle/src/pics/turtle.0027.png
new file mode 100644
index 00000000..d55940ce
--- /dev/null
+++ b/kturtle/src/pics/turtle.0027.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0028.png b/kturtle/src/pics/turtle.0028.png
new file mode 100644
index 00000000..3e17afee
--- /dev/null
+++ b/kturtle/src/pics/turtle.0028.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0029.png b/kturtle/src/pics/turtle.0029.png
new file mode 100644
index 00000000..14d26bb4
--- /dev/null
+++ b/kturtle/src/pics/turtle.0029.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0030.png b/kturtle/src/pics/turtle.0030.png
new file mode 100644
index 00000000..1809eb2e
--- /dev/null
+++ b/kturtle/src/pics/turtle.0030.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0031.png b/kturtle/src/pics/turtle.0031.png
new file mode 100644
index 00000000..bc9f2f94
--- /dev/null
+++ b/kturtle/src/pics/turtle.0031.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0032.png b/kturtle/src/pics/turtle.0032.png
new file mode 100644
index 00000000..7b252516
--- /dev/null
+++ b/kturtle/src/pics/turtle.0032.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0033.png b/kturtle/src/pics/turtle.0033.png
new file mode 100644
index 00000000..6b2e84b6
--- /dev/null
+++ b/kturtle/src/pics/turtle.0033.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0034.png b/kturtle/src/pics/turtle.0034.png
new file mode 100644
index 00000000..71ad275f
--- /dev/null
+++ b/kturtle/src/pics/turtle.0034.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.0035.png b/kturtle/src/pics/turtle.0035.png
new file mode 100644
index 00000000..edee5d05
--- /dev/null
+++ b/kturtle/src/pics/turtle.0035.png
Binary files differ
diff --git a/kturtle/src/pics/turtle.png b/kturtle/src/pics/turtle.png
new file mode 100644
index 00000000..5bdf2768
--- /dev/null
+++ b/kturtle/src/pics/turtle.png
Binary files differ
diff --git a/kturtle/src/settings.kcfgc b/kturtle/src/settings.kcfgc
new file mode 100644
index 00000000..abbb05b2
--- /dev/null
+++ b/kturtle/src/settings.kcfgc
@@ -0,0 +1,5 @@
+File=kturtle.kcfg
+IncludeFiles=kstandarddirs.h,kdebug.h
+ClassName=Settings
+Singleton=true
+Mutators=true \ No newline at end of file
diff --git a/kturtle/src/token.cpp b/kturtle/src/token.cpp
new file mode 100644
index 00000000..b30842a4
--- /dev/null
+++ b/kturtle/src/token.cpp
@@ -0,0 +1,19 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "token.h"
diff --git a/kturtle/src/token.h b/kturtle/src/token.h
new file mode 100644
index 00000000..2c0e7622
--- /dev/null
+++ b/kturtle/src/token.h
@@ -0,0 +1,222 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _TOKEN_H_
+#define _TOKEN_H_
+
+#include <qstring.h>
+
+#include "value.h"
+
+
+struct Pos // convenience, it codes a bit nicer with this, i.e.: "int row = tok.start.row"
+{
+ uint row;
+ uint col;
+};
+
+struct Token
+{
+ int type; // filled with enumed tokenTypes
+ QString look; // the way the token looks in the text editor
+ Value value; // if the token is a number it can be stored here
+ Pos start; // row'n'col of the starting/ending point of the token
+ Pos end;
+};
+
+
+enum tokenTypes
+{
+ tokNotSet = 0, // inittial type of all tokens
+ tokError = 1, // when there is an error
+ tokUnknown = 2, // when no token was found, a tokUnknown is often a variable, function or error
+
+ tokIf, // the execution controlling tokens
+ tokElse,
+ tokWhile,
+ tokFor,
+ tokTo,
+ tokStep,
+ tokForEach,
+ tokIn,
+ tokBreak,
+ tokReturn,
+
+ tokBegin, // the scope delimiting tokens
+ tokEnd,
+
+ tokNumber, // the containers
+ tokString,
+
+ tokAssign, // for assignments
+
+ tokAnd, // and, or, not
+ tokOr,
+ tokNot,
+
+ tokEq, // ==, !=, >=, >, <=, <
+ tokNe,
+ tokGe,
+ tokGt,
+ tokLe,
+ tokLt,
+
+ tokBraceOpen, // (, ), +, -, *, /
+ tokBraceClose,
+ tokPlus,
+ tokMinus,
+ tokMul,
+ tokDev,
+
+ tokComma,
+
+ tokEOL, // End Of Line token
+ tokEOF, // End Of File token
+
+ tokLearn, // learn command
+
+ tokClear, // the 'regular' command tokens
+ tokGo,
+ tokGoX,
+ tokGoY,
+ tokForward,
+ tokBackward,
+ tokDirection,
+ tokTurnLeft,
+ tokTurnRight,
+ tokCenter,
+ tokSetPenWidth,
+ tokPenUp,
+ tokPenDown,
+ tokSetFgColor,
+ tokSetBgColor,
+ tokResizeCanvas,
+ tokSpriteShow,
+ tokSpriteHide,
+ tokSpritePress,
+ tokSpriteChange,
+ tokMessage,
+ tokInputWindow,
+ tokPrint,
+ tokFontType,
+ tokFontSize,
+ tokRepeat,
+ tokRandom,
+ tokWait,
+ tokWrapOn,
+ tokWrapOff,
+ tokReset,
+ tokRun,
+
+ tokDo // a dummy command
+};
+
+// const QString tokenTypeNames[] =
+// {
+// /* tokNotSet = 0 */ "",
+// /* tokError = 1 */ "",
+// /* tokUnknown = 2 */ "name",
+//
+// /* tokIf */ "if",
+// /* tokElse */ "else",
+// /* tokWhile */ "while",
+// /* tokFor */ "for",
+// /* tokTo */ "to",
+// /* tokStep */ "step",
+// /* tokForEach */ "each",
+// /* tokIn */ "in",
+// /* tokBreak */ "break",
+// /* tokReturn */ "return",
+//
+// /* tokBegin */ "",
+// /* tokEnd */ "",
+//
+// /* tokNumber */ "number",
+// /* tokString */ "string",
+//
+// /* tokAssign */ "asignment",
+//
+// /* tokAnd */ "and",
+// /* tokOr */ "or",
+// /* tokNot */ "not",
+//
+// /* tokEq */ "questions",
+// /* tokNe */ "questions",
+// /* tokGe */ "questions",
+// /* tokGt */ "questions",
+// /* tokLe */ "questions",
+// /* tokLt */ "questions",
+//
+// /* tokBraceOpen */ "math",
+// /* tokBraceClose */ "math",
+// /* tokPlus */ "math",
+// /* tokMinus */ "math",
+// /* tokMul */ "math",
+// /* tokDev */ "math",
+//
+// /* tokComma */ "",
+//
+// /* tokEOL */ "",
+// /* tokEOF */ "",
+//
+// /* tokLearn */ "learn",
+//
+// /* tokClear */ "clear",
+// /* tokGo */ "go",
+// /* tokGoX */ "gox",
+// /* tokGoY */ "goy",
+// /* tokForward */ "forward",
+// /* tokBackward */ "backward",
+// /* tokDirection */ "direction",
+// /* tokTurnLeft */ "turnleft",
+// /* tokTurnRight */ "turnright",
+// /* tokCenter */ "center",
+// /* tokSetPenWidth */ "setpenwidth",
+// /* tokPenUp */ "penup",
+// /* tokPenDown */ "pendown",
+// /* tokSetFgColor */ "setfgcolor",
+// /* tokSetBgColor */ "setbgcolor",
+// /* tokResizeCanvas */ "resizecanvas",
+// /* tokSpriteShow */ "spriteshow",
+// /* tokSpriteHide */ "spritehide",
+// /* tokSpritePress */ "",
+// /* tokSpriteChange */ "",
+// /* tokMessage */ "message",
+// /* tokInputWindow */ "inputwindow",
+// /* tokPrint */ "print",
+// /* tokFontType */ "",
+// /* tokFontSize */ "fontsize",
+// /* tokRepeat */ "repeat",
+// /* tokRandom */ "random",
+// /* tokWait */ "wait",
+// /* tokWrapOn */ "wrapon",
+// /* tokWrapOff */ "wrapoff",
+// /* tokReset */ "reset",
+// /* tokRun */ "run",
+//
+// /* tokDo */ "",
+// };
+//
+// // QString Token::tokenType2name(int tokenType)
+// // {
+// // if (tokenType >= 0) return tokenTypeNames[tokenType];
+// // else return "";
+// // }
+
+#endif // _TOKEN_H_
diff --git a/kturtle/src/translate.cpp b/kturtle/src/translate.cpp
new file mode 100644
index 00000000..d2c43f16
--- /dev/null
+++ b/kturtle/src/translate.cpp
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qdom.h>
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "settings.h"
+
+#include "translate.h"
+
+
+
+Translate::Translate()
+{
+ loadTranslations();
+}
+
+
+QString Translate::name2fuzzy(const QString &name)
+{
+ if ( !aliasMap[name].isEmpty() ) // translate the alias if any
+ {
+ return QString( i18n("'%1' (%2)").arg(keyMap[name]).arg(reverseAliasMap[name]) );
+ }
+ return QString( "'" + keyMap[name] + "'");
+}
+
+QString Translate::name2key(const QString &name)
+{
+ return keyMap[name];
+}
+
+QString Translate::alias2key(const QString &name)
+{
+ return aliasMap[name];
+}
+
+
+void Translate::loadTranslations() {
+ QDomDocument KeywordsXML;
+
+ kdDebug(0) << "Loading translation dictionary: "<< locate("data", "kturtle/data/logokeywords." + Settings::logoLanguage() + ".xml") <<endl;
+ // Read the specified translation file
+ QFile xmlfile( locate("data", "kturtle/data/logokeywords." + Settings::logoLanguage() + ".xml") );
+
+ if ( !xmlfile.open(IO_ReadOnly) ) return;
+
+ if ( !KeywordsXML.setContent(&xmlfile) )
+ {
+ xmlfile.close();
+ return;
+ }
+ xmlfile.close();
+
+ // get into the first child of the root element (in our case a <command> tag)
+ QDomElement rootElement = KeywordsXML.documentElement();
+ QDomNode n = rootElement.firstChild();
+
+ while ( !n.isNull() )
+ {
+ QString name, key, alias;
+ name = n.toElement().attribute("name"); // get the name attribute of <command>
+ QDomNode m = n.firstChild(); // get into the first child of a <command>
+ while (true)
+ {
+ if( !m.toElement().text().isEmpty() )
+ {
+ if (m.toElement().tagName() == "keyword")
+ {
+ key = m.toElement().text();
+ keyMap.insert(name, key);
+ }
+ if (m.toElement().tagName() == "alias")
+ {
+ alias = m.toElement().text();
+ aliasMap.insert(alias, key);
+ reverseAliasMap.insert(key, alias);
+ }
+ }
+ // break when read the last child of the current <command>
+ if ( m == n.lastChild() ) break;
+ m = m.nextSibling(); // goto the next element in the current <command>
+ }
+ n = n.nextSibling(); // goto the next <command>
+ }
+
+ kdDebug(0) << "Translation dictionary loaded" <<endl;
+}
+
diff --git a/kturtle/src/translate.h b/kturtle/src/translate.h
new file mode 100644
index 00000000..b40cf133
--- /dev/null
+++ b/kturtle/src/translate.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _TRANSLATE_H_
+#define _TRANSLATE_H_
+
+#include <qmap.h>
+#include <qstring.h>
+
+
+class Translate
+{
+ public:
+ Translate();
+ ~Translate() {}
+
+ QString name2fuzzy(const QString&);
+ QString name2key(const QString&);
+ QString alias2key(const QString&);
+
+
+ private:
+ void loadTranslations();
+
+ typedef QMap<QString, QString> StringMap;
+ StringMap keyMap;
+ StringMap aliasMap;
+ StringMap reverseAliasMap;
+};
+
+
+#endif // _TRANSLATE_H_
+
+
diff --git a/kturtle/src/treenode.cpp b/kturtle/src/treenode.cpp
new file mode 100644
index 00000000..d27204ad
--- /dev/null
+++ b/kturtle/src/treenode.cpp
@@ -0,0 +1,255 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+// This file is originally written by Walter Scheppers, but allmost
+// most aspects of it are slightly changed by Cies Breijs.
+
+
+#include <kdebug.h>
+
+#include "treenode.h"
+
+
+TreeNode::TreeNode()
+{
+ init();
+ fType = Unknown;
+}
+
+TreeNode::TreeNode(Token t, NodeType nodeType, QString name)
+{
+ init();
+ fType = nodeType;
+ fTok = t;
+ if ( !name.isNull() ) fTok.look = name;
+ kdDebug(0)<<"TreeNode::TreeNode(); new TreeNode created, with look: '"<<fTok.look<<"', from position ("<<fTok.start.row<<", "<<fTok.start.col<<")."<<endl;
+}
+
+TreeNode::TreeNode(TreeNode* p)
+{
+ init();
+ setParent(p);
+ fType = Unknown;
+ fTok.value = -1;
+}
+
+TreeNode::~TreeNode()
+{
+ destroy(this);
+}
+
+
+
+void TreeNode::init()
+{
+ clear();
+ parent = NULL;
+ // fTok.look (QString) and fTok.value (Value) are properly init'ed when constructed
+ fTok.start.row = 0;
+ fTok.start.col = 0;
+ fTok.end.row = 0;
+ fTok.end.col = 0;
+}
+
+
+
+
+void TreeNode::appendChild(TreeNode* node)
+{
+ node->setParent(this);
+ push_back(node);
+}
+
+void TreeNode::appendSibling(TreeNode* node)
+{
+ node->parent = parent;
+ if (parent != NULL) parent->push_back(node);
+}
+
+
+TreeNode* TreeNode::nextSibling()
+{
+ if (parent)
+ {
+ TreeNode::iterator i = lookup();
+ if ( i != parent->end() )
+ {
+ ++i;
+ // Must check after i has been incremented
+ // to make sure i isn't at the end before
+ // returning the contained pointer value.
+ if ( i != parent->end() ) return *i;
+ }
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::prevSibling()
+{
+ if (parent)
+ {
+ TreeNode::iterator i = lookup();
+ // Must make sure we aren't at beginning as well
+ // or we can crash when decrementing since we shouldn't
+ // decrement before the start of the list.
+ if ( ( i != parent->end() ) && ( i != parent->begin() ) )
+ {
+ --i;
+ return *i;
+ }
+ }
+ return NULL;
+}
+
+
+
+TreeNode* TreeNode::firstChild()
+{
+ if ( !empty() )
+ {
+ TreeNode::const_iterator child = begin();
+ return *child;
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::secondChild()
+{
+ if ( !empty() )
+ {
+ TreeNode::const_iterator child = begin();
+ return (*child)->nextSibling();
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::thirdChild()
+{
+ if ( !empty() )
+ {
+ TreeNode* child = secondChild();
+ if (child != NULL) return child->nextSibling();
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::fourthChild()
+{
+ if ( !empty() )
+ {
+ TreeNode* child = thirdChild();
+ if (child != NULL) return child->nextSibling();
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::fifthChild()
+{
+ if ( !empty() )
+ {
+ TreeNode* child = fourthChild();
+ if(child != NULL) return child->nextSibling();
+ }
+ return NULL;
+}
+
+TreeNode* TreeNode::lastChild()
+{
+ // using a reverse iterator...
+ if ( !empty() )
+ {
+ TreeNode::const_reverse_iterator child = rbegin();
+ return *child;
+ }
+ return NULL;
+}
+
+
+
+
+TreeNode::iterator TreeNode::lookup()
+{
+ if (parent != NULL)
+ {
+ TreeNode::iterator i = parent->begin();
+ while ( (*i != this) && (i != parent->end() ) ) ++i;
+ return i;
+ }
+ return end();
+}
+
+
+
+TreeNode& TreeNode::operator= (const TreeNode& t)
+{
+ if (this != &t)
+ {
+ fType = t.fType;
+ fTok = t.fTok;
+ parent = t.parent;
+
+ clear();
+ for (TreeNode::const_iterator i = t.begin(); i != t.end(); ++i)
+ {
+ push_back(*i);
+ }
+ }
+ return *this;
+}
+
+
+
+
+// recursively walk through tree and show node names with indentation
+void TreeNode::showTree(TreeNode* node, int indent) const
+{
+ indent++;
+ if ( (node != NULL) && (node->size() > 0) )
+ {
+ for ( TreeNode::const_iterator i = node->begin(); i != node->end(); ++i )
+ {
+ (*i)->show(indent);
+ showTree(*i, indent);
+ }
+ }
+}
+
+void TreeNode::show(int indent)
+{
+ QString s = "";
+ for (int i = 0; i < indent; i++)
+ {
+ s += "> ";
+ }
+ kdDebug(0)<<s<<""<<fTok.look<<" @ ("<<getRow()<<", "<<getCol()<<")"<<endl;
+}
+
+
+//recursively walk down tree and delete every node bottom up
+void TreeNode::destroy(TreeNode* node)
+{
+ if ( (node != NULL) && (node->size() > 0) )
+ {
+ for ( TreeNode::iterator i = node->begin(); i != node->end(); ++i )
+ {
+ destroy(*i);
+ (*i)->clear(); //free children
+ //delete ( *i ); //free mem
+ }
+ }
+}
diff --git a/kturtle/src/treenode.h b/kturtle/src/treenode.h
new file mode 100644
index 00000000..44d64d0a
--- /dev/null
+++ b/kturtle/src/treenode.h
@@ -0,0 +1,276 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+// This file is originally written by Walter Scheppers, but allmost
+// every aspect of it is slightly changed by Cies Breijs.
+
+
+#ifndef _TREENODE_H_
+#define _TREENODE_H_
+
+#include <list>
+
+#include <qstring.h>
+
+#include "lexer.h"
+#include "token.h"
+#include "value.h"
+
+
+using namespace std; // needed because treenode inherites from std::list
+
+//BUGS: prevSibling and nextSibling sometimes segfault and are not optimal, in short, don't use em! :)
+
+enum NodeType
+{
+ Unknown = -1,
+ programNode,
+ functionNode,
+ functionCallNode,
+ funcReturnNode,
+ returnNode,
+ breakNode,
+ idListNode,
+ blockNode,
+ forNode,
+ forEachNode,
+ whileNode,
+ ifNode,
+ assignNode,
+ expressionNode,
+ idNode,
+ constantNode,
+
+ addNode,
+ mulNode,
+ divNode,
+ subNode,
+ minusNode,
+
+ nodeGE,
+ nodeGT,
+ nodeLE,
+ nodeLT,
+ nodeNE,
+ nodeEQ,
+
+ andNode,
+ orNode,
+ notNode,
+
+ runNode,
+
+ ClearNode,
+ GoNode,
+ GoXNode,
+ GoYNode,
+ ForwardNode,
+ BackwardNode,
+ DirectionNode,
+ TurnLeftNode,
+ TurnRightNode,
+ CenterNode,
+ SetPenWidthNode,
+ PenUpNode,
+ PenDownNode,
+ SetFgColorNode,
+ SetBgColorNode,
+ ResizeCanvasNode,
+ SpriteShowNode,
+ SpriteHideNode,
+ SpritePressNode,
+ SpriteChangeNode,
+
+ MessageNode,
+ InputWindowNode,
+ printNode,
+ FontTypeNode,
+ FontSizeNode,
+ RepeatNode,
+ RandomNode,
+ WaitNode,
+ WrapOnNode,
+ WrapOffNode,
+ ResetNode,
+
+ LineBreakNode,
+ EndOfFileNode
+
+
+// HOPEFULLY THIS LIST CAN ONCE LOOK LIKE THIS:
+// nodeProgram, // this frirst block has no corresponding token
+// nodeFunction,
+// nodeFunctionCall,
+// nodeReturnFunction,
+// nodeParameterList,
+// nodeBlock,
+// nodeExpression,
+// nodeId, // for assignments
+//
+// nodeNotSet = -1, // inittial type of all tokens
+// nodeUnknown = 0, // when no token was found, a tokUnknown is often a variable, function or error
+//
+// nodeIf,
+// nodeElse,
+// nodeWhile,
+// nodeFor,
+// nodeTo,
+// nodeStep,
+// nodeForEach,
+// nodeIn,
+// nodeBreak,
+// nodeReturn,
+//
+// nodeBegin,
+// nodeEnd,
+//
+// // nodeNumber, --> constantNode
+// // nodeString,
+//
+// nodeAssign,
+//
+// nodeAnd,
+// nodeOr,
+// nodeNot,
+//
+// nodeEq,
+// nodeNe,
+// nodeGe,
+// nodeGt,
+// nodeLe,
+// nodeLt,
+//
+// // nodeBraceOpen,
+// // nodeBraceClose,
+// // nodePlus,
+// nodeAdd, // different from TokenType
+// nodeSub, // different from TokenType
+// nodeMul,
+// nodeDev,
+// nodeMinus, // different meaning from TokenType
+//
+// // nodeComma,
+// // nodeEOL,
+// // nodeEOF,
+// // nodeError,
+//
+// nodeLearn,
+//
+// nodeClear,
+// nodeGo,
+// nodeGoX,
+// nodeGoY,
+// nodeForward,
+// nodeBackward,
+// nodeDirection,
+// nodeTurnLeft,
+// nodeTurnRight,
+// nodeCenter,
+// nodeSetPenWidth,
+// nodePenUp,
+// nodePenDown,
+// nodeSetFgColor,
+// nodeSetBgColor,
+// nodeResizeCanvas,
+// nodeSpriteShow,
+// nodeSpriteHide,
+// nodeSpritePress,
+// nodeSpriteChange,
+// nodeMessage,
+// nodeInputWindow,
+// nodePrint,
+// nodeFontType,
+// nodeFontSize,
+// nodeRepeat,
+// nodeRandom,
+// nodeWait,
+// nodeWrapOn,
+// nodeWrapOff,
+// nodeReset,
+// nodeRun,
+//
+// // nodeDo
+};
+
+
+
+class TreeNode : public list<TreeNode*> /*, public Value <-- maybe oneday */
+{
+ public:
+ TreeNode(); // used for creation of the first node called 'tree', in the contructor of the parser
+ TreeNode( TreeNode* ); // give parent
+ TreeNode( Token, NodeType = Unknown, QString = QString() );
+ virtual ~TreeNode();
+
+ void init();
+
+ void appendChild(TreeNode*);
+ void appendSibling(TreeNode*); // works only if it has parent set!
+
+ TreeNode* firstChild();
+ TreeNode* secondChild();
+ TreeNode* thirdChild();
+ TreeNode* fourthChild();
+ TreeNode* fifthChild();
+
+ TreeNode* lastChild();
+ TreeNode* nextSibling();
+ TreeNode* prevSibling();
+
+ void setParent(TreeNode* p) { parent = p; }
+ TreeNode* getParent() const { return parent; }
+
+ void setToken(Token t) { fTok = t; }
+ Token& getToken() { return fTok; }
+
+ void setType(NodeType t) { fType = t; }
+ NodeType getType() const { return fType; }
+
+ void setLook(const QString& s) { fTok.look = s; }
+ QString getLook() const { return fTok.look; }
+
+ void setValue(const Value& n) { fTok.value = n; }
+ void setValue(double d) { fTok.value = d; }
+ void setValue(const QString& s) { fTok.value = s; }
+ void setValue(bool b) { fTok.value.setBool(b); }
+ Value getValue() const { return fTok.value; }
+
+ uint getRow() const { return fTok.start.row; }
+ uint getCol() const { return fTok.start.col; }
+
+ bool hasChildren() const { return size() != 0; }
+ TreeNode::iterator lookup(); // gives location in parent list as iterator (used by prevSibling and nextSibling)
+
+ TreeNode& operator=(const TreeNode&);
+
+ virtual void show(int indent = 0);
+ void showTree(TreeNode* node, int indent = 0) const;
+
+
+ private:
+ void destroy(TreeNode*);
+
+ NodeType fType;
+ Token fTok;
+
+
+ protected:
+ TreeNode *parent;
+};
+
+#endif // _TREENODE_H_
diff --git a/kturtle/src/value.cpp b/kturtle/src/value.cpp
new file mode 100644
index 00000000..b529452d
--- /dev/null
+++ b/kturtle/src/value.cpp
@@ -0,0 +1,328 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "value.h"
+
+
+Value::Value()
+{
+ init();
+}
+
+Value::Value(const Value& n)
+{
+ *this = n;
+}
+
+
+
+int Value::Type() const
+{
+ return type;
+}
+
+void Value::setType(int newType)
+{
+ if (type == newType) return; // dont change values when type is not changing
+ else if (newType == boolValue)
+ {
+ init();
+ type = newType;
+ m_string = i18n("false");
+ }
+ else if (newType == numberValue)
+ {
+ init();
+ type = newType;
+ }
+ else if (newType == stringValue)
+ {
+ init();
+ type = newType;
+ }
+ else if (newType == emptyValue) init();
+}
+
+
+bool Value::Bool() const
+{
+ if (type == boolValue) return m_bool;
+ else if (type == numberValue) return (m_double - 0.5 > 0);
+ return false;
+}
+
+void Value::setBool(bool b)
+{
+ type = boolValue;
+ m_bool = b;
+ if (m_bool)
+ {
+ m_double = 1;
+ m_string = i18n("true");
+ }
+ else
+ {
+ m_double = 0;
+ m_string = i18n("false");
+ }
+}
+
+
+double Value::Number() const
+{
+ if (type == boolValue)
+ {
+ if (m_bool) return 1;
+ else return 0;
+ }
+ else if (type == numberValue) return m_double;
+ return 0; // stringValue, emptyValue
+}
+
+void Value::setNumber(double d)
+{
+ type = numberValue;
+ m_double = d;
+ m_string.setNum(d);
+}
+
+bool Value::setNumber(const QString &s)
+{
+ type = numberValue;
+ bool ok = true;
+ double num = s.toDouble(&ok);
+ if (ok)
+ {
+ m_double = num;
+ m_string.setNum(num);
+ return true;
+ }
+ return false;
+}
+
+
+QString Value::String() const
+{
+ if (type == boolValue)
+ {
+ if (m_bool) return QString( i18n("true") );
+ else return QString( i18n("false") );
+ }
+ else if (type == numberValue)
+ {
+ QString s;
+ s.setNum(m_double);
+ return s;
+ }
+ return m_string; // stringValue, emptyValue
+}
+
+void Value::setString(double d)
+{
+ type = stringValue;
+ m_double = d;
+ m_string.setNum(d);
+}
+
+void Value::setString(const QString &s)
+{
+ type = stringValue;
+ m_string = s;
+}
+
+
+
+Value& Value::operator=(const Value& n)
+{
+ if (this != &n)
+ {
+ if (type == n.type)
+ {
+ type = n.Type();
+ m_bool = n.Bool();
+ m_double = n.Number();
+ m_string = n.String();
+ }
+ else if (n.Type() == boolValue)
+ {
+ setBool( n.Bool() );
+ }
+ else if (n.Type() == numberValue)
+ {
+ setNumber( n.Number() );
+ }
+ else if (n.Type() == stringValue)
+ {
+ setString( n.String() );
+ }
+ else if (n.Type() == emptyValue)
+ {
+ init();
+ }
+ }
+ return *this;
+}
+
+
+Value& Value::operator=(const QString& s)
+{
+ setString(s);
+ return *this;
+}
+
+Value& Value::operator=(double n)
+{
+ setNumber(n);
+ return *this;
+}
+
+
+
+Value& Value::operator+(const Value& n)
+{
+ if (type == numberValue && n.Type() == numberValue)
+ {
+ m_double += n.Number();
+ }
+ else
+ {
+ type = stringValue;
+ m_string = String() + n.String();
+ }
+ return *this;
+}
+
+
+Value& Value::operator-(const Value& n)
+{
+ if (type == numberValue && n.Type() == numberValue)
+ {
+ m_double -= n.Number();
+ }
+ else
+ {
+ kdDebug(0)<<"Value::operator; cannot subtract strings"<<endl;
+ }
+ return *this;
+}
+
+
+Value& Value::operator*(const Value& n)
+{
+ if (type == numberValue && n.Type() == numberValue)
+ {
+ m_double *= n.Number();
+ }
+ else
+ {
+ kdDebug(0)<<"Value::operator; cannot multiply strings"<<endl;
+ }
+ return *this;
+}
+
+
+Value& Value::operator/(const Value& n)
+{
+ if (type == numberValue && n.Type() == numberValue)
+ {
+ m_double /= n.Number();
+ }
+ else
+ {
+ kdDebug(0)<<"Value::operator; cannot divide strings"<<endl;
+ }
+ return *this;
+}
+
+
+
+bool Value::operator==(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool == n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double == n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string == n.String();
+ if (type == emptyValue && n.Type() == emptyValue) return true;
+ return false;
+}
+
+
+bool Value::operator!=(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool != n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double != n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string != n.String();
+ // if (type == emptyValue && n.Type() == emptyValue) return false;
+ return false;
+}
+
+
+bool Value::operator<(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool < n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double < n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string.length() < n.String().length();
+ // if (type == emptyValue && n.Type() == emptyValue) return false;
+ return false;
+}
+
+
+bool Value::operator<=(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool <= n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double <= n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string.length() <= n.String().length();
+ if (type == emptyValue && n.Type() == emptyValue) return true;
+ return false;
+}
+
+
+bool Value::operator>(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool > n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double > n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string.length() > n.String().length();
+ // if (type == emptyValue && n.Type() == emptyValue) return false;
+ return false;
+}
+
+
+bool Value::operator>=(const Value& n) const
+{
+ if (type == boolValue && n.Type() == boolValue) return m_bool >= n.Bool();
+ if (type == numberValue && n.Type() == numberValue) return m_double >= n.Number();
+ if (type == stringValue && n.Type() == stringValue) return m_string.length() >= n.String().length();
+ if (type == emptyValue && n.Type() == emptyValue) return true;
+ return false;
+}
+
+
+
+// private
+
+void Value::init()
+{
+ type = emptyValue; // init'ed values are empty by default
+ m_bool = false;
+ m_double = 0;
+ m_string = "";
+}
+
+
diff --git a/kturtle/src/value.h b/kturtle/src/value.h
new file mode 100644
index 00000000..8c61966e
--- /dev/null
+++ b/kturtle/src/value.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2003 by Walter Schreppers
+ Copyright (C) 2004 by Cies Breijs
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef _VALUE_H_
+#define _VALUE_H_
+
+#include <qstring.h>
+#include <qtextstream.h>
+
+
+enum valueType
+{
+ emptyValue,
+ boolValue,
+ numberValue,
+ stringValue
+};
+
+class Value
+{
+ public:
+ Value();
+ Value(const Value&);
+ ~Value() {}
+
+
+ void resetValue() { init(); }
+
+ int Type() const;
+ void setType(int);
+
+ void setBool(bool);
+ bool Bool() const;
+
+ double Number() const;
+ void setNumber(double);
+ bool setNumber(const QString&);
+
+ QString String() const;
+ void setString(double);
+ void setString(const QString&);
+
+ Value& operator=(const Value&);
+ Value& operator=(const QString&);
+ Value& operator=(double);
+
+ Value& operator+(const Value&);
+ Value& operator-(const Value&);
+ Value& operator*(const Value&);
+ Value& operator/(const Value&);
+
+ bool operator==(const Value&) const;
+ bool operator!=(const Value&) const;
+ bool operator< (const Value&) const;
+ bool operator<=(const Value&) const;
+ bool operator> (const Value&) const;
+ bool operator>=(const Value&) const;
+
+
+ private:
+ void init();
+
+ int type;
+ bool m_bool;
+ double m_double;
+ QString m_string;
+};
+
+#endif // _VALUE_H_