diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | c90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch) | |
tree | 6d8391395bce9eaea4ad78958617edb20c6a7573 /lskat | |
download | tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lskat')
85 files changed, 9572 insertions, 0 deletions
diff --git a/lskat/AUTHORS b/lskat/AUTHORS new file mode 100644 index 00000000..944b9a7d --- /dev/null +++ b/lskat/AUTHORS @@ -0,0 +1 @@ +Martin Heni <[email protected]> diff --git a/lskat/COPYING b/lskat/COPYING new file mode 100644 index 00000000..54754ab4 --- /dev/null +++ b/lskat/COPYING @@ -0,0 +1,341 @@ + 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) 19yy <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) 19yy 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/lskat/Makefile.am b/lskat/Makefile.am new file mode 100644 index 00000000..efb7b82c --- /dev/null +++ b/lskat/Makefile.am @@ -0,0 +1,11 @@ + +SUBDIRS = lskat grafix lskatproc + +####### kdevelop will overwrite this part!!! (end)############ +# not a GNU package. You can remove this line, if +# have all needed files, that a GNU package needs +AUTOMAKE_OPTIONS = foreign + +KDE_ICON = lskat + +xdg_apps_DATA = lskat.desktop diff --git a/lskat/README b/lskat/README new file mode 100644 index 00000000..08a01e00 --- /dev/null +++ b/lskat/README @@ -0,0 +1,33 @@ +GENERAL NOTE: + + This is a small KDE 2.0 game, I wrote to practise + programming in KDE. + It should work quite stable. But if you find any bugs + please contact me. + It would be also nice to give me some general feedback + about the program, so that it can be approved or it + can be considered in other programs. + (Email: [email protected]) + +INSTALLATION: + +# unpack the archive +tar xzf lskat-0.9.tar.gz + +# build the package +cd lskat-0.9 +./configure +# or if KDE is in /opt/kde2 +./configure --prefix=/opt/kde2 +make + +# become superuser for installing +su -c 'make install' + +DECKS: + + You can use up to 6 own carddecks. Simply put into + the grafichs directory resp the lskatpic.taz archive + BMP graphics of the size 72x96, named deck1.bmp .. + deck6.bmp + diff --git a/lskat/TODO b/lskat/TODO new file mode 100644 index 00000000..7c90f740 --- /dev/null +++ b/lskat/TODO @@ -0,0 +1,3 @@ +- Convert BMP graphics to PNG (done) +- Checke QT QString-char * casting + (Its a bit of a QCString/QString mess right now) diff --git a/lskat/grafix/Makefile.am b/lskat/grafix/Makefile.am new file mode 100644 index 00000000..c99fec81 --- /dev/null +++ b/lskat/grafix/Makefile.am @@ -0,0 +1,8 @@ +grafix_DATA = background.png deck1.png deck2.png deck3.png deck4.png \ +t1.png t2.png t3.png \ +t4.png t5.png tback.png type1.png type2.png type3.png + +grafixdir = $(kde_datadir)/lskat/grafix + +EXTRA_DIST = $(grafix_DATA) + diff --git a/lskat/grafix/background.png b/lskat/grafix/background.png Binary files differnew file mode 100644 index 00000000..7c7546a2 --- /dev/null +++ b/lskat/grafix/background.png diff --git a/lskat/grafix/deck1.png b/lskat/grafix/deck1.png Binary files differnew file mode 100644 index 00000000..70eb9049 --- /dev/null +++ b/lskat/grafix/deck1.png diff --git a/lskat/grafix/deck2.png b/lskat/grafix/deck2.png Binary files differnew file mode 100644 index 00000000..a17f390b --- /dev/null +++ b/lskat/grafix/deck2.png diff --git a/lskat/grafix/deck3.png b/lskat/grafix/deck3.png Binary files differnew file mode 100644 index 00000000..c04eccd4 --- /dev/null +++ b/lskat/grafix/deck3.png diff --git a/lskat/grafix/deck4.png b/lskat/grafix/deck4.png Binary files differnew file mode 100644 index 00000000..44e9ef91 --- /dev/null +++ b/lskat/grafix/deck4.png diff --git a/lskat/grafix/t1.png b/lskat/grafix/t1.png Binary files differnew file mode 100644 index 00000000..1722b1a7 --- /dev/null +++ b/lskat/grafix/t1.png diff --git a/lskat/grafix/t2.png b/lskat/grafix/t2.png Binary files differnew file mode 100644 index 00000000..a5b11f7a --- /dev/null +++ b/lskat/grafix/t2.png diff --git a/lskat/grafix/t3.png b/lskat/grafix/t3.png Binary files differnew file mode 100644 index 00000000..6a1b10fc --- /dev/null +++ b/lskat/grafix/t3.png diff --git a/lskat/grafix/t4.png b/lskat/grafix/t4.png Binary files differnew file mode 100644 index 00000000..21079f7e --- /dev/null +++ b/lskat/grafix/t4.png diff --git a/lskat/grafix/t5.png b/lskat/grafix/t5.png Binary files differnew file mode 100644 index 00000000..2cc08d8c --- /dev/null +++ b/lskat/grafix/t5.png diff --git a/lskat/grafix/tback.png b/lskat/grafix/tback.png Binary files differnew file mode 100644 index 00000000..84132ad6 --- /dev/null +++ b/lskat/grafix/tback.png diff --git a/lskat/grafix/type1.png b/lskat/grafix/type1.png Binary files differnew file mode 100644 index 00000000..d6714c7d --- /dev/null +++ b/lskat/grafix/type1.png diff --git a/lskat/grafix/type2.png b/lskat/grafix/type2.png Binary files differnew file mode 100644 index 00000000..1f646df1 --- /dev/null +++ b/lskat/grafix/type2.png diff --git a/lskat/grafix/type3.png b/lskat/grafix/type3.png Binary files differnew file mode 100644 index 00000000..66b109d4 --- /dev/null +++ b/lskat/grafix/type3.png diff --git a/lskat/hi128-app-lskat.png b/lskat/hi128-app-lskat.png Binary files differnew file mode 100644 index 00000000..48c94d8b --- /dev/null +++ b/lskat/hi128-app-lskat.png diff --git a/lskat/hi16-app-lskat.png b/lskat/hi16-app-lskat.png Binary files differnew file mode 100644 index 00000000..de69f4cf --- /dev/null +++ b/lskat/hi16-app-lskat.png diff --git a/lskat/hi22-app-lskat.png b/lskat/hi22-app-lskat.png Binary files differnew file mode 100644 index 00000000..f811b52f --- /dev/null +++ b/lskat/hi22-app-lskat.png diff --git a/lskat/hi32-app-lskat.png b/lskat/hi32-app-lskat.png Binary files differnew file mode 100644 index 00000000..7a605d44 --- /dev/null +++ b/lskat/hi32-app-lskat.png diff --git a/lskat/hi48-app-lskat.png b/lskat/hi48-app-lskat.png Binary files differnew file mode 100644 index 00000000..259608d1 --- /dev/null +++ b/lskat/hi48-app-lskat.png diff --git a/lskat/hi64-app-lskat.png b/lskat/hi64-app-lskat.png Binary files differnew file mode 100644 index 00000000..00abe3bf --- /dev/null +++ b/lskat/hi64-app-lskat.png diff --git a/lskat/lskat.desktop b/lskat/lskat.desktop new file mode 100644 index 00000000..40044788 --- /dev/null +++ b/lskat/lskat.desktop @@ -0,0 +1,108 @@ +[Desktop Entry] +GenericName=Card Game +GenericName[af]=Kaart Speletjie +GenericName[ar]=لعبة الورق +GenericName[be]=Картачная гульня +GenericName[bg]=Игра на карти +GenericName[bn]=তাস খেলা +GenericName[br]=C'hoari kartennoù +GenericName[bs]=Igra s kartama +GenericName[ca]=Joc de cartes +GenericName[cs]=Karty +GenericName[cy]=Gêm Cerdiau +GenericName[da]=Kortspil +GenericName[de]=Kartenspiel +GenericName[el]=Παιχνίδι καρτών +GenericName[eo]=Kartludo +GenericName[es]=Juego de cartas +GenericName[et]=Kaardimäng +GenericName[eu]=Karta-jokoa +GenericName[fa]=بازی ورق +GenericName[fi]=Korttipeli +GenericName[fo]=Kortspøl +GenericName[fr]=Jeu de cartes +GenericName[ga]=Cluiche Cártaí +GenericName[gl]=Xogo de cartas +GenericName[he]=משחק קלפים +GenericName[hi]=ताश के खेल +GenericName[hr]=Kartaška igra +GenericName[hu]=Kártyajáték +GenericName[is]=Spil +GenericName[it]=Gioco di carte +GenericName[ja]=カードゲーム +GenericName[km]=ល្បែងបៀ +GenericName[ko]=카드 놀이 +GenericName[lt]=Kortų žaidimas +GenericName[lv]=Kāršu Spēle +GenericName[mk]=Игра со карти +GenericName[mt]=Logħba tal-karti +GenericName[nb]=Kortspill +GenericName[nds]=Koortenspeel +GenericName[ne]=कार्ड खेल +GenericName[nl]=Kaartspel +GenericName[nn]=Kortspel +GenericName[nso]=Papadi ya Dikarata +GenericName[pa]=ਤਾਸ਼ ਖੇਡ +GenericName[pl]=Gra karciana +GenericName[pt]=Jogo de Cartas +GenericName[pt_BR]=Jogo de Cartas +GenericName[ro]=Un joc de cărţi +GenericName[ru]=Лейтенант Скат +GenericName[rw]=Umukino Ikarika +GenericName[se]=Goartaspeallu +GenericName[sk]=Kartová hra +GenericName[sl]=Igra s kartami +GenericName[sr]=Игра са картама +GenericName[sr@Latn]=Igra sa kartama +GenericName[sv]=Kortspel +GenericName[ta]=அட்டை விளையாட்டு +GenericName[tg]=Бозии Кортҳо +GenericName[th]=เกมไพ่ +GenericName[tr]=İskambil Oyunu +GenericName[uk]=Карти +GenericName[uz]=Qarta oʻyini +GenericName[uz@cyrillic]=Қарта ўйини +GenericName[ven]=Garatha ya Mutambo +GenericName[vi]=Game thẻ +GenericName[wa]=Cwårdjeu +GenericName[xh]=Ikhadi lomdlalo +GenericName[zh_CN]=牌类游戏 +GenericName[zh_TW]=紙牌遊戲 +GenericName[zu]=Umdlalo wamakhadi +Exec=lskat +Icon=lskat +Name=Lieutenant Skat +Name[bg]=Лейтенант Скат +Name[ca]=Tinent Skat +Name[cs]=Poručík Skat +Name[da]=Lieutnant Skat +Name[de]=Offiziersskat +Name[el]=Υπολοχαγός Skat +Name[eo]=Leŭtenanta skato +Name[es]=Teniente Skat +Name[et]=Leitnant Skat +Name[eu]=Skat tenientea +Name[fi]=Luutnantti Skat +Name[hr]=Vojnički Skat +Name[hu]=Skat hadnagy +Name[is]=Hermaðurinn Skat +Name[it]=Tenente Skat +Name[km]=Lieutnant Skat +Name[lt]=Leitenantas Skatas +Name[nds]=Buernskat +Name[ne]=लिउटिनान्ट स्काट +Name[nl]=Luitenant Skat +Name[nn]=Løytnant Skat +Name[pl]=Skat porucznika +Name[pt]=Tenente Skat +Name[pt_BR]=Tenente Skat +Name[sl]=Poročnik Skat +Name[sv]=Officersskat +Name[uk]=Лейтенант Скет +Name[wa]=Lieutnant Skat +Terminal=false +Type=Application +DocPath=lskat/index.html +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Game;CardGame; diff --git a/lskat/lskat.kdevprj b/lskat/lskat.kdevprj new file mode 100644 index 00000000..bbba872e --- /dev/null +++ b/lskat/lskat.kdevprj @@ -0,0 +1,286 @@ +[AUTHORS] +dist=true +install=false +install_location= +type=DATA +[COPYING] +dist=true +install=false +install_location= +type=DATA +[ChangeLog] +dist=true +install=false +install_location= +type=DATA +[Config for BinMakefileAm] +bin_program=lskat +cxxflags=-O0 -g3 -Wall +ldadd=-lkfile -lkdeui -lkdecore -lqt -lXext -lX11 +ldflags= +[General] +author=Martin Heni +kdevprj_version=1.0beta2 +lfv_open_groups= +makefiles=Makefile.am,lskat/Makefile.am,lskat/docs/Makefile.am,lskat/docs/en/Makefile.am,po/Makefile.am,lskatproc/Makefile +project_name=LSkat +project_type=normal_kde +sub_dir=lskat/ +version=0.9 +version_control=CVS +[INSTALL] +dist=true +install=false +install_location= +type=DATA +[LFV Groups] +Dialogs=*.kdevdlg +GNU=AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,NEWS +Headers=*.h,*.hxx,*.hpp,*.H +Others=* +Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l +Translations=*.po +groups=Headers,Sources,Dialogs,Translations,GNU,Others +[Makefile.am] +files=lskat.kdevprj,AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,lskat.lsm +sub_dirs=lskat,po +type=normal +[README] +dist=true +install=false +install_location= +type=DATA +[TODO] +dist=true +install=false +install_location= +type=DATA +[lskat.kdevprj] +dist=true +install=false +install_location= +type=DATA +[lskat.lsm] +dist=true +install=false +install_location= +type=DATA +[lskat/KChildConnect.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KChildConnect.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KConnectEntry.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KConnectEntry.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KConnectTypes.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KEInput.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KEInput.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KEMessage.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KEMessage.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KInputChildProcess.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KInputChildProcess.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KInteractiveConnect.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KInteractiveConnect.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KMessageEntry.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KMessageEntry.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KProcessConnect.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KProcessConnect.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KRSocket.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KRSocket.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/KRemoteConnect.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/KRemoteConnect.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/Makefile.am] +files=lskat/main.cpp,lskat/lskat.cpp,lskat/lskat.h,lskat/lskatdoc.cpp,lskat/lskatdoc.h,lskat/lskatview.cpp,lskat/lskatview.h,lskat/resource.h,lskat/lskat.desktop,lskat/lskat.xpm,lskat/mini-lskat.xpm,lskat/KChildConnect.cpp,lskat/KChildConnect.h,lskat/KConnectEntry.cpp,lskat/KConnectEntry.h,lskat/KConnectTypes.h,lskat/KEInput.cpp,lskat/KEInput.h,lskat/KEMessage.cpp,lskat/KEMessage.h,lskat/KInputChildProcess.cpp,lskat/KInputChildProcess.h,lskat/KInteractiveConnect.cpp,lskat/KInteractiveConnect.h,lskat/KMessageEntry.cpp,lskat/KMessageEntry.h,lskat/KProcessConnect.cpp,lskat/KProcessConnect.h,lskat/KRSocket.cpp,lskat/KRSocket.h,lskat/KRemoteConnect.cpp,lskat/KRemoteConnect.h,lskat/namedlg.cpp,lskat/namedlg.h,lskat/networkdlg.cpp,lskat/networkdlg.h,lskat/aboutdlg.cpp,lskat/aboutdlg.h,lskat/aboutdlgdata.cpp,lskat/msgdlg.cpp,lskat/msgdlg.h +sub_dirs= +type=prog_main +[lskat/aboutdlg.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/aboutdlg.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/aboutdlgdata.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/docs/Makefile.am] +sub_dirs= +type=normal +[lskat/docs/en/Makefile.am] +sub_dirs= +type=normal +[lskat/lskat.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/lskat.desktop] +dist=true +install=true +install_location=$$(kde_appsdir)/Applications/lskat.desktop +type=DATA +[lskat/lskat.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/lskat.xpm] +dist=true +install=true +install_location=$$(kde_icondir)/lskat.xpm +type=DATA +[lskat/lskatdoc.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/lskatdoc.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/lskatview.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/lskatview.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/main.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/mini-lskat.xpm] +dist=true +install=true +install_location=$$(kde_minidir)/lskat.xpm +type=DATA +[lskat/msgdlg.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/msgdlg.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/namedlg.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/namedlg.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/networkdlg.cpp] +dist=true +install=false +install_location= +type=SOURCE +[lskat/networkdlg.h] +dist=true +install=false +install_location= +type=HEADER +[lskat/resource.h] +dist=true +install=false +install_location= +type=HEADER +[po/Makefile.am] +sub_dirs= +type=po diff --git a/lskat/lskat.lsm b/lskat/lskat.lsm new file mode 100644 index 00000000..388ff010 --- /dev/null +++ b/lskat/lskat.lsm @@ -0,0 +1,14 @@ +Begin3 +Title: LSkat +Version: 0.9 +Entered-date: +Description: A small cardgame for the KDE 2 desktop +Keywords: skat, card, cardgame,game,kde +Author: Martin Heni <[email protected]> +Maintained-by: Martin Heni <[email protected]> +Primary-site: +Home-page: http://www.heni-online.de/linux +Original-site: +Platforms: Linux and other Unices +Copying-policy: GNU Public License +End diff --git a/lskat/lskat/KChildConnect.cpp b/lskat/lskat/KChildConnect.cpp new file mode 100644 index 00000000..61931693 --- /dev/null +++ b/lskat/lskat/KChildConnect.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + KChildConnect.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include "KChildConnect.h" + +#include "KChildConnect.moc" + +KChildConnect::KChildConnect() + : QObject(0,0) +{ + input_pending=false; + inputbuffer=""; +} + +KChildConnect::~KChildConnect() +{ +} + +KR_STATUS KChildConnect::QueryStatus() +{ + return KR_OK; +} + +// Communication with process +bool KChildConnect::SendMsg(KEMessage *msg) +{ + QString sendstring=msg->ToString(); + // Debug only + if (msg->HasKey(QCString("KLogSendMsg"))) + { + char *p; + int size; + FILE *fp; + msg->GetData(QCString("KLogSendMsg"),p,size); + if (p && (fp=fopen(p,"a")) ) + { + fprintf(fp,"------------------------------------\n"); + fprintf(fp, "%s", sendstring.utf8().data()); + fclose(fp); + } + } + // end debug only + return Send(sendstring); +} + +// Send string to parent +bool KChildConnect::Send(QString str) +{ + if (!str || str.length()<1) return true; // no need to send crap + printf("%s",str.latin1()); + fflush(stdout); + return true; +} + +void KChildConnect::Receive(QString input) +{ + // Cut out CR + int len,pos; + QString tmp; + + + // Call us recursive until there are no CR left + len=KEMESSAGE_CR.length(); + pos=input.find(KEMESSAGE_CR); + if (pos>0) + { + tmp=input.left(pos); + if (tmp.length()>0) Receive(tmp); // CR free + input=input.right(input.length()-pos-len); + if (input.length()>0) Receive(input); + return ; + } + +// printf(" ---> KChildConnect::Receive: '%s'\n",(const char *)input); + if (input==(KEMESSAGE_HEAD) && !input_pending) + { + input_pending=true; + inputcache.clear(); + return ; + } + if (!input_pending) return ; // ignore + if (input!=(KEMESSAGE_TAIL)) + { + inputcache.append(input.latin1()); + return; + } + input_pending=0; + + KEMessage *msg=new KEMessage; + char *it; + for (it=inputcache.first();it!=0;it=inputcache.next()) + { + msg->AddString(QCString(it)); + } + +// printf("+- CHILDprocess:: GOT MESSAGE::Emmiting slotReceiveMsg\n"); + emit signalReceiveMsg(msg,ID); + + delete msg; +} + +void KChildConnect::SetID(int id) +{ + ID=id; +} +int KChildConnect::QueryID() +{ + return ID; +} + diff --git a/lskat/lskat/KChildConnect.h b/lskat/lskat/KChildConnect.h new file mode 100644 index 00000000..d90c62ca --- /dev/null +++ b/lskat/lskat/KChildConnect.h @@ -0,0 +1,53 @@ +/*************************************************************************** + KChildConnect.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KCHILDCONNECT_H_ +#define _KCHILDCONNECT_H_ + +#include <qobject.h> +#include <qstrlist.h> +#include "KEMessage.h" + + +class KChildConnect: public QObject +{ + Q_OBJECT + + protected: + QStrList inputcache; + bool input_pending; + QString inputbuffer; + int ID; + + public: + KChildConnect(); + ~KChildConnect(); + void Receive(QString input); + int QueryID(); + void SetID(int id); + + virtual bool SendMsg(KEMessage *msg); + virtual bool Send(QString str); + virtual KR_STATUS QueryStatus(); + + public slots: + + + signals: + void signalReceiveMsg(KEMessage *msg,int id); +}; + +#endif diff --git a/lskat/lskat/KConnectEntry.cpp b/lskat/lskat/KConnectEntry.cpp new file mode 100644 index 00000000..870b8cd2 --- /dev/null +++ b/lskat/lskat/KConnectEntry.cpp @@ -0,0 +1,165 @@ +/*************************************************************************** + KConnectEntry.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "KConnectEntry.h" + +KG_INPUTTYPE KConnectEntry::QueryType() +{ + return type; +} + +KRemoteConnect *KConnectEntry::QueryRemoteConnect() +{ + return connect.r; +} + +KProcessConnect *KConnectEntry::QueryProcessConnect() +{ + return connect.p; +} + +KInteractiveConnect *KConnectEntry::QueryInteractiveConnect() +{ + return connect.i; +} + +KR_STATUS KConnectEntry::QueryStatus() +{ + switch(type) + { + case KG_INPUTTYPE_INTERACTIVE: + return connect.i->QueryStatus(); + break; + case KG_INPUTTYPE_REMOTE: + return connect.r->QueryStatus(); + break; + case KG_INPUTTYPE_PROCESS: + return connect.p->QueryStatus(); + break; + default: + return KR_INVALID; + break; + } +} +bool KConnectEntry::SendMsg(KEMessage *msg) +{ + switch(type) + { + case KG_INPUTTYPE_INTERACTIVE: + return connect.i->SendMsg(msg); + break; + case KG_INPUTTYPE_REMOTE: + return connect.r->SendMsg(msg); + break; + case KG_INPUTTYPE_PROCESS: + return connect.p->SendMsg(msg); + break; + default: + return false; + break; + } +} + +bool KConnectEntry::Exit() +{ + bool result; + result=FALSE; + switch(type) + { + case KG_INPUTTYPE_INTERACTIVE: + result=connect.i->Exit(); + delete connect.i; + break; + case KG_INPUTTYPE_REMOTE: + result=connect.r->Exit(); + delete connect.r; + break; + case KG_INPUTTYPE_PROCESS: + result=connect.p->Exit(); + delete connect.p; + break; + default: result=FALSE; + break; + } + return result; +} + +bool KConnectEntry::Init(KG_INPUTTYPE stype,int id,KEMessage *msg) +{ + bool result; + type=stype; + ID=id; + switch(stype) + { + case KG_INPUTTYPE_INTERACTIVE: + connect.i=new KInteractiveConnect; + result=connect.i->Init(id,msg); + break; + case KG_INPUTTYPE_REMOTE: + connect.r=new KRemoteConnect; + result=connect.r->Init(id,msg); + break; + case KG_INPUTTYPE_PROCESS: + connect.p=new KProcessConnect; + result=connect.p->Init(id,msg); + break; + default: result=FALSE; + break; + } + return result; +} +KConnectEntry::KConnectEntry() +{ + type=(KG_INPUTTYPE)0; + connect.r=0; +} + +KConnectEntry::~KConnectEntry() +{ +// printf("DESTRUCTING KCONNECTENTRY\n"); + Exit(); +} + +KConnectEntry::KConnectEntry(KConnectEntry &msg) +{ + *this=msg; +} +KConnectEntry &KConnectEntry::operator=(KConnectEntry &entry) +{ + // printf("&KConnectEntry::operator=:: I am not sure whether this is really a good idea...\n"); + Init(entry.QueryType(),entry.ID); + + return *this; +} diff --git a/lskat/lskat/KConnectEntry.h b/lskat/lskat/KConnectEntry.h new file mode 100644 index 00000000..73619eac --- /dev/null +++ b/lskat/lskat/KConnectEntry.h @@ -0,0 +1,56 @@ +/*************************************************************************** + KConnectEntry.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KCONNECTENTRY_H_ +#define _KCONNECTENTRY_H_ + +#include <string.h> +#include "KRemoteConnect.h" +#include "KProcessConnect.h" +#include "KInteractiveConnect.h" +#include "KConnectTypes.h" +#include "KEMessage.h" + +union UConnect +{ + KRemoteConnect *r; + KProcessConnect *p; + KInteractiveConnect *i; +}; + +class KConnectEntry +{ + private: + KG_INPUTTYPE type; // remote,computer,interactive + UConnect connect; + protected: + int ID; + + public: + KG_INPUTTYPE QueryType(); + KRemoteConnect *QueryRemoteConnect(); + KProcessConnect *QueryProcessConnect(); + KInteractiveConnect *QueryInteractiveConnect(); + KConnectEntry(); + ~KConnectEntry(); + KConnectEntry(KConnectEntry &entry); + KConnectEntry &operator=(KConnectEntry &entry); + bool Exit(); + bool Init(KG_INPUTTYPE stype,int id=0,KEMessage *msg=0); + KR_STATUS QueryStatus(); + bool SendMsg(KEMessage *msg); +}; +#endif diff --git a/lskat/lskat/KConnectTypes.h b/lskat/lskat/KConnectTypes.h new file mode 100644 index 00000000..6a9822b3 --- /dev/null +++ b/lskat/lskat/KConnectTypes.h @@ -0,0 +1,38 @@ +/*************************************************************************** + KConnectTypes.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KCONNECTTYPES_H_ +#define _KCONNECTTYPES_H_ + +enum KGM_TYPE {KGM_TYPE_INVALID=0,KGM_TYPE_SHORT=1,KGM_TYPE_LONG=2, + KGM_TYPE_FLOAT=3,KGM_TYPE_DATA=4}; + +enum KG_INPUTTYPE { + KG_INPUTTYPE_INVALID=0, + KG_INPUTTYPE_INTERACTIVE=1, + KG_INPUTTYPE_PROCESS=2, + KG_INPUTTYPE_REMOTE=3}; + +enum KR_STATUS { + KR_NO_SOCKET=-2, + KR_WAIT_FOR_CLIENT=-1, + KR_INVALID=0, + // >0 OK + KR_OK=1, + KR_CLIENT=2, + KR_SERVER=3 + }; +#endif diff --git a/lskat/lskat/KEInput.cpp b/lskat/lskat/KEInput.cpp new file mode 100644 index 00000000..b5765d00 --- /dev/null +++ b/lskat/lskat/KEInput.cpp @@ -0,0 +1,296 @@ +/*************************************************************************** + KEInput.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include "KEInput.h" +#include "KConnectEntry.h" + +#define K_INPUT_DELAY 25 // delay following non interactive moves + +#include "KEInput.moc" + +KEInput::KEInput(QObject * parent) + : QObject(parent,0) +{ + number_of_inputs=0; + locked=FALSE; + previous_input=-1; + next_input=-1; + cTimer=0; +// mMsg=(KEMessage *)0; +} + +KEInput::~KEInput() +{ + int i; + for (i=number_of_inputs-1;i>=0;i--) + { + RemoveInput(i); + } + delete cTimer; +} + +int KEInput::QueryNumberOfInputs() +{ + return number_of_inputs; +} + +int KEInput::QueryNext() +{ + return next_input; +} + +int KEInput::QueryPrevious() +{ + return previous_input; +} + +bool KEInput::IsInput(int no) +{ + if (no>=number_of_inputs || no<0) return FALSE; + if (QueryType(no)==0) return FALSE; + return TRUE; +} + +// Default is the type of the current player +bool KEInput::IsInteractive(int no) +{ + return QueryType(no)==KG_INPUTTYPE_INTERACTIVE; +} +bool KEInput::IsProcess(int no) +{ + return QueryType(no)==KG_INPUTTYPE_PROCESS; +} +bool KEInput::IsRemote(int no) +{ + return QueryType(no)==KG_INPUTTYPE_REMOTE; +} +KG_INPUTTYPE KEInput::QueryType(int no) +{ + if (no==-1) no=QueryNext(); + if (no>=number_of_inputs || no<0) return KG_INPUTTYPE_INVALID; + return playerArray[no].QueryType(); +} + +KR_STATUS KEInput::QueryStatus(int no) +{ + if (no==-1) no=QueryNext(); + if (no>=number_of_inputs || no<0) + { + return KR_INVALID; + } + return playerArray[no].QueryStatus(); +} +bool KEInput::SendMsg(KEMessage *msg,int no) +{ + if (no==-1) no=QueryNext(); + if (no>=number_of_inputs || no<0) + { + return false; + } + return playerArray[no].SendMsg(msg); +} + + +bool KEInput::SetInputDevice(int no, KG_INPUTTYPE type,KEMessage *msg) +{ + bool result; + // Grow if necessary + if (no<0) return false; + else if (no<number_of_inputs) + { + RemoveInput(no); + } + if (no>=number_of_inputs) + { + playerArray.resize(no+1); + number_of_inputs=no+1; + } + result=playerArray[no].Init(type,no,msg); + // if (result) + // Connect even if remote connection is not yet build + if (result || playerArray[no].QueryStatus()==KR_WAIT_FOR_CLIENT) + { + switch(QueryType(no)) + { + case KG_INPUTTYPE_INTERACTIVE: + connect(playerArray[no].QueryInteractiveConnect(),SIGNAL(signalReceiveMsg(KEMessage *,int )), + this,SLOT(slotSetInput(KEMessage *,int ))); + connect(playerArray[no].QueryInteractiveConnect(),SIGNAL(signalPrepareMove(KEMessage *,KG_INPUTTYPE)), + this,SLOT(slotPrepareMove(KEMessage *,KG_INPUTTYPE))); + break; + case KG_INPUTTYPE_REMOTE: + connect(playerArray[no].QueryRemoteConnect(),SIGNAL(signalReceiveMsg(KEMessage *,int )), + this,SLOT(slotSetInput(KEMessage *,int ))); + connect(playerArray[no].QueryRemoteConnect(),SIGNAL(signalPrepareMove(KEMessage *,KG_INPUTTYPE)), + this,SLOT(slotPrepareMove(KEMessage *,KG_INPUTTYPE))); + break; + case KG_INPUTTYPE_PROCESS: + connect(playerArray[no].QueryProcessConnect(),SIGNAL(signalReceiveMsg(KEMessage *,int )), + this,SLOT(slotSetInput(KEMessage *,int ))); + connect(playerArray[no].QueryProcessConnect(),SIGNAL(signalPrepareMove(KEMessage *,KG_INPUTTYPE)), + this,SLOT(slotPrepareMove(KEMessage *,KG_INPUTTYPE))); + break; + default: + break; + } + } + return result; +} + +bool KEInput::RemoveInput(int no) +{ + bool result; + if (no>=number_of_inputs || no<0) return FALSE; + result=playerArray[no].Exit(); + // shrink if last entry is removed + if (no==number_of_inputs-1) + { + playerArray.resize(no); + number_of_inputs=no; + } + return result; +} + + +// Sets a new player and sends it a message +bool KEInput::Next(int number, bool force) +{ + if (locked && !force) return FALSE; + if (!IsInput(number)) return FALSE; + locked=TRUE; + + // printf("KEInput::Next %d OK ... lock set!!\n",number); + + previous_input=next_input; + next_input=number; + + switch(QueryType(number)) + { + case KG_INPUTTYPE_INTERACTIVE: + playerArray[number].QueryInteractiveConnect()->Next(); + break; + case KG_INPUTTYPE_REMOTE: + if (QueryType(previous_input)!=0 && + QueryType(previous_input)!=KG_INPUTTYPE_INTERACTIVE) + { + // delay non interactive move to allow interactive inout + if (cTimer) delete cTimer; // Ouch... + cTimer=new QTimer(this); + connect(cTimer,SIGNAL(timeout()),this,SLOT(slotTimerNextRemote())); + cTimer->start(K_INPUT_DELAY,TRUE); + } + else + { + playerArray[number].QueryRemoteConnect()->Next(); + } + break; + case KG_INPUTTYPE_PROCESS: + if (QueryType(previous_input)!=0 && + QueryType(previous_input)!=KG_INPUTTYPE_INTERACTIVE) + { + // delay non interactive move to allow interactive inout + cTimer=new QTimer(this); + connect(cTimer,SIGNAL(timeout()),this,SLOT(slotTimerNextProcess())); + cTimer->start(K_INPUT_DELAY,TRUE); + } + else + playerArray[number].QueryProcessConnect()->Next(); + break; + default: return FALSE; + } + return TRUE; +} + +void KEInput::slotTimerNextRemote() +{ + delete cTimer; + cTimer=0; + if (next_input>=0 && next_input<number_of_inputs) + playerArray[next_input].QueryRemoteConnect()->Next(); +} + +void KEInput::slotTimerNextProcess() +{ + delete cTimer; + cTimer=0; + if (next_input>=0 && next_input<number_of_inputs) + playerArray[next_input].QueryProcessConnect()->Next(); +} + +// called to prepare a move which is send to a remote/computer +// should fill in message data +void KEInput::slotPrepareMove(KEMessage *msg,KG_INPUTTYPE type) +{ + // just forward it + switch(type) + { + case KG_INPUTTYPE_INTERACTIVE: + emit signalPrepareInteractiveMove(msg); + break; + case KG_INPUTTYPE_PROCESS: + emit signalPrepareProcessMove(msg); + break; + case KG_INPUTTYPE_REMOTE: + emit signalPrepareRemoteMove(msg); + break; + default: // Do nothing + break; + } +} +// called by ReceiveMsg +void KEInput::slotSetInput(KEMessage *msg,int id) +{ + if (!msg) return ; + SetInput(msg,id); +} + +bool KEInput::SetInput(KEMessage *msg,int number) +{ + /* + if (!locked) + { + printf("KEINput:SetInput not locked(should be) returning FALSE\n"); + return FALSE; + } + */ + if (number<0 || number>=number_of_inputs) number=next_input; // automatically select player +// KEMessage *mMsg= new KEMessage; + // evt if (mMsg) delete mMsg; +// *mMsg=*msg; + // locked=FALSE; + // printf("**** KEInput: emitting signalReceiveInput 474\n"); + emit signalReceiveInput(msg,number); +// emit signalReceiveInput(mMsg); +// delete mMsg; + return TRUE; +} + +void KEInput::Lock() +{ + locked=true; +} + +void KEInput::Unlock() +{ + locked=false; +} + +bool KEInput::IsLocked() +{ + return locked; +} + diff --git a/lskat/lskat/KEInput.h b/lskat/lskat/KEInput.h new file mode 100644 index 00000000..e2f3ef8b --- /dev/null +++ b/lskat/lskat/KEInput.h @@ -0,0 +1,82 @@ +/*************************************************************************** + KEInput.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KEINPUT_H_ +#define _KEINPUT_H_ + +#include <qptrlist.h> +#include <qobject.h> +#include <qtimer.h> +#include <qmemarray.h> +#include "KConnectEntry.h" +#include "KRemoteConnect.h" +#include "KProcessConnect.h" +#include "KInteractiveConnect.h" +#include "KEMessage.h" +#include "KConnectTypes.h" + + +class KEInput : public QObject +{ + Q_OBJECT + + private: + int number_of_inputs; + int previous_input,next_input; + bool locked; +// KEMessage *mMsg; + QTimer *cTimer; + + QPtrList<KRemoteConnect> remoteList; + QPtrList<KProcessConnect> computerList; + QPtrList<KInteractiveConnect> interactiveList; + QMemArray<KConnectEntry> playerArray; + + public: + KEInput(QObject * parent=0); + ~KEInput(); + int QueryNumberOfInputs(); + int QueryNext(); + bool IsInteractive(int no=-1); + bool IsProcess(int no=-1); + bool IsRemote(int no=-1); + int QueryPrevious(); + KG_INPUTTYPE QueryType(int no=-1); + KR_STATUS QueryStatus(int no=-1); + bool IsInput(int no); + bool SetInputDevice(int no, KG_INPUTTYPE type, KEMessage *msg=0); + bool RemoveInput(int no); + bool Next(int number, bool force=false); + bool SetInput(KEMessage *msg,int number=-1); + bool IsLocked(); + bool SendMsg(KEMessage *msg,int no=-1); + void Unlock(); + void Lock(); + + public slots: + void slotTimerNextRemote(); + void slotTimerNextProcess(); + void slotSetInput(KEMessage *msg,int id); + void slotPrepareMove(KEMessage *msg,KG_INPUTTYPE type); + + signals: + void signalReceiveInput(KEMessage *msg,int id); + void signalPrepareRemoteMove(KEMessage *msg); + void signalPrepareProcessMove(KEMessage *msg); + void signalPrepareInteractiveMove(KEMessage *msg); + +}; +#endif diff --git a/lskat/lskat/KEMessage.cpp b/lskat/lskat/KEMessage.cpp new file mode 100644 index 00000000..9d3d3d3f --- /dev/null +++ b/lskat/lskat/KEMessage.cpp @@ -0,0 +1,326 @@ +/*************************************************************************** + KEMessage.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "KEMessage.h" + +void KEMessage::AddEntry(QString key,KMessageEntry *entry) +{ + // printf(" AddingEntry: %s with data field %p\n",(char *)key,entry->QueryData()); + if (!entry) return ; + dict.insert(key,entry); + keys.append(key.latin1()); +} + +void KEMessage::AddDataType(QString key,int size,const char *data,KGM_TYPE type) +{ +// printf("AddDataType for %s size=%d\n",(const char *)key,size); + if (size<=0) return ; + KMessageEntry *entry=new KMessageEntry; + entry->SetType(type); + entry->CopyData(size,data); + AddEntry(key,entry); +} + +void KEMessage::AddData(QString key,short data) +{ + AddDataType(key,sizeof(short),(char *)&data,KGM_TYPE_SHORT); +} + +void KEMessage::AddData(QString key,long data) +{ + AddDataType(key,sizeof(long),(char *)&data,KGM_TYPE_LONG); +} + +void KEMessage::AddData(QString key,float data) +{ + AddDataType(key,sizeof(float),(char *)&data,KGM_TYPE_FLOAT); +} + +void KEMessage::AddData(QString key, const char *data,int size) +{ + if (size<0) size=strlen(data)+1; // +1 for 0 Byte + AddDataType(key,size,data,KGM_TYPE_DATA); +} + +KGM_TYPE KEMessage::QueryType(QString key) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return (KGM_TYPE)0; + return entry->QueryType(); +} + +bool KEMessage::HasKey(QString key) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + return true; +} + +bool KEMessage::GetData(QString key,short &s) +{ + short *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_SHORT) return false; + // printf("GetShortData: %p for %s\n",entry->QueryData(),(char *)key); + result=(short *)entry->QueryData(); + s=*result; + return true; +} + +bool KEMessage::GetData(QString key,long &l) +{ + long *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_LONG) return false; + result=(long *)entry->QueryData(); + l=*result; + return true; +} + +bool KEMessage::GetData(QString key,float &f) +{ + float *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_FLOAT) return false; + // printf("GetFloatData: %p for %s\n",entry->QueryData(),(char *)key); + result=(float *)entry->QueryData(); + f=*result; + return true; +} + +bool KEMessage::GetData(QString key,char * &c,int &size) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_DATA) return false; + c=entry->QueryData(); + size=entry->QuerySize(); + return true; +} + +QString KEMessage::EntryToString(char *key,KMessageEntry *entry) +{ + QString s,tmp; + int size,i; + KGM_TYPE type; + char *data; + s=QCString(""); + if (!entry) return s; + size=entry->QuerySize(); + type=entry->QueryType(); + data=entry->QueryData(); + + // Key + /* + tmp.sprintf("%s%s%d%s%d%s", + key,KEMESSAGE_SEP, + size,KEMESSAGE_SEP, + (int)type,KEMESSAGE_SEP); + */ + tmp=QCString(key); + s+=tmp; + s+=KEMESSAGE_SEP; + tmp.sprintf("%d",size); + s+=tmp; + s+=KEMESSAGE_SEP; + tmp.sprintf("%d",(int)type); + s+=tmp; + s+=KEMESSAGE_SEP; + + + // We ignore the type of data and process them all as + // byte sequence + for (i=0;i<size;i++) + { + // Convert to 4 bit value ... someone can improves + tmp.sprintf("%c%c", + 'a'+(data[i]&15), + 'a'+((data[i]>>4)&15)); + s+=tmp; + } + s+=KEMESSAGE_CR; + + return s; +} + +QString KEMessage::StringToEntry(QString str,KMessageEntry *entry) +{ + int pos,oldpos,cnt,len; + QString key,size,type,data; + const char *p; + char *q; + char c; + + len=KEMESSAGE_SEP.length(); + + if (!entry) return QString(); + pos=str.find(KEMESSAGE_SEP,0); + if (pos<0) return QString(); // wrong format + key=str.left(pos); + + + oldpos=pos; + pos=str.find(KEMESSAGE_SEP,oldpos+len); + if (pos<0) return QString(); // wrong format + size=str.mid(oldpos+len,pos-oldpos-len); + + + oldpos=pos; + pos=str.find(KEMESSAGE_SEP,oldpos+len); + if (pos<0) return QString(); // wrong format + type=str.mid(oldpos+len,pos-oldpos-len); + + + data=str.right(str.length()-pos-len); + + + cnt=size.toInt(); + entry->SetType((KGM_TYPE)type.toInt()); + + // I hope this works with unicode strings as well + p=data.latin1(); + q=(char *)calloc(data.length()/2,sizeof(char)); + if (!q) return QString(); + for(pos=0;pos<cnt;pos++) + { + if (pos*2+1>(int)data.length()) return QString(); // SEVERE ERROR + c=*(p+2*pos)-'a' | ((*(p+2*pos+1)-'a')<<4); + q[pos]=c; + } + entry->CopyData(cnt,q); + + free(q); + return key; +} + +QString KEMessage::ToString() +{ + QString s; + KMessageEntry *entry; + char *it; + s=KEMESSAGE_HEAD+KEMESSAGE_CR; + for (it=keys.first();it!=0;it=keys.next()) + { + entry=dict.find(QCString(it)); + s+=EntryToString(it,entry); + } + s+=KEMESSAGE_TAIL+KEMESSAGE_CR; + return s; +} + +bool KEMessage::AddString(QString s) +{ + // break s into key,size and data + QString key; + KMessageEntry *entry=new KMessageEntry; + key=StringToEntry(s,entry); + if (!key) return false; + AddEntry(key,entry); + return true; +} +bool KEMessage::AddStringMsg(QString str) +{ + bool result; + QString data; + int pos,oldpos,len; + + len=KEMESSAGE_CR.length(); + + pos=str.find(KEMESSAGE_CR); + if (pos<0) return false; // wrong format + if (str.left(pos)!=(KEMESSAGE_HEAD)) return false; // wrong message + + do + { + oldpos=pos; + pos=str.find(KEMESSAGE_CR,oldpos+len); + if (pos<0) return false; // wrong format + data=str.mid(oldpos+len,pos-oldpos-len); + if (data!=(KEMESSAGE_TAIL)) + { + result=AddString(data); + if (!result) return false; // wrong format + } + }while(data!=(KEMESSAGE_TAIL)); + + return result; +} + +void KEMessage::RemoveAll() +{ + keys.clear(); + dict.clear(); +} + +void KEMessage::Remove(QString key) +{ + keys.remove(key.latin1()); + dict.remove(key); +} + +uint KEMessage::QueryNumberOfKeys() +{ + return keys.count(); +} +QStrList *KEMessage::QueryKeys() +{ + return &keys; +} + +KEMessage::~KEMessage() +{ + // printf("Deleteing KEMessage %p\n",this); +} +KEMessage::KEMessage() +{ + // printf("KEMessage construct %p\n",this); + dict.setAutoDelete(true); +} +KEMessage::KEMessage(KEMessage &msg) +{ + // printf("KEMessage copy constructor from %p to %p\n",&msg,this); + *this=msg; +} +KEMessage &KEMessage::operator=(KEMessage &msg) +{ + // KEMessage *newmsg=new KEMessage; + KMessageEntry *entry; + KMessageEntry *newentry; + char *it; + // printf("Assigning = KEMessage from %p to %p\n",&msg,this); + for (it=msg.keys.first();it!=0;it=msg.keys.next()) + { + entry=msg.dict.find(QCString(it)); + newentry=new KMessageEntry; + *newentry=*entry; + AddEntry(QCString(it),newentry); + + } + // return *newmsg; + return *this; +} diff --git a/lskat/lskat/KEMessage.h b/lskat/lskat/KEMessage.h new file mode 100644 index 00000000..0a1913cc --- /dev/null +++ b/lskat/lskat/KEMessage.h @@ -0,0 +1,66 @@ +/*************************************************************************** + KEMessage.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KEMESSAGE_H_ +#define _KEMESSAGE_H_ + +#include <string.h> +#include <qstring.h> +#include <qstrlist.h> +#include <qdict.h> +#include "KMessageEntry.h" + +#define KEMESSAGE_HEAD QString(QCString("BEGIN_V1000")) +#define KEMESSAGE_TAIL QString(QCString("END_V1000")) +#define KEMESSAGE_CR QString(QCString("\n")) +#define KEMESSAGE_SEP QString(QCString(":::")) + +class KEMessage +{ + private: + QStrList keys; + QDict<KMessageEntry> dict; + + protected: + void AddEntry(QString key,KMessageEntry *entry); + public: + QStrList *QueryKeys(); + uint QueryNumberOfKeys(); + void AddDataType(QString key,int size,const char *data,KGM_TYPE type); + void AddData(QString key,short data); + void AddData(QString key,long data); + void AddData(QString key,float data); + void AddData(QString key,const char *data,int size=-1); + bool GetData(QString key,short &s); + bool GetData(QString key,long &l); + bool GetData(QString key,float &f); + bool GetData(QString key,char * &c,int &size); + bool HasKey(QString key); + void Remove(QString key); + KGM_TYPE QueryType(QString key); + QString ToString(); + QString EntryToString(char *key,KMessageEntry *entry); + QString StringToEntry(QString str,KMessageEntry *entry); + bool AddString(QString s); + bool AddStringMsg(QString str); + void RemoveAll(); + ~KEMessage(); + KEMessage(); + KEMessage(KEMessage &msg); + KEMessage &operator=(KEMessage &msg); +}; + +#endif diff --git a/lskat/lskat/KInputChildProcess.cpp b/lskat/lskat/KInputChildProcess.cpp new file mode 100644 index 00000000..fb6e743a --- /dev/null +++ b/lskat/lskat/KInputChildProcess.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + KInputChildProcess.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <qstring.h> + +#include "KInputChildProcess.h" +#include "KInputChildProcess.moc" + + +KInputChildProcess::~KInputChildProcess() +{ + delete buffer; + delete childConnect; +} +KInputChildProcess::KInputChildProcess(int size_buffer) + : QObject(0,0) +{ + buffersize=size_buffer; + if (buffersize<1) buffersize=1024; + buffer=new char[buffersize]; + inputbuffer=""; + terminateChild=false; +} +bool KInputChildProcess::exec() +{ + int pos; + QString s; + + childConnect=new KChildConnect; + if (!childConnect) return false; + connect(childConnect,SIGNAL(signalReceiveMsg(KEMessage *,int)), + this,SLOT(slotReceiveMsg(KEMessage *,int))); + do + { + // Wait for input + if (feof(stdin)) + { + sleep(1); + continue; + } + + if (!fgets(buffer,buffersize,stdin) ) + { + continue; + } + s=buffer; + s=inputbuffer+s; + // printf("ChildABC '%s'\n",(const char *)s); + // fflush(stdout); + pos=s.findRev(KEMESSAGE_CR); + if (pos<0) + { + inputbuffer=s; + } + else if (pos+KEMESSAGE_CR.length()==s.length()) + { + // CR at the end...calling receive + childConnect->Receive(s); + } + else + { + inputbuffer=s.right(s.length()-pos-KEMESSAGE_CR.length()); + s=s.left(pos+KEMESSAGE_CR.length()); + // printf("s='%s' in='%s'\n",(const char *)s,(const char *)inputbuffer); + childConnect->Receive(s); + } + }while(!terminateChild); + return true; +} + +void KInputChildProcess::Terminate() +{ + terminateChild=true; +} +bool KInputChildProcess::IsTerminated() +{ + return terminateChild; +} + +bool KInputChildProcess::ReceiveMsg(KEMessage *,int ) +{ + return false; +} +void KInputChildProcess::slotReceiveMsg(KEMessage *msg,int id) +{ + if (!ReceiveMsg(msg,id)) // made for virtual override + { + // otherwise emit signal + emit signalReceiveMsg(msg,id); + } +} +bool KInputChildProcess::SendMsg(KEMessage *msg) +{ + if (childConnect) return childConnect->SendMsg(msg); + return false; +} + + diff --git a/lskat/lskat/KInputChildProcess.h b/lskat/lskat/KInputChildProcess.h new file mode 100644 index 00000000..b4694df5 --- /dev/null +++ b/lskat/lskat/KInputChildProcess.h @@ -0,0 +1,57 @@ +/*************************************************************************** + KInputChildProcess.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KINPUTCHILDPROCESS_H_ +#define _KINPUTCHILDPROCESS_H_ + +#include <qobject.h> +#include "KEMessage.h" +#include "KChildConnect.h" + + +class KInputChildProcess : public QObject +{ + Q_OBJECT + + private: + char *buffer; + QString inputbuffer; + int buffersize; + bool terminateChild; + protected: + KChildConnect *childConnect; + + public: + KInputChildProcess(int size_buffer=4096); + ~KInputChildProcess(); + bool exec(); + virtual bool ReceiveMsg(KEMessage *msg,int id); + // Forward calls to childconnect + bool SendMsg(KEMessage *msg); + // Immediately kills child's exec ! + void Terminate(); + bool IsTerminated(); + + + public slots: + void slotReceiveMsg(KEMessage *msg,int id); + + signals: + void signalReceiveMsg(KEMessage *msg,int id); +}; + + +#endif diff --git a/lskat/lskat/KInteractiveConnect.cpp b/lskat/lskat/KInteractiveConnect.cpp new file mode 100644 index 00000000..e95dcbe1 --- /dev/null +++ b/lskat/lskat/KInteractiveConnect.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + KInteractiveConnect.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include "KInteractiveConnect.h" + +#include "KInteractiveConnect.moc" + +bool KInteractiveConnect::Next() +{ + // Dummy only for interactive + KEMessage *msg=new KEMessage; + emit signalPrepareMove(msg,KG_INPUTTYPE_INTERACTIVE); + delete msg; + return true; +} +bool KInteractiveConnect::Init(int id,KEMessage *) +{ + // emit signalReceiveMsg(msg); + SetID(id); + return true; +} +bool KInteractiveConnect::Exit() +{ + return true; +} + +KInteractiveConnect::~KInteractiveConnect() +{ +// printf("DESTRUCTING INTERACTIVE\n"); +} + +KInteractiveConnect::KInteractiveConnect() + : KChildConnect() +{ +} + +bool KInteractiveConnect::SendMsg(KEMessage *msg) +{ + printf("+- Interactive::SendMessage MESSAGE::Emmiting slotReceiveMsg\n"); + emit signalReceiveMsg(msg,QueryID()); + return true; +} +// Try not to use this..prodices just unnecessary string-msg +// conversion +bool KInteractiveConnect::Send(QString str) +{ + Receive(str); + return true; +} diff --git a/lskat/lskat/KInteractiveConnect.h b/lskat/lskat/KInteractiveConnect.h new file mode 100644 index 00000000..5a393c26 --- /dev/null +++ b/lskat/lskat/KInteractiveConnect.h @@ -0,0 +1,41 @@ +/*************************************************************************** + KInteractiveConnect.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KINTERACTIVECONNECT_H_ +#define _KINTERACTIVECONNECT_H_ + +#include "KEMessage.h" +#include "KChildConnect.h" + +class KInteractiveConnect:public KChildConnect +{ + Q_OBJECT + + public: + KInteractiveConnect(); + ~KInteractiveConnect(); + bool Next(); + bool Init(int id=0,KEMessage *msg=0); + bool Exit(); + bool SendMsg(KEMessage *msg); + bool Send(QString str); + + signals: + void signalPrepareMove(KEMessage *msg,KG_INPUTTYPE type); +// void signalReceiveMsg(KEMessage *msg,int id); +}; + +#endif diff --git a/lskat/lskat/KMessageEntry.cpp b/lskat/lskat/KMessageEntry.cpp new file mode 100644 index 00000000..cb9b2dc0 --- /dev/null +++ b/lskat/lskat/KMessageEntry.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + KMessageEntry.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include "KMessageEntry.h" + +void KMessageEntry::SetType(KGM_TYPE t) +{ + type=t; +} + +KGM_TYPE KMessageEntry::QueryType() +{ + return type; +} + +int KMessageEntry::QuerySize() +{ + return size; +} + +char * KMessageEntry::QueryData() +{ + return data; +} + +bool KMessageEntry::CopyData(int s,const char *c) +{ + if (s<1) return false; + data=(char *)calloc(s,1); + if (!data) return false; + // printf(" MessageEntry Copy Data to calloc %p\n",data); + memcpy(data,c,s); + size=s; + return true; +} + +KMessageEntry::KMessageEntry() +{ + // printf("KMessageEntry construct %p\n",this); + size=0; + type=(KGM_TYPE)0; + data=(char *)0; +} + +KMessageEntry::KMessageEntry(KMessageEntry &entry) +{ + // printf("KMessageEntry copy constructor from %p to %p\n",&entry,this); + *this=entry; +} +KMessageEntry &KMessageEntry::operator=(KMessageEntry &entry) +{ + // printf("KMessageEntry operator= from %p to %p\n",&entry,this); + SetType(entry.type); + CopyData(entry.size,entry.data); + return *this; +} + +KMessageEntry::~KMessageEntry() +{ + // printf("MessageEntry destructor %p\n",this); + // printf(" MessageEntry free %p\n",data); + if (data) free(data); + data=(char *)0; +} + diff --git a/lskat/lskat/KMessageEntry.h b/lskat/lskat/KMessageEntry.h new file mode 100644 index 00000000..3feb4fad --- /dev/null +++ b/lskat/lskat/KMessageEntry.h @@ -0,0 +1,42 @@ +/*************************************************************************** + KMessageEntry.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _KMESSAGEENTRY_H_ +#define _KMESSAGEENTRY_H_ + +#include "KConnectTypes.h" + +class KMessageEntry +{ + private: + int size; + KGM_TYPE type; + char *data; + + public: + void SetType(KGM_TYPE t); + KGM_TYPE QueryType(); + int QuerySize(); + char *QueryData(); + bool CopyData(int s,const char *c); + KMessageEntry(); + KMessageEntry(KMessageEntry &entry); + KMessageEntry &operator=(KMessageEntry &entry); + ~KMessageEntry(); +}; + +#endif diff --git a/lskat/lskat/KProcessConnect.cpp b/lskat/lskat/KProcessConnect.cpp new file mode 100644 index 00000000..740486b3 --- /dev/null +++ b/lskat/lskat/KProcessConnect.cpp @@ -0,0 +1,192 @@ +/*************************************************************************** + KProcessConnect.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include "KProcessConnect.h" + +#include "KProcessConnect.moc" + +KProcessConnect::KProcessConnect() + : KChildConnect() +{ + running=false; + process=0; +} + +KProcessConnect::~KProcessConnect() +{ + Exit(); + delete process; +// printf("DESTRUCTRING KPROCESSCONNECT\n"); +} + +bool KProcessConnect::Init(int id,KEMessage *msg) +{ + int size; + char *p; + + SetID(id); + if (msg) + { + if (!msg->GetData(QCString("ProcessName"),p,size)) return false; // no process name + processname=p; + /* + printf("Found processname '%s' size %d size=%u\n", + p,size,msg->QueryNumberOfKeys()); + */ + msg->Remove(QCString("ProcessName")); + } + if (processname.length()<1) return false; + + inputbuffer=""; + + // Delete first on multiple init + if (running) Exit(); + + // create process + process=new KProcess; + *process << processname; + connect(process, SIGNAL(receivedStdout(KProcess *, char *, int )), + this, SLOT(slotReceivedStdout(KProcess *, char * , int ))); + connect(process, SIGNAL(processExited(KProcess *)), + this, SLOT(slotProcessExited(KProcess *))); + /* + connect(process, SIGNAL(wroteStdin(KProcess *)), + this, SLOT(slotWroteStdin(KProcess *))); + */ + + // TRUE if ok + running=process->start(KProcess::NotifyOnExit,KProcess::All); + + if (running && msg && msg->QueryNumberOfKeys()>0) + { + SendMsg(msg); + } + + return running; +} + +void KProcessConnect::slotReceivedStdout(KProcess *, char *buffer, int buflen) +{ + QString s; + char c; + int pos; + + if (buflen<1) return ; + if (buffer[buflen-1]!=0) // shit..we got a not null terminated string + { + c=buffer[buflen-1]; + buffer[buflen-1]=0; + s=buffer; + s+=c; + } + else + { + s=buffer; + } + // Append old unresolved input + s=inputbuffer+s; + pos=s.findRev(KEMESSAGE_CR); + // printf("String '%s' pos=%d len=%d\n",(const char *)s,pos,s.length()); + if (pos<0) + { + inputbuffer=s; + } + else if (pos+KEMESSAGE_CR.length()==s.length()) + { + // CR at the end...calling receive + Receive(s); + } + else + { + inputbuffer=s.right(s.length()-pos-KEMESSAGE_CR.length()); + s=s.left(pos+KEMESSAGE_CR.length()); + // printf("s='%s' in='%s'\n",(const char *)s,(const char *)inputbuffer); + Receive(s); + } +} +void KProcessConnect::slotProcessExited(KProcess *) +{ + running=false; + delete process; + process=0; + Init(QueryID()); +} +void KProcessConnect::slotWroteStdin(KProcess *) +{ + printf("slotWroteStdin:: IS NEVER CALLED\n"); +} + +bool KProcessConnect::Exit() +{ + // kill process if running + if (running) + { + running=false; + if (process) process->kill(); + delete process; + process=0; + } + return true; +} + +bool KProcessConnect::Next() +{ + bool result; + if (!running) return false; + // create and send message + // printf("+- KProcessConnect::ProcessNext\n"); + KEMessage *msg=new KEMessage; + // User fills message + emit signalPrepareMove(msg,KG_INPUTTYPE_PROCESS); + result=SendMsg(msg); + delete msg; + return result; +} + +// Send string to child +bool KProcessConnect::Send(QString str) +{ + bool result; + // printf("****** PROCESS:SEND\n"); + if (!running || !process) return false; + if (!str || str.length()<1) return true; // no need to send crap + // TODO ..why? + QString s; + s=KEMESSAGE_CR+KEMESSAGE_CR; + str=s+str; + // printf("+++ Sending to child '%s'!!!\n",(const char *)str); + result=process->writeStdin(str.latin1(),str.length()+1); + if (!result) printf("ERROR in PROCESS SEND\n"); + return result; +} + diff --git a/lskat/lskat/KProcessConnect.h b/lskat/lskat/KProcessConnect.h new file mode 100644 index 00000000..9229ddd4 --- /dev/null +++ b/lskat/lskat/KProcessConnect.h @@ -0,0 +1,57 @@ +/*************************************************************************** + KProcessConnect.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KPROCESSCONNECT_H_ +#define _KPROCESSCONNECT_H_ + +#include <kprocess.h> +//#include <ksock.h> +// #include "KEInput.h" +#include "KEMessage.h" +#include "KChildConnect.h" + + +class KProcessConnect: public KChildConnect +{ + Q_OBJECT + + private: + KProcess *process; + QString processname; + bool running; + + public: + KProcessConnect(); + ~KProcessConnect(); + bool Init(int id=0,KEMessage *msg=0); + bool Exit(); + bool Next(); + // bool SendMsg(KEMessage *msg); + virtual bool Send(QString str); + // void Receive(QString input); + + public slots: + void slotReceivedStdout(KProcess *proc, char *buffer, int buflen); + void slotProcessExited(KProcess *p); + void slotWroteStdin(KProcess *p); + + + signals: + void signalPrepareMove(KEMessage *msg,KG_INPUTTYPE type); +// void signalReceiveMsg(KEMessage *msg); +}; + +#endif diff --git a/lskat/lskat/KRSocket.cpp b/lskat/lskat/KRSocket.cpp new file mode 100644 index 00000000..0a699600 --- /dev/null +++ b/lskat/lskat/KRSocket.cpp @@ -0,0 +1,374 @@ +/*************************************************************************** + KRSocket.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 file is part of the KDE libraries + * Copyright (C) 1997 Torben Weis ([email protected]) + * + * $Id$ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <config.h> + +#include <sys/types.h> +#include <sys/stat.h> +// on Linux/libc5, this includes linux/socket.h where SOMAXCONN is defined +#include <sys/socket.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/un.h> + +#include <netinet/in.h> + +#include <arpa/inet.h> + +#include "KRSocket.h" + +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +// defines MAXDNAME under Solaris +#include <arpa/nameser.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> + +#ifdef HAVE_SYSENT_H +#include <sysent.h> +#endif + +#ifdef TIME_WITH_SYS_TIME +#include <time.h> +#endif + +// Play it safe, use a reasonable default, if SOMAXCONN was nowhere defined. +#ifndef SOMAXCONN +#warning Your header files do not seem to support SOMAXCONN +#define SOMAXCONN 5 +#endif + +#include <qsocketnotifier.h> + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 // this is the value, I found under Linux +#endif + +#include <kdebug.h> + +KRServerSocket::KRServerSocket( const char *_path, int optname, int value, int level) : + notifier( 0L ), sock( -1 ) +{ + domain = PF_UNIX; + + if ( !init ( _path,optname,value,level ) ) + { + qFatal("Error constructing PF_UNIX domain server socket\n"); + return; + } + + notifier = new QSocketNotifier( sock, QSocketNotifier::Read ); + connect( notifier, SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) ); +} + +KRServerSocket::KRServerSocket( const char *_path ) : + notifier( 0L ), sock( -1 ) +{ + domain = PF_UNIX; + + if ( !init ( _path ) ) + { + qFatal("Error constructing PF_UNIX domain server socket\n"); + return; + } + + notifier = new QSocketNotifier( sock, QSocketNotifier::Read ); + connect( notifier, SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) ); +} + +KRServerSocket::KRServerSocket( unsigned short int _port ) : + notifier( 0L ), sock( -1 ) +{ + domain = PF_INET; + + if ( !init ( _port ) ) + { + // fatal("Error constructing\n"); + return; + } + + notifier = new QSocketNotifier( sock, QSocketNotifier::Read ); + connect( notifier, SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) ); +} + +KRServerSocket::KRServerSocket( unsigned short int _port,int optname,int value,int level ) : + notifier( 0L ), sock( -1 ) +{ + domain = PF_INET; + + if ( !init ( _port,optname,value,level ) ) + { + // fatal("Error constructing\n"); + return; + } + + notifier = new QSocketNotifier( sock, QSocketNotifier::Read ); + connect( notifier, SIGNAL( activated(int) ), this, SLOT( slotAccept(int) ) ); +} + +bool KRServerSocket::init( const char *_path ) +{ + return init(_path,0); +} + +bool KRServerSocket::init( const char *_path,int optname,int value,int level ) +{ + if ( domain != PF_UNIX ) + return false; + + int l = strlen( _path ); + if ( l > UNIX_PATH_MAX - 1 ) + { + kdWarning() << "Too long PF_UNIX domain name: " << _path << endl; + return false; + } + + sock = ::socket( PF_UNIX, SOCK_STREAM, 0 ); + if (sock < 0) + { + kdWarning() << "Could not create socket" << endl; + return false; + } + // Heni - 05042000 + if (optname>0) + { + kde_socklen_t len=sizeof(value); + if (-1==setsockopt(sock,level,optname,(char*)&value,len )) + { + kdWarning() << "Could not set socket options." << endl; + } + } + // end Heni + + unlink(_path ); + + struct sockaddr_un name; + name.sun_family = AF_UNIX; + strcpy( name.sun_path, _path ); + + if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) + { + kdWarning() << "Could not bind to socket." << endl; + ::close( sock ); + sock = -1; + return false; + } + + if ( chmod( _path, 0600) < 0 ) + { + kdWarning() << "Could not setupt premissions for server socket." << endl; + ::close( sock ); + sock = -1; + return false; + } + + if ( listen( sock, SOMAXCONN ) < 0 ) + { + kdWarning() << "Error listening on socket." << endl; + ::close( sock ); + sock = -1; + return false; + } + + return true; +} + +bool KRServerSocket::init( unsigned short int _port ) +{ + return init(_port,0); +} +bool KRServerSocket::init( unsigned short int _port,int optname,int value,int level ) +{ + if ( +#ifdef INET6 + ( domain != PF_INET6 ) && +#endif + ( domain != PF_INET ) ) + return false; + + sock = ::socket( domain, SOCK_STREAM, 0 ); + if (sock < 0) + { + kdWarning() << "Could not create socket" << endl; + return false; + } + // Heni - 05042000 + if (optname>0) + { + kde_socklen_t len=sizeof(value); + if (-1==setsockopt(sock,level,optname,(char*)&value,len )) + { + kdWarning() << "Could not set socket options." << endl; + } + } + // end Heni + + if (domain == AF_INET) { + + sockaddr_in name; + + name.sin_family = domain; + name.sin_port = htons( _port ); + name.sin_addr.s_addr = htonl(INADDR_ANY); + + if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) { + kdWarning() << "Could not bind to socket." << endl; + ::close( sock ); + sock = -1; + return false; + } + } +#ifdef INET6 + else if (domain == AF_INET6) { + sockaddr_in6 name; + + name.sin6_family = domain; + name.sin6_flowinfo = 0; + name.sin6_port = htons(_port); + memcpy(&name.sin6_addr, &in6addr_any, sizeof(in6addr_any)); + + if ( bind( sock, (struct sockaddr*) &name,sizeof( name ) ) < 0 ) { + kdWarning() << "Could not bind to socket!" << endl; + ::close( sock ); + sock = -1; + return false; + } + } +#endif + + if ( listen( sock, SOMAXCONN ) < 0 ) + { + kdWarning() << "Error listening on socket" << endl; + ::close( sock ); + sock = -1; + return false; + } + + return true; +} + +unsigned short int KRServerSocket::port() +{ + if ( domain != PF_INET ) + return false; + + ksockaddr_in name; kde_socklen_t len = sizeof(name); + getsockname(sock, (struct sockaddr *) &name, &len); + return ntohs(get_sin_port(name)); +} + +unsigned long KRServerSocket::ipv4_addr() +{ + if ( domain != PF_INET ) + return 0; + + sockaddr_in name; kde_socklen_t len = sizeof(name); + getsockname(sock, (struct sockaddr *) &name, &len); + if (name.sin_family == AF_INET) // It's IPv4 + return ntohl(name.sin_addr.s_addr); +#ifdef INET6 + else if (name.sin_family == AF_INET6) // It's IPv6 Ah. + return 0; +#endif + else // We dunno what it is + return 0; +} + +void KRServerSocket::slotAccept( int ) +{ + if ( domain == PF_INET ) + { + ksockaddr_in clientname; + int new_sock; + + kde_socklen_t size = sizeof(clientname); + + if ((new_sock = accept (sock, (struct sockaddr *) &clientname, &size)) < 0) + { + kdWarning() << "Error accepting" << endl; + return; + } + + emit accepted( new KSocket( new_sock ) ); + } + else if ( domain == PF_UNIX ) + { + struct sockaddr_un clientname; + int new_sock; + + kde_socklen_t size = sizeof(clientname); + + if ((new_sock = accept (sock, (struct sockaddr *) &clientname, &size)) < 0) + { + kdWarning() << "Error accepting" << endl; + return; + } + + emit accepted( new KSocket( new_sock ) ); + } +} + +KRServerSocket::~KRServerSocket() +{ + delete notifier; + + close( sock ); +} + +#include "KRSocket.moc" diff --git a/lskat/lskat/KRSocket.h b/lskat/lskat/KRSocket.h new file mode 100644 index 00000000..6c0b9974 --- /dev/null +++ b/lskat/lskat/KRSocket.h @@ -0,0 +1,169 @@ +/*************************************************************************** + KRSocket.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* + * Remark: This is a copy of the ksock library. It will be merged with + * the ksock file as soon as it supports the SOCK_REUSE_ADDR flag +*/ + + +#ifndef KRSOCK_H +#define KRSOCK_H + +#include <qobject.h> +#include <sys/types.h> +// we define STRICT_ANSI to get rid of some warnings in glibc +#ifndef __STRICT_ANSI__ +#define __STRICT_ANSI__ +#define _WE_DEFINED_IT_ +#endif +#include <sys/socket.h> +#ifdef _WE_DEFINED_IT_ +#undef __STRICT_ANSI__ +#undef _WE_DEFINED_IT_ +#endif + +#include <sys/un.h> + +#include <netinet/in.h> +class QSocketNotifier; + +#ifdef INET6 +typedef sockaddr_in6 ksockaddr_in; +#define KSOCK_DEFAULT_DOMAIN PF_INET6 +#else +typedef sockaddr_in ksockaddr_in; +#define KSOCK_DEFAULT_DOMAIN PF_INET +#endif + +#include <ksock.h> + +class KRServerSocketPrivate; + + +/** + * Monitor a port for incoming TCP/IP connections. + * + * You can use a KRServerSocket to listen on a port for incoming + * connections. When a connection arrived in the port, a KSocket + * is created and the signal accepted is raised. Make sure you + * always connect to this signal. If you dont the ServerSocket will + * create new KSocket's and no one will delete them! + * + * If socket() is -1 or less the socket was not created properly. + * + * @author Torben Weis <[email protected]> + * @version $Id$ + * @short Monitor a port for incoming TCP/IP connections. +*/ +class KRServerSocket : public QObject +{ + Q_OBJECT +public: + /** + * Constructor. + * @param _port the port number to monitor for incoming connections. + */ + KRServerSocket( unsigned short int _port ); + KRServerSocket( unsigned short int _port, int optname, int value=1, int level=SOL_SOCKET); + + /** + * Creates a UNIX domain server socket. + */ + KRServerSocket( const char *_path ); + KRServerSocket( const char *_path, int optname, int value=1, int level=SOL_SOCKET); + + /** + * Destructor. Closes the socket if it was not already closed. + */ + ~KRServerSocket(); + + /** + * Get the file descriptor assoziated with the socket. + */ + int socket() const { return sock; } + + /** + * Returns the port number which is being monitored. + */ + unsigned short int port(); + + /** + * The address. + */ + unsigned long ipv4_addr(); + +public slots: + /** + * Called when someone connected to our port. + */ + virtual void slotAccept( int ); + +signals: + /** + * A connection has been accepted. + * It is your task to delete the KSocket if it is no longer needed. + */ + void accepted( KSocket* ); + +protected: + bool init( short unsigned int ); + bool init( const char *_path ); + bool init( const char *_path, int optname, int value=1, int level=SOL_SOCKET); + bool init( short unsigned int, int optname, int value=1, int level=SOL_SOCKET); + + /** + * Notifies us when there is something to read on the port. + */ + QSocketNotifier *notifier; + + /** + * The file descriptor for this socket. sock may be -1. + * This indicates that it is not connected. + */ + int sock; + + int domain; + +private: + KRServerSocket(const KRServerSocket&); + KRServerSocket& operator=(const KRServerSocket&); + + KRServerSocketPrivate *d; +}; + + +// Here are a whole bunch of hackish macros that allow one to +// get at the correct member of ksockaddr_in + +#ifdef INET6 +#define get_sin_addr(x) x.sin6_addr +#define get_sin_port(x) x.sin6_port +#define get_sin_family(x) x.sin6_family +#define get_sin_paddr(x) x->sin6_addr +#define get_sin_pport(x) x->sin6_port +#define get_sin_pfamily(x) x->sin6_family +#else +#define get_sin_addr(x) x.sin_addr +#define get_sin_port(x) x.sin_port +#define get_sin_family(x) x.sin_family +#define get_sin_paddr(x) x->sin_addr +#define get_sin_pport(x) x->sin_port +#define get_sin_pfamily(x) x->sin_family +#endif + +#endif diff --git a/lskat/lskat/KRemoteConnect.cpp b/lskat/lskat/KRemoteConnect.cpp new file mode 100644 index 00000000..f1bcb4f3 --- /dev/null +++ b/lskat/lskat/KRemoteConnect.cpp @@ -0,0 +1,334 @@ +/*************************************************************************** + KRemoteConnect.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include "KRemoteConnect.h" + +#include "KRemoteConnect.moc" + +const char* LSKAT_SERVICE = "_lskat._tcp"; + +KRemoteConnect::KRemoteConnect() + : KChildConnect() +{ + port=7687; + IP="localhost"; + socketStatus=KR_INVALID; + kSocket=0; + service=0; + kServerSocket=0; + bufferMsg=0; + buffer=new char[4097]; + inputbuffer=""; + input_pending=false; +} +KRemoteConnect::~KRemoteConnect() +{ + Exit(); + delete buffer; + delete service; + printf("DESTGRUCTING KRemoteConenct\n"); +} + +KR_STATUS KRemoteConnect::QueryStatus() +{ + return socketStatus; +} + +bool KRemoteConnect::Init(int id,KEMessage *msg) +{ +short prt; +char *p; +int size; +bool tryserver; + + SetID(id); + if (msg) + { + if (msg->GetData(QCString("Port"),prt)) + { + port=(unsigned int)prt; + msg->Remove(QCString("Port")); + } + if (msg->GetData(QCString("IP"),p,size)) + { + IP=QCString(p); + msg->Remove(QCString("IP")); + } + if (msg->GetData(QCString("Name"),p,size)) + { + Name=QString::fromUtf8(p); + msg->Remove(QCString("Name")); + } + } + /* + printf("Connecting to %s %u (remain=%d)\n", + (const char *)IP,port,msg->QueryNumberOfKeys()); + */ + + // First try to connect to given host:socket + // if no IP given only offer server + tryserver=false; + if (!IP.isEmpty()) + { + kSocket=new KSocket(IP.latin1(),port); + if (!kSocket) return false; + if (kSocket->socket()!=-1) // success + { + kSocket->enableRead(TRUE); + //kSocket->enableWrite(TRUE); + connect(kSocket,SIGNAL(closeEvent(KSocket *)), + this,SLOT(socketClosed(KSocket *))); + connect(kSocket,SIGNAL(readEvent(KSocket *)), + this,SLOT(socketRead(KSocket *))); + /* + connect(kSocket,SIGNAL(writeEvent(KSocket *)), + this,SLOT(socketWrite(KSocket *))); + */ + /* + printf("Socket(%d) %p connection built to a server\n", + kSocket->socket(),kSocket); + */ + socketStatus=KR_CLIENT; + + // Send msg if any + if (msg->QueryNumberOfKeys()>0) + { + msg->AddData(QCString("Server"),(short)QueryID()); + SendMsg(msg); + } + + } + else + { + tryserver=true; + } + } + else + { + printf("NO IP given..only server possible\n"); + tryserver=true; + } + + if (tryserver) // become a server + { + delete kSocket; + kSocket=0; + delete service; + service = 0; + // Store message + if (msg->QueryNumberOfKeys()>0) + { + bufferMsg=new KEMessage; + *bufferMsg=*msg; + } + else + { + bufferMsg=0; + } + socketStatus=KR_WAIT_FOR_CLIENT; + OfferServerSocket(); + return false; + } + + return true; +} + +bool KRemoteConnect::OfferServerSocket() +{ + if (kServerSocket) + { + return false; + } + kServerSocket=new KRServerSocket(port,SO_REUSEADDR); + if (!kServerSocket) + { + socketStatus=KR_INVALID; + return false; + } + if (kServerSocket->socket()==-1) + { + socketStatus=KR_NO_SOCKET; + return false; + } + printf("Offering socket and publishing stuff\n"); + service = new DNSSD::PublicService(Name,LSKAT_SERVICE,port); + service->publishAsync(); + connect(kServerSocket,SIGNAL(accepted(KSocket *)), + this,SLOT(socketRequest(KSocket *))); + + return true; +} +void KRemoteConnect::socketRequest(KSocket *sock) +{ + if (kSocket) // already connected + { + delete sock; + delete kServerSocket; + kServerSocket=0; + return ; + } + kSocket=sock; + if (kSocket->socket()!=-1) // success + { + kSocket->enableRead(TRUE); + //kSocket->enableWrite(TRUE); + connect(kSocket,SIGNAL(closeEvent(KSocket *)), + this,SLOT(socketClosed(KSocket *))); + connect(kSocket,SIGNAL(readEvent(KSocket *)), + this,SLOT(socketRead(KSocket *))); + /* + connect(kSocket,SIGNAL(writeEvent(KSocket *)), + this,SLOT(socketWrite(KSocket *))); + */ + socketStatus=KR_SERVER; + delete kServerSocket; // no more connections + kServerSocket=0; + if (bufferMsg) + { + // Delayed sending of init msg + bufferMsg->AddData(QCString("Client"),(short)QueryID()); + SendMsg(bufferMsg); + delete bufferMsg; + bufferMsg=0; + } + } +} + +void KRemoteConnect::socketClosed(KSocket *sock) +{ + delete sock; + kSocket=0; + socketStatus=KR_INVALID; + KEMessage *msg=new KEMessage; + msg->AddData(QCString("ConnectionLost"),(short)QueryID()); + emit signalReceiveMsg(msg,QueryID()); + delete msg; +} +void KRemoteConnect::socketRead(KSocket *sock) +{ + ssize_t buflen; + QString s; + char c; + int pos; + + // printf("++++++ Incoming socket read +++++++\n"); + if (-1==sock->socket()) return ; + // printf("Read input on socket %p\n",sock); + buflen=read(sock->socket(),buffer,4096); + buffer[buflen]=0; + // printf("Read %d byte <%s>\n",buflen,buffer); + + if (buflen<1) return ; + if (buffer[buflen-1]!=0) // shit..we got a not null terminated string + { + c=buffer[buflen-1]; + buffer[buflen-1]=0; + s=buffer; + s+=c; + } + else + { + s=buffer; + } + + // Append old unresolved input + s=inputbuffer+s; + pos=s.findRev(KEMESSAGE_CR); + // printf("String '%s' pos=%d len=%d\n",(const char *)s,pos,s.length()); + if (pos<0) + { + inputbuffer=s; + } + else if (pos+KEMESSAGE_CR.length()==s.length()) + { + // CR at the end...calling receive + Receive(s); + } + else + { + inputbuffer=s.right(s.length()-pos-KEMESSAGE_CR.length()); + s=s.left(pos+KEMESSAGE_CR.length()); + // printf("s='%s' in='%s'\n",(const char *)s,(const char *)inputbuffer); + Receive(s); + } +} + + +void KRemoteConnect::socketWrite(KSocket *) +{ + // printf("wrtie input on socket %p\n",sock); +} + +bool KRemoteConnect::Exit() +{ + delete kSocket; + delete kServerSocket; + delete bufferMsg; + kSocket=0; + kServerSocket=0; + bufferMsg=0; + socketStatus=KR_INVALID; + return true; +} +bool KRemoteConnect::Next() +{ + bool result; + // printf("+- KRemoteConnect::Next() status=%d\n",socketStatus); + if (socketStatus<=0) return false; + // create and send message + KEMessage *msg=new KEMessage; + // User fills message + emit signalPrepareMove(msg,KG_INPUTTYPE_REMOTE); + result=SendMsg(msg); + delete msg; + return result; +} + +// Send string to child +bool KRemoteConnect::Send(QString str) +{ + // connected? + if (!kSocket || kSocket->socket()==-1) return false; + if (socketStatus<=0) return false; + + if (-1==write(kSocket->socket(),str.latin1(),str.length()+1)) + { + printf("Warning: Problems writing to socket.\n"); + return false; + } + return true;; +} diff --git a/lskat/lskat/KRemoteConnect.h b/lskat/lskat/KRemoteConnect.h new file mode 100644 index 00000000..baa005d6 --- /dev/null +++ b/lskat/lskat/KRemoteConnect.h @@ -0,0 +1,74 @@ +/*************************************************************************** + KRemoteConnect.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KREMOTECONNECT_H_ +#define _KREMOTECONNECT_H_ + +//#include <ksock.h> +#include "KEMessage.h" +#include "KRSocket.h" +//#include "ksock.h" +#include "KChildConnect.h" +#include <dnssd/publicservice.h> + + + +class KRemoteConnect: public KChildConnect +{ + Q_OBJECT + + protected: + KRServerSocket *kServerSocket; + KSocket *kSocket; + QString IP; + QString Name; + ushort port; + KR_STATUS socketStatus; + char *buffer; + KEMessage *bufferMsg; + DNSSD::PublicService *service; +// QString inputbuffer; +// bool input_pending; +// QStrList inputcache; + + public: + KRemoteConnect(); + ~KRemoteConnect(); + bool Init(int id=0,KEMessage *msg=0); + bool Exit(); + bool Next(); +// bool SendMsg(KEMessage *msg); + virtual bool Send(QString str); +// void Receive(QString input); + virtual KR_STATUS QueryStatus(); + + protected: + bool OfferServerSocket(); + + protected slots: + void socketClosed(KSocket *sock); + void socketRead(KSocket *sock); + void socketWrite(KSocket *sock); + void socketRequest(KSocket *sock); + + + + signals: + void signalPrepareMove(KEMessage *msg,KG_INPUTTYPE type); +// void signalReceiveMsg(KEMessage *msg); +}; + +#endif diff --git a/lskat/lskat/Makefile.am b/lskat/lskat/Makefile.am new file mode 100644 index 00000000..ade32c96 --- /dev/null +++ b/lskat/lskat/Makefile.am @@ -0,0 +1,21 @@ + +####### kdevelop will overwrite this part!!! (begin)########## +bin_PROGRAMS = lskat +lskat_SOURCES = msgdlg.cpp networkdlg.cpp namedlg.cpp KRemoteConnect.cpp KRSocket.cpp KProcessConnect.cpp KMessageEntry.cpp KInteractiveConnect.cpp KInputChildProcess.cpp KEMessage.cpp KEInput.cpp KConnectEntry.cpp KChildConnect.cpp lskatview.cpp lskatdoc.cpp lskat.cpp main.cpp networkdlgbase.ui + +lskat_LDADD = $(LIB_KFILE) $(LIB_KDEGAMES) $(LIB_KDNSSD) +lskat_DEPENDENCIES = $(LIB_KDEGAMES_DEP) + +INCLUDES = -I$(top_srcdir)/libkdegames $(all_includes) + +METASOURCES = AUTO + +lskat_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +rcdir = $(kde_datadir)/lskat +rc_DATA = lskatui.rc + + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/lskat.pot + diff --git a/lskat/lskat/lskat.cpp b/lskat/lskat/lskat.cpp new file mode 100644 index 00000000..9d1ce7a6 --- /dev/null +++ b/lskat/lskat/lskat.cpp @@ -0,0 +1,1081 @@ +/* + lskat.cpp - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for QT +#include <qprogressdialog.h> + +// include files for KDE +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <kconfig.h> +#include <khelpmenu.h> +#include <kstdaction.h> +#include <kaction.h> +#include <kdebug.h> + +// application specific includes +#include "lskat.h" +#include "lskatview.h" +#include "lskatdoc.h" +#include "namedlg.h" +#include "networkdlg.h" +#include "msgdlg.h" +#include <kcarddialog.h> + +#include <stdlib.h> +#include <kstatusbar.h> + +#define ACTION(x) (actionCollection()->action(x)) +#define ID_STATUS_MSG 1003 +#define ID_STATUS_MOVER 1002 + +LSkatApp::LSkatApp() : KMainWindow(0) +{ + config=kapp->config(); + + // localise data file + QString file=QString::fromLatin1("lskat/grafix/t1.png"); + mGrafix=kapp->dirs()->findResourceDir("data", file); + if (mGrafix.isNull()) mGrafix = QCString("grafix/"); + else mGrafix+=QCString("lskat/grafix/"); + if (global_debug>3) printf("Localised datafile=%s\n",mGrafix.latin1()); + + + /////////////////////////////////////////////////////////////////// + // call inits to invoke all other construction parts + initGUI(); + initStatusBar(); + + setupGUI(KMainWindow::StatusBar | Save); + createGUI(QString::null, false); + + initDocument(); + initView(); + + doc->ReadConfig(config); + + // Needs to be after readOptions as we read in default paths + doc->LoadGrafix(mGrafix); + + mInput=new KEInput(this); + doc->SetInputHandler(mInput); + connect(mInput,SIGNAL(signalPrepareProcessMove(KEMessage *)), + this,SLOT(slotPrepareProcessMove(KEMessage *))); + connect(mInput,SIGNAL(signalPrepareRemoteMove(KEMessage *)), + this,SLOT(slotPrepareRemoteMove(KEMessage *))); + connect(mInput,SIGNAL(signalPrepareInteractiveMove(KEMessage *)), + this,SLOT(slotPrepareInteractiveMove(KEMessage *))); + connect(mInput,SIGNAL(signalReceiveInput(KEMessage *, int)), + this,SLOT(slotReceiveInput(KEMessage *,int ))); + + setMinimumSize(640,480); + setMaximumSize(800,600); + resize( 640, 480 ); + + // better be last in init + checkMenus(); +} + +LSkatApp::~LSkatApp() +{ + delete mInput; +} + +void LSkatApp::checkMenus(int menu) +{ + if (!menu || (menu&CheckFileMenu)) + { + if (doc->IsRunning()) disableAction("new_game"); + else enableAction("new_game"); + + if (!doc->IsRunning()) disableAction("end_game"); + else enableAction("end_game"); + + if (doc->GetPlayedBy(0)==KG_INPUTTYPE_REMOTE || + doc->GetPlayedBy(0)==KG_INPUTTYPE_REMOTE ) + { + enableAction("send_message"); + } + else + { + disableAction("send_message"); + } + } + + if (!menu || (menu&CheckOptionsMenu)) + { + ((KSelectAction *)ACTION("startplayer"))->setCurrentItem(doc->GetStartPlayer()); + + if (doc->IsRunning()) disableAction("startplayer"); + else enableAction("startplayer"); + + if (doc->GetPlayedBy(0)==KG_INPUTTYPE_INTERACTIVE) + ((KSelectAction *)ACTION("player1"))->setCurrentItem(0); + else if (doc->GetPlayedBy(0)==KG_INPUTTYPE_PROCESS) + ((KSelectAction *)ACTION("player1"))->setCurrentItem(1); + else + ((KSelectAction *)ACTION("player1"))->setCurrentItem(2); + + /* + if (doc->IsRunning()) disableAction("player1"); + else enableAction("player1"); + */ + + if (doc->GetPlayedBy(1)==KG_INPUTTYPE_INTERACTIVE) + ((KSelectAction *)ACTION("player2"))->setCurrentItem(0); + else if (doc->GetPlayedBy(1)==KG_INPUTTYPE_PROCESS) + ((KSelectAction *)ACTION("player2"))->setCurrentItem(1); + else + ((KSelectAction *)ACTION("player2"))->setCurrentItem(2); + + /* + if (doc->IsRunning()) disableAction("player2"); + else enableAction("player2"); + */ + + ((KSelectAction *)ACTION("choose_level"))->setCurrentItem(doc->GetComputerLevel()-1); + } + +} + +void LSkatApp::initGUI() +{ + QStringList list; + + (void)KStdAction::openNew(this, SLOT(slotFileNew()), actionCollection(), "new_game"); + ACTION("new_game")->setStatusText(i18n("Starting a new game...")); + ACTION("new_game")->setWhatsThis(i18n("Starting a new game...")); + (void)new KAction(i18n("&End Game"),"stop", 0, this, SLOT(slotFileEnd()), + actionCollection(), "end_game"); + ACTION("end_game")->setStatusText(i18n("Ending the current game...")); + ACTION("end_game")->setWhatsThis(i18n("Aborts a currently played game. No winner will be declared.")); + (void)new KAction(i18n("&Clear Statistics"),"flag", 0, this, SLOT(slotFileStatistics()), + actionCollection(), "clear_statistics"); + ACTION("clear_statistics")->setStatusText(i18n("Delete all time statistics...")); + ACTION("clear_statistics")->setWhatsThis(i18n("Clears the all time statistics which is kept in all sessions.")); + (void)new KAction(i18n("Send &Message..."), CTRL+Key_M, this, SLOT(slotFileMessage()), + actionCollection(), "send_message"); + ACTION("send_message")->setStatusText(i18n("Sending message to remote player...")); + ACTION("send_message")->setWhatsThis(i18n("Allows you to talk with a remote player.")); + (void)KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection(), "game_exit"); + ACTION("game_exit")->setStatusText(i18n("Exiting...")); + ACTION("game_exit")->setWhatsThis(i18n("Quits the program.")); + + (void)new KSelectAction(i18n("Starting Player"),0,this,SLOT(slotStartplayer()), + actionCollection(), "startplayer"); + ACTION("startplayer")->setStatusText(i18n("Changing starting player...")); + ACTION("startplayer")->setWhatsThis(i18n("Chooses which player begins the next game.")); + list.clear(); + list.append(i18n("Player &1")); + list.append(i18n("Player &2")); + ((KSelectAction *)ACTION("startplayer"))->setItems(list); + + (void)new KSelectAction(i18n("Player &1 Played By"),0,this,SLOT(slotPlayer1By()), + actionCollection(), "player1"); + ACTION("player1")->setStatusText(i18n("Changing who plays player 1...")); + ACTION("player1")->setWhatsThis(i18n("Changing who plays player 1...")); + list.clear(); + list.append(i18n("&Player")); + list.append(i18n("&Computer")); + list.append(i18n("&Remote")); + ((KSelectAction *)ACTION("player1"))->setItems(list); + (void)new KSelectAction(i18n("Player &2 Played By"),0,this,SLOT(slotPlayer2By()), + actionCollection(), "player2"); + ACTION("player1")->setStatusText(i18n("Changing who plays player 2...")); + ACTION("player1")->setWhatsThis(i18n("Changing who plays player 2...")); + ((KSelectAction *)ACTION("player2"))->setItems(list); + + (void)new KSelectAction(i18n("&Level"),0,this,SLOT(slotLevel()), + actionCollection(), "choose_level"); + ACTION("choose_level")->setStatusText(i18n("Change level...")); + ACTION("choose_level")->setWhatsThis(i18n("Change the strength of the computer player.")); + list.clear(); + list.append(i18n("&Normal")); + list.append(i18n("&Advanced")); + list.append(i18n("&Hard")); + ((KSelectAction *)ACTION("choose_level"))->setItems(list); + + (void)new KAction(i18n("Select &Card Deck..."), 0, this, SLOT(slotOptionsCardDeck()), + actionCollection(), "select_carddeck"); + ACTION("select_carddeck")->setStatusText(i18n("Configure card decks...")); + ACTION("select_carddeck")->setWhatsThis(i18n("Choose how the cards should look.")); + + (void)new KAction(i18n("Change &Names..."), 0, this, SLOT(slotOptionsNames()), + actionCollection(), "change_names"); + ACTION("change_names")->setStatusText(i18n("Configure player names...")); + ACTION("change_names")->setWhatsThis(i18n("Configure player names...")); + + actionCollection()->setHighlightingEnabled(true); + connect(actionCollection(), SIGNAL(actionStatusText(const QString &)), SLOT(slotStatusMsg(const QString &))); + connect(actionCollection(), SIGNAL(clearStatusText()), SLOT(slotClearStatusMsg())); + + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), +actionCollection()); +} + + +void LSkatApp::initStatusBar() +{ + /////////////////////////////////////////////////////////////////// + // STATUSBAR + // statusBar()->setInsertOrder(KStatusBar::RightToLeft); + statusBar()->insertItem(i18n("This leaves space for the mover"),ID_STATUS_MOVER,0,true); + statusBar()->insertItem(i18n("Ready"), ID_STATUS_MSG); + + slotStatusMover(i18n("(c) Martin Heni ")); + slotStatusMsg(i18n("Welcome to Lieutenant Skat")); + + // computer move timer + procTimer=new QTimer(this); + connect(procTimer,SIGNAL(timeout()),this,SLOT(slotProcTimer())); +} + +void LSkatApp::initDocument() +{ + doc = new LSkatDoc(this); + // TODO check for return false !!! + doc->newDocument(config,mGrafix); +} + +void LSkatApp::initView() +{ + //////////////////////////////////////////////////////////////////// + // create the main widget here that is managed by KMainWindow's view-region and + // connect the widget to your document to display document contents. + view = new LSkatView(this); + doc->addView(view); + setCentralWidget(view); + setCaption(i18n("Lieutenant Skat")); +} + +void LSkatApp::enableAction(const char *s) +{ + if (s) + { + KAction *act=actionCollection()->action(s); + if (act) act->setEnabled(true); + } + +} +void LSkatApp::disableAction(const char *s) +{ + if (s) + { + KAction *act=actionCollection()->action(s); + if (act) act->setEnabled(false); + } +} + +LSkatDoc *LSkatApp::getDocument() const +{ + return doc; +} + +void LSkatApp::saveProperties(KConfig *_cfg) +{ + if(doc->getTitle()!=i18n("Untitled") && !doc->isModified()) + { + // saving to tempfile not necessary + } + else + { + QString filename=doc->getAbsFilePath(); + _cfg->writePathEntry("filename", filename); + _cfg->writeEntry("modified", doc->isModified()); + + QString tempname = kapp->tempSaveName(filename); + doc->saveDocument(tempname); + } +} + + +void LSkatApp::readProperties(KConfig* _cfg) +{ + QString filename = _cfg->readPathEntry("filename"); + bool modified = _cfg->readBoolEntry("modified", false); + if(modified) + { + bool canRecover; + QString tempname = kapp->checkRecoverFile(filename, canRecover); + + if(canRecover) + { + doc->openDocument(tempname); + doc->setModified(); + QFileInfo info(filename); + doc->setAbsFilePath(info.absFilePath()); + doc->setTitle(info.fileName()); + QFile::remove(tempname); + } + } + else + { + if(!filename.isEmpty()) + { + doc->openDocument(filename); + } + } + + //QString caption=kapp->caption(); + setCaption(i18n("Lieutenant Skat")); +} + +bool LSkatApp::queryClose() +{ + return true; + return doc->saveModified(); +} + +bool LSkatApp::queryExit() +{ + doc->WriteConfig(config); + return true; +} + +///////////////////////////////////////////////////////////////////// +// SLOT IMPLEMENTATION +///////////////////////////////////////////////////////////////////// + +void LSkatApp::slotFileStatistics() +{ + QString message; + message=i18n("Do you really want to clear the all time " + "statistical data?"); + + if (KMessageBox::Yes==KMessageBox::questionYesNo(this,message,QString::null,KStdGuiItem::clear())) + { + doc->ClearStats(); + doc->slotUpdateAllViews(0); + } +} + +/** send message */ +void LSkatApp::slotFileMessage() +{ + int res; + + MsgDlg *dlg=new MsgDlg(this,QCString("Send message...")); + res=dlg->exec(); + if (res==QDialog::Accepted) + { + QString s; + s=dlg->GetMsg(); + if (!s || s.length()<1) s=QCString("..."); + KEMessage *msg=new KEMessage; + + // printf("Msg: %s\n",(char *)msg); + + msg->AddData(QCString("Message"),(char *)(s.latin1())); + if (mInput->QueryType(0)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,0); + if (mInput->QueryType(1)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,1); + delete msg; + } +} + +void LSkatApp::slotFileNew() +{ + NewGame(); + checkMenus(CheckFileMenu|CheckOptionsMenu); +} + +void LSkatApp::slotFileEnd() +{ + doc->EndGame(true); + doc->slotUpdateAllViews(0); + slotStatusMsg(i18n("Game ended...start a new one...")); + + KEMessage *msg=new KEMessage; + msg->AddData(QCString("EndGame"),(short)1); + if (mInput->QueryType(0)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,0); + if (mInput->QueryType(1)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,1); + + msg->RemoveAll(); + msg->AddData(QCString("Terminate"),(short)1); + if (mInput->QueryType(0)==KG_INPUTTYPE_PROCESS) + mInput->SendMsg(msg,0); + if (mInput->QueryType(1)==KG_INPUTTYPE_PROCESS) + mInput->SendMsg(msg,1); + delete msg; + checkMenus(CheckFileMenu|CheckOptionsMenu); + slotStatusNames(); +} + +void LSkatApp::slotFileQuit() +{ + doc->WriteConfig(config); + if (view) view->close(); + close(); + kdDebug() << "slotFileQuit done"<<endl; +} + +void LSkatApp::slotStartplayer() +{ + int i=((KSelectAction *)ACTION("startplayer"))->currentItem(); + doc->SetStartPlayer(i); + doc->UpdateViews(UPDATE_STATUS); +} + +void LSkatApp::slotPlayer1By() +{ + switch(((KSelectAction *)ACTION("player1"))->currentItem()) + { + case 0: + slotPlayer1(KG_INPUTTYPE_INTERACTIVE); + break; + case 1: + slotPlayer1(KG_INPUTTYPE_PROCESS); + break; + case 2: + slotPlayer1(KG_INPUTTYPE_REMOTE); + break; + } +} + +void LSkatApp::slotPlayer2By() +{ + switch(((KSelectAction *)ACTION("player2"))->currentItem()) + { + case 0: + slotPlayer2(KG_INPUTTYPE_INTERACTIVE); + break; + case 1: + slotPlayer2(KG_INPUTTYPE_PROCESS); + break; + case 2: + slotPlayer2(KG_INPUTTYPE_REMOTE); + break; + } +} + +void LSkatApp::slotPlayer1(KG_INPUTTYPE i) +{ + doc->SetPlayedBy(0,i); + if (doc->IsRunning()) + { + MakeInputDevice(0); + // New: Start computer when switched during game + if (mInput->QueryType(0)!=KG_INPUTTYPE_REMOTE && + doc->GetCurrentPlayer()==0 ) + { + mInput->Unlock(); + mInput->Next(doc->GetCurrentPlayer()); + } + } + doc->UpdateViews(UPDATE_STATUS); +} + +void LSkatApp::slotPlayer2(KG_INPUTTYPE i) +{ + doc->SetPlayedBy(1,i); + if (doc->IsRunning()) + { + MakeInputDevice(1); + // New: Start computer when switched during game + if (mInput->QueryType(0)!=KG_INPUTTYPE_REMOTE && + doc->GetCurrentPlayer()==1 ) + { + mInput->Unlock(); + mInput->Next(doc->GetCurrentPlayer()); + } + } + doc->UpdateViews(UPDATE_STATUS); +} + +void LSkatApp::slotOptionsNames() +{ + NameDlg *dlg=new NameDlg(this,QCString("Enter your name...")); + dlg->SetNames(doc->GetName(0),doc->GetName(1)); + if (dlg->exec()==QDialog::Accepted) + { + QString n1,n2; + dlg->GetNames(n1,n2); + doc->SetName(0,n1); + doc->SetName(1,n2); + doc->UpdateViews(UPDATE_STATUS); + slotStatusNames(); + } +} + +void LSkatApp::slotOptionsCardDeck() +{ + QString s1,s2; + int result; + s1=doc->GetDeckpath(); + s2=doc->GetCardpath(); + + result=KCardDialog::getCardDeck(s1,s2); + if (result==QDialog::Accepted) + { + doc->SetCardDeckPath(s1,s2); + doc->slotUpdateAllViews(0); + } +} + +void LSkatApp::slotLevel() +{ + int i=((KSelectAction *)ACTION("choose_level"))->currentItem(); + i++; // we start at 1 + doc->SetComputerLevel(i); + doc->UpdateViews(UPDATE_STATUS); + printf("Level set to %d\n",i); +} + +void LSkatApp::slotClearStatusMsg() +{ + slotStatusMsg(i18n("Ready")); +} + +void LSkatApp::slotStatusMsg(const QString &text) +{ + /////////////////////////////////////////////////////////////////// + // change status message permanently + statusBar()->clear(); + statusBar()->changeItem(text, ID_STATUS_MSG); +} + +void LSkatApp::slotStatusMover(const QString &text) +{ + /////////////////////////////////////////////////////////////////// + // change status mover permanently + statusBar()->clear(); + statusBar()->changeItem(text, ID_STATUS_MOVER); +} + + +void LSkatApp::slotStatusHelpMsg(const QString &text) +{ + /////////////////////////////////////////////////////////////////// + // change status message of whole statusbar temporary (text, msec) + statusBar()->message(text, 2000); +} + +/** Triggers the processmove timer */ +void LSkatApp::slotProcTimer(void) +{ + mInput->Unlock(); + mInput->Next(doc->GetCurrentPlayer()); + /* + printf("Delayed setting Next=%d ->%d\n", + doc->GetCurrentPlayer(),mInput->QueryNext()); + */ +} + +/** Set the names in the mover field */ +void LSkatApp::slotStatusNames(){ + + QString msg; + if (!doc->IsRunning()) msg=i18n("No game running"); + else + { + msg=i18n("%1 to move...").arg(doc->GetName(doc->GetCurrentPlayer())); + } + slotStatusMover(msg); +} + +void LSkatApp::NewGame() +{ + bool res; + // doc->SetIntro(0); + doc->NewGame(); + doc->slotUpdateAllViews(0); + res=MakeInputDevice(0); + if (!res) + { + KMessageBox::error(this, + i18n("Cannot start player 1. Maybe the network connection " + "failed or the computer player process file is not " + "found.")); + return ; + } + res=MakeInputDevice(1); + if (!res) + { + KMessageBox::error(this, + i18n("Cannot start player 2. Maybe the network connection " + "failed or the computer player process file is not " + "found.")); + return ; + } + // Remote game is started when receiving the start mesage .. not here! + if (mInput->QueryType(0)!=KG_INPUTTYPE_REMOTE && + mInput->QueryType(1)!=KG_INPUTTYPE_REMOTE ) + { + mInput->Unlock(); + mInput->Next(doc->GetStartPlayer()); + } + // Connected 0 and we are server + else if (mInput->QueryType(0)==KG_INPUTTYPE_REMOTE && + mInput->QueryStatus()>0 && doc->IsServer()) + { + mInput->Unlock(); + mInput->Next(doc->GetStartPlayer()); + } + // Connected 1 and we are server + else if (mInput->QueryType(1)==KG_INPUTTYPE_REMOTE && + mInput->QueryStatus()>1 && doc->IsServer()) + { + mInput->Unlock(); + mInput->Next(doc->GetStartPlayer()); + } + slotStatusNames(); +} + +bool LSkatApp::MakeInputDevice(int no) +{ + bool res=true; + KEMessage *msg; + disableAction("send_message"); + KG_INPUTTYPE type=doc->GetPlayedBy(no); + if (type==KG_INPUTTYPE_INTERACTIVE) + { + if (mInput->QueryType(no)!=type) + res=mInput->SetInputDevice(no,type); + } + else if (type==KG_INPUTTYPE_REMOTE) + { + QString host; + short port; + QString Name; + msg=new KEMessage; + PrepareGame(msg); + // Build new connection + if ( mInput->QueryType(no)!=type || mInput->QueryStatus(no)<=0) + { + OptionsNetwork(); + port=doc->QueryPort(); + host=doc->QueryHost(); + Name=doc->QueryName(); + msg->AddData(QCString("Port"),(short)port); + msg->AddData(QCString("IP"),(char *)(host.latin1())); + msg->AddData(QCString("Name"),(const char *)(Name.utf8())); + res=mInput->SetInputDevice(no,type,msg); + if (!res) + { + QProgressDialog *progress; + QString s; + int tim,j; + tim=10000; + if (!host.isEmpty()) + { + s=i18n("Remote connection to %1:%2...").arg(host).arg(port); + } + else + { + s=i18n("Offering remote connection on port %1...").arg(port); + } + progress=new QProgressDialog(s, i18n("Abort"), tim, this,0,true ); + progress->setCaption(i18n("Lieutenant Skat")); + for (j=0; j<tim; j++) + { + progress->setProgress( j ); + if ( progress->wasCancelled() ) break; + if (mInput->QueryStatus(no)>0) break; + usleep(100); + } + // progress.setProgress(tim); + delete progress; + } + } + else // we are already connected + { + // force the other one to be client + usleep(1000); + if (doc->IsServer()) + { + if (global_debug>10) + printf("We want theother one to be client\n"); + msg->AddData(QCString("Client"),(short)-1); // force client + mInput->SendMsg(msg,no); + } + // resp server + else + { + if (global_debug>10) + printf("We want theother one to be server\n"); + msg->AddData(QCString("Server"),(short)-1); // force server + mInput->SendMsg(msg,no); + } + } + delete msg; + if (mInput->QueryStatus(no)>0) + { + res=true; + } + else res=false; + enableAction("send_message"); + } + else if (type==KG_INPUTTYPE_PROCESS) + { + if (mInput->QueryType(no)!=type) + { + // QString path=kapp->dirs()->findExe(doc->QueryProcessName()); + QString path=doc->GetProcess(); + if (global_debug>5) + { + printf("Make Process %d\n",no); + printf("Exe file found: %s\n",path.latin1()); + } + if (path.isNull()) return false; + msg=new KEMessage; + msg->AddData(QCString("ProcessName"),(char *)(path.latin1())); + // msg->AddData("ProcessName",doc->QueryProcessName()); + res=mInput->SetInputDevice(no,KG_INPUTTYPE_PROCESS,msg); + delete msg; + } + + } + return res; +} + +void LSkatApp::OptionsNetwork() +{ + int res; + + NetworkDlg *dlg=new NetworkDlg(this,QCString("Configure a network game...")); + dlg->SetPort(doc->QueryPort()); + dlg->SetHost(doc->QueryHost()); + dlg->SetName(doc->QueryName()); + res=dlg->exec(); + doc->SetPort(dlg->QueryPort()); + doc->SetHost(dlg->QueryHost()); + doc->SetName(dlg->QueryName()); + delete dlg; +} + +void LSkatApp::slotPrepareProcessMove(KEMessage *msg) +{ + if (global_debug>3) + printf("+++ main should prepare process move\n"); + slotStatusMsg(i18n("Waiting for the computer to move...")); + + msg->AddData(QCString("Hint"),(short)0); + msg->AddData(QCString("Move"),(short)1); + + if (global_debug>3) + printf("PREPARE GAME in processmove\n"); + if (global_debug>1) + msg->AddData(QCString("KLogSendMsg"),"process.log"); + PrepareGame(msg); +} + +void LSkatApp::slotPrepareRemoteMove(KEMessage *) +{ + if (global_debug>3) + printf("+++ main should prepare remote move\n"); + slotStatusMsg(i18n("Waiting for remote player...")); +} + +void LSkatApp::slotPrepareInteractiveMove(KEMessage *) +{ + if (global_debug>3) + printf("+++ main should prepare interactive move\n"); + slotStatusMsg(i18n("Please make your move...")); +} + +void LSkatApp::slotReceiveInput(KEMessage *msg,int ) +{ + /* + if (global_debug>=0) + { + QStrList *keys=msg->QueryKeys(); + char *it; + printf(" MESSAGESIZE=%u\n",msg->QueryNumberOfKeys()); + for (it=keys->first();it!=0;it=keys->next()) + { + printf(" Key '%s' type=%d\n",it,msg->QueryType(it)); + } + } + */ + short move; + QString message; + short x,y,player; + bool remotesend; + int size; + + if (msg->HasKey(QCString("Debug"))) + { + char *debug; + msg->GetData(QCString("Debug"),debug,size); + printf("Received Debug: %d <%s>\n",size,debug); + } + if (msg->HasKey(QCString("ConnectionLost"))) + { + if (msg->GetData(QCString("ConnectionLost"),move)) + { + if (move==0) + { + message=i18n("Remote connection lost for player 1..."); + KMessageBox::information(this,message); + slotStatusMsg(message); + slotPlayer1(KG_INPUTTYPE_INTERACTIVE); + } + else + { + message=i18n("Remote connection lost for player 2..."); + KMessageBox::information(this,message); + slotStatusMsg(message); + slotPlayer2(KG_INPUTTYPE_INTERACTIVE); + } + } + } + if (msg->HasKey(QCString("Message"))) + { + char *p; + if (msg->GetData(QCString("Message"),p,size)) + { + message=i18n("Message from remote player:\n")+p; + KMessageBox::information(this,message); + if (global_debug>3) + printf("MESSAGE **** %s ****\n",message.latin1()); + } + } + if (msg->HasKey(QCString("EndGame"))) + { + KEMessage *msg2=new KEMessage; + + msg2->AddData(QCString("Terminate"),(short)1); + if (mInput->QueryType(0)==KG_INPUTTYPE_PROCESS) + mInput->SendMsg(msg2,0); + if (mInput->QueryType(1)==KG_INPUTTYPE_PROCESS) + mInput->SendMsg(msg2,1); + delete msg2; + + msg->GetData(QCString("EndGame"),move); + message=i18n("Remote player ended game..."); + KMessageBox::information(this,message); + slotStatusMsg(message); + + doc->EndGame(true); + doc->slotUpdateAllViews(0); + slotStatusNames(); + } + + if (msg->HasKey(QCString("Move"))) + { + slotStatusMsg(i18n("Ready")); + msg->GetData(QCString("Move"),player); + msg->GetData(QCString("MoveX"),x); + msg->GetData(QCString("MoveY"),y); + remotesend=msg->HasKey(QCString("RemoteMove")); + if (remotesend && doc->IsRemoteSwitch()) + player=1-player; + Move((int)x,(int)y,(int)player,remotesend); + } + // Client key is automatically added by message system !!! + if (msg->HasKey(QCString("Client"))) + { + if (global_debug>5) + printf("We are client and extracting game data now.\n"); + slotStatusMsg(i18n("You are network client...loading remote game...")); + doc->NewGame(); + ExtractGame(msg); + doc->SetServer(false); + doc->slotUpdateAllViews(0); + mInput->Unlock(); + mInput->Next(doc->GetStartPlayer()); + } + // Server key is automatically added by message system !!! + if (msg->HasKey(QCString("Server"))) + { + if (global_debug>5) + printf("We are server now.\n"); + slotStatusMsg(i18n("You are network server...")); + doc->SetServer(true); + mInput->Unlock(); + mInput->Next(doc->GetStartPlayer()); + } +} + +// Called after the move animation done +void LSkatApp::MoveFinished() +{ + int res=doc->MakeMove(); + QString ld,s; + if (res==2) // end game + { + doc->EvaluateGame(); + doc->slotUpdateAllViews(0); + // m->SetStatusBar(i18n("Game over"),3); + //doc->SwitchStartPlayer(); + doc->slotUpdateAllViews(0); + checkMenus(CheckFileMenu|CheckOptionsMenu); + } + else if (doc->IsRunning()) // continue game + { + // Delay fast playing of the computer ! + /* + printf("*** next=%d current=%d playedby=%d\n", + mInput->QueryNext(),doc->GetCurrentPlayer() , + doc->GetPlayedBy(doc->GetCurrentPlayer())); + */ + // Maybe we do not need to distinquish these two cases? + // Computer was last and is next + if (doc->GetPlayedBy(mInput->QueryNext())==KG_INPUTTYPE_PROCESS && + doc->GetPlayedBy(doc->GetCurrentPlayer())==KG_INPUTTYPE_PROCESS) + { + procTimer->start(1000,true); + } + // Computer is next + else if (doc->GetPlayedBy(doc->GetCurrentPlayer())==KG_INPUTTYPE_PROCESS) + { + procTimer->start(1000,true); + } + else + { + mInput->Unlock(); + mInput->Next(doc->GetCurrentPlayer()); + } + } + slotStatusNames(); +} + +void LSkatApp::Move(int x,int y,int player,bool remote) +{ + KEMessage *msg; + if (global_debug>1) + printf("Move of %d to x=%d y=%d\n",player,x,y); + if (x<0 || y<0 || x>7 || y>1 || player <0 || player>1) + { + KMessageBox::error(this, + i18n("Severe internal error. Move to illegal position.\n" + "Restart game and report bug to the developer.\n")); + return ; + } + int res=doc->PrepareMove(player,y*4+x); + if (res>0) + { + doc->InitMove(0,player,x,y); + if (mInput->QueryType()!=KG_INPUTTYPE_REMOTE && !remote ) + { + msg=new KEMessage; + if (doc->IsRemoteSwitch()) player=1-player; + msg->AddData(QCString("Move"),(short)player); + msg->AddData(QCString("MoveX"),(short)x); + msg->AddData(QCString("MoveY"),(short)y); + msg->AddData(QCString("RemoteMove"),(short)1); + if (mInput->QueryType(0)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,0); + if (mInput->QueryType(1)==KG_INPUTTYPE_REMOTE) + mInput->SendMsg(msg,1); + delete msg; + } + } + else if (res==-3) + { + KMessageBox::information(this, + i18n("This move would not follow the rulebook.\n" + "Better think again!\n")); + return ; + } + else if (res==-2) + { + KMessageBox::information(this,i18n("It is not your turn.\n")); + return ; + } + else + { + KMessageBox::information(this, i18n("This move is not possible.\n")); + return ; + } +} + +void LSkatApp::PrepareGame(KEMessage *msg) +{ + if (!msg) + return; + + msg->AddData(QCString("Cards"),(char *)doc->GetCardP(),NO_OF_CARDS*sizeof(int)); + msg->AddData(QCString("Startplayer"),(short)doc->GetStartPlayer()); + msg->AddData(QCString("CurrentPlayer"),(short)doc->GetCurrentPlayer()); + if (doc->GetPlayedBy(0)==KG_INPUTTYPE_REMOTE) + msg->AddData(QCString("RemoteIs"),(short)0); + else if (doc->GetPlayedBy(1)==KG_INPUTTYPE_REMOTE) + msg->AddData(QCString("RemoteIs"),(short)1); + msg->AddData(QCString("Trump"),(short)doc->GetTrump()); + // For computer player + // -1 or the current played card + msg->AddData(QCString("CurrentMove"),(short)doc->GetMove(doc->GetStartPlayer())); + msg->AddData(QCString("Height"),(char *)doc->GetCardHeightP(),NO_OF_CARDS/2*sizeof(int)); + msg->AddData(QCString("No"),(short)doc->GetMoveNo()); + msg->AddData(QCString("Sc1"),(short)doc->GetScore(0)); + msg->AddData(QCString("Sc2"),(short)doc->GetScore(1)); + msg->AddData(QCString("Level"),(short)doc->GetComputerLevel()); +} + +void LSkatApp::ExtractGame(KEMessage *msg) +{ + if (!msg) + return; + // Do we have to switch players? + bool switchit; + short remote; + msg->GetData(QCString("RemoteIs"),remote); + if (doc->GetPlayedBy(remote)==KG_INPUTTYPE_REMOTE) switchit=true; + else switchit=false; + + short start; + int i,size; + int *cards; + char *p; + short trump; + msg->GetData(QCString("Startplayer"),start); + msg->GetData(QCString("Cards"),p,size); + cards=(int *)p; + msg->GetData(QCString("Trump"),trump); + if (size!=NO_OF_CARDS*sizeof(int)) + { + printf("Error: Transmission of cards failed..wrong sizes\n"); + } + + doc->SetRemoteSwitch(switchit); + if (switchit) + { + start=1-start; + for (i=0;i<NO_OF_CARDS;i++) + { + if (i>=NO_OF_CARDS/2) + doc->SetCard(i-NO_OF_CARDS/2,cards[i]); + else + doc->SetCard(i+NO_OF_CARDS/2,cards[i]); + } + } + else + { + for (i=0;i<NO_OF_CARDS;i++) + { + doc->SetCard(i,cards[i]); + } + } + + doc->SetStartPlayer(start); + doc->SetCurrentPlayer(start); + doc->SetTrump((CCOLOUR)trump); +} + + +void LSkatApp::SetGrafix(QString s) +{ + mGrafix=s; +} + +#include "lskat.moc" diff --git a/lskat/lskat/lskat.h b/lskat/lskat/lskat.h new file mode 100644 index 00000000..b5686dde --- /dev/null +++ b/lskat/lskat/lskat.h @@ -0,0 +1,216 @@ +/*************************************************************************** + lskat.h - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef LSKAT_H +#define LSKAT_H + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +// include files for Qt +#include <qstrlist.h> + +// include files for KDE +#include <kapplication.h> +#include <kmainwindow.h> +#include <kaccel.h> + +#include "KEInput.h" +#include "KEMessage.h" +#include "KConnectTypes.h" + +typedef enum {Club=0,Spade=1,Heart=2,Diamond=3,Grand=4} CCOLOUR; +typedef enum {Ace=0,King=1,Queen=2,Jack=3,Ten=4,Nine=5,Eight=6,Seven=7} CCARD; +#define NO_OF_CARDS 32 +#define NO_OF_TILES 16 +#define NO_OF_TRUMPS 5 +//#define NO_OF_DECKS 6 +#define NO_OF_ANIM 24 + +// Window update codes +#define UPDATE_STATUS 1 + +extern int global_debug; +// forward declaration of the LSkat classes +class LSkatDoc; +class LSkatView; + +/** + * The base class for LSkat application windows. It sets up the main + * window and reads the config file as well as providing a menubar, toolbar + * and statusbar. An instance of LSkatView creates your center view, which is connected + * to the window's Doc object. + * LSkatApp reimplements the methods that KMainWindow provides for main window handling and supports + * full session management as well as keyboard accelerator configuration by using KAccel. + * @see KMainWindow + * @see KApplication + * @see KConfig + * @see KAccel + * + * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. + * @version KDevelop version 0.4 code generation + */ +class LSkatApp : public KMainWindow +{ + Q_OBJECT + + friend class LSkatView; + + public: + /** construtor of LSkatApp, calls all init functions to create the application. + */ + LSkatApp(); + ~LSkatApp(); + /** enables menuentries/toolbar items + */ + void enableAction(const char *); + /** disables menuentries/toolbar items + */ + void disableAction(const char *); + /** add a opened file to the recent file list and update recent_file_menu + */ + /** returns a pointer to the current document connected to the KMainWindow instance and is used by + * the View class to access the document object's methods + */ + LSkatDoc *getDocument() const; + void MoveFinished(); + void Move(int x,int y,int player,bool remote); + void SetGrafix(QString s); + + protected: + void NewGame(); + bool MakeInputDevice(int no); + void OptionsNetwork(); + // Puts all game data into a message + void PrepareGame(KEMessage *msg); + void ExtractGame(KEMessage *msg); + + /** initGUI creates the menubar and inserts the menupopups as well as creating the helpMenu. + * @see KApplication#getHelpMenu + */ + void initGUI(); + /** Checks all menus..usually done on init programm */ + void checkMenus(int menu=0); + + /** this creates the toolbars. + */ + /** sets up the statusbar for the main window by initialzing a statuslabel. + */ + void initStatusBar(); + /** initializes the document object of the main window that is connected to the view in initView(). + * @see initView(); + */ + void initDocument(); + /** creates the centerwidget of the KMainWindow instance and sets it as the view + */ + void initView(); + /** queryClose is called by KMainWindow on each closeEvent of a window. Against the + * default implementation (only returns true), this calles saveModified() on the document object to ask if the document shall + * be saved if Modified; on cancel the closeEvent is rejected. + * @see KMainWindow#queryClose + * @see KMainWindow#closeEvent + */ + virtual bool queryClose(); + /** queryExit is called by KMainWindow when the last window of the application is going to be closed during the closeEvent(). + * Against the default implementation that just returns true, this calls saveOptions() to save the settings of the last window's + * properties. + * @see KMainWindow#queryExit + * @see KMainWindow#closeEvent + */ + virtual bool queryExit(); + /** saves the window properties for each open window during session end to the session config file, including saving the currently + * opened file by a temporary filename provided by KApplication. + * @see KMainWindow#saveProperties + */ + virtual void saveProperties(KConfig *_cfg); + /** reads the session config file and restores the application's state including the last opened files and documents by reading the + * temporary files saved by saveProperties() + * @see KMainWindow#readProperties + */ + virtual void readProperties(KConfig *_cfg); + + public slots: + void slotPrepareProcessMove(KEMessage *msg); + void slotPrepareRemoteMove(KEMessage *msg); + void slotPrepareInteractiveMove(KEMessage *msg); + void slotReceiveInput(KEMessage *msg,int id); + + /** clears the document in the actual view to reuse it as the new document */ + void slotFileNew(); + /** asks for saving if the file is modified, then closes the actual file and window*/ + void slotFileEnd(); + /** closes all open windows by calling close() on each memberList item until the list is empty, then quits the application. + * If queryClose() returns false because the user canceled the saveModified() dialog, the closing breaks. + */ + void slotFileQuit(); + // clear all time stats + void slotFileStatistics(); + /** Msg to remote player */ + void slotFileMessage(); + /** changes the statusbar contents for the standard label permanently, used to indicate current actions. + * @param text the text that is displayed in the statusbar + */ + void slotStatusMsg(const QString &text); + void slotClearStatusMsg(); + /** changes the status message of the whole statusbar for two seconds, then restores the last status. This is used to display + * statusbar messages that give information about actions for toolbar icons and menuentries. + * @param text the text that is displayed in the statusbar + */ + void slotStatusHelpMsg(const QString &text); + /** Set the names in the mover field */ + void slotStatusNames(); + void slotStatusMover(const QString &text); + + void slotLevel(); + void slotStartplayer(); + void slotPlayer1(KG_INPUTTYPE i); + void slotPlayer2(KG_INPUTTYPE i); + void slotPlayer1By(); + void slotPlayer2By(); + void slotOptionsNames(); + void slotOptionsCardDeck(); + /** Triggers the process timer */ + void slotProcTimer(void); + +protected: // Protected attributes + + enum CheckFlags {All=0,CheckFileMenu=1,CheckOptionsMenu=2,CheckViewMenu=4}; + + /** */ + /** Counts the time in the status bar */ + QTimer * procTimer; + KEInput *mInput; + QString mGrafix; + + private: + /** contains the recently used filenames */ + QStrList recentFiles; + + /** the configuration object of the application */ + KConfig *config; + + LSkatView *view; + /** doc represents your actual document and is created only once. It keeps + * information such as filename and does the serialization of your files. + */ + LSkatDoc *doc; +}; + +#endif // LSKAT_H + diff --git a/lskat/lskat/lskatdoc.cpp b/lskat/lskat/lskatdoc.cpp new file mode 100644 index 00000000..8da62ea4 --- /dev/null +++ b/lskat/lskat/lskatdoc.cpp @@ -0,0 +1,817 @@ +/*************************************************************************** + lskatdoc.cpp - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for Qt +#include <qdir.h> +#include <qfileinfo.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <pwd.h> +#include <sys/types.h> + + +// include files for KDE +#include <klocale.h> + +// application specific includes +#include "lskatdoc.h" +#include "lskat.h" +#include "lskatview.h" +#include <kcarddialog.h> + +QPtrList<LSkatView> *LSkatDoc::pViewList = 0L; + +LSkatDoc::LSkatDoc(QWidget *parent, const char *name) : QObject(parent, name) +{ + int i; + if(!pViewList) + { + pViewList = new QPtrList<LSkatView>(); + } + + pViewList->setAutoDelete(true); + + isrunning=0; + wasgame=false; + initrandom(); + // Allow translation of playernames + /* + names[0]=i18n("Alice"); + names[1]=i18n("Bob"); + */ + + for (i=0;i<14;i++) cardvalues[i]=0; + cardvalues[(int)Ace]=11; + cardvalues[(int)Ten]=10; + cardvalues[(int)King]=4; + cardvalues[(int)Queen]=3; + cardvalues[(int)Jack]=2; + + /* + computerlevel=2; + playedby[1]=KG_INPUTTYPE_INTERACTIVE; + playedby[0]=KG_INPUTTYPE_PROCESS; + // playedby[1]=KG_INPUTTYPE_INTERACTIVE; + */ + + + isintro=1; + server=false; + port=7432; + host=""; + Name=""; + remoteswitch=false; + + + ClearStats(); +} + +LSkatDoc::~LSkatDoc() +{ +} + +void LSkatDoc::addView(LSkatView *view) +{ + pViewList->append(view); +} + +void LSkatDoc::removeView(LSkatView *view) +{ + pViewList->remove(view); +} + +void LSkatDoc::setAbsFilePath(const QString &filename) +{ + absFilePath=filename; +} + +const QString &LSkatDoc::getAbsFilePath() const +{ + return absFilePath; +} + +void LSkatDoc::setTitle(const QString &_t) +{ + title=_t; +} + +const QString &LSkatDoc::getTitle() const +{ + return title; +} + +void LSkatDoc::InitMove(LSkatView *sender,int player,int x,int y) +{ + LSkatView *w; + if(pViewList) + { + for(w=pViewList->first(); w!=0; w=pViewList->next()) + { + if(w!=sender) w->InitMove(player,x,y); + } + } + +} +void LSkatDoc::slotUpdateAllViews(LSkatView *sender) +{ + LSkatView *w; + if(pViewList) + { + for(w=pViewList->first(); w!=0; w=pViewList->next()) + { + if(w!=sender) + w->repaint(); + } + } +} +void LSkatDoc::UpdateViews(int mode) +{ + LSkatView *w; + if (IsIntro()) return ; + if(pViewList) + { + for(w=pViewList->first(); w!=0; w=pViewList->next()) + { + if (mode & UPDATE_STATUS) w->updateStatus(); + } + } +} + +bool LSkatDoc::saveModified() +{ + return true; +} + +void LSkatDoc::closeDocument() +{ + deleteContents(); +} + +bool LSkatDoc::newDocument(KConfig * /*config*/,QString path) +{ + int res; + modified=false; + absFilePath=QDir::homeDirPath(); + title=i18n("Untitled"); + if (global_debug>1) printf("path=%s\n",path.latin1()); + res=LoadBitmap(path); + if (res==0) return false; + return true; +} + +bool LSkatDoc::LoadGrafix(QString path) +{ + int res; + res=LoadCards(cardPath); + if (res==0) return false; + res=LoadDeck(deckPath); + if (res==0) return false; + return true; +} + +bool LSkatDoc::SetCardDeckPath(QString deck,QString card) +{ + bool update=false; + if (!deck.isNull() && deck!=deckPath) + { + update=true; + deckPath=deck; + LoadDeck(deckPath); + } + if (!card.isNull() && card!=cardPath) + { + update=true; + cardPath=card; + LoadCards(cardPath); + } + return update; +} + +bool LSkatDoc::openDocument(const QString &filename, const char * /*format*/ /*=0*/) +{ + QFileInfo fileInfo(filename); + title=fileInfo.fileName(); + absFilePath=fileInfo.absFilePath(); + ///////////////////////////////////////////////// + // TODO: Add your document opening code here + ///////////////////////////////////////////////// + + modified=false; + return true; +} + +bool LSkatDoc::saveDocument(const QString & /*filename*/, const char * /*format*/ /*=0*/) +{ + ///////////////////////////////////////////////// + // TODO: Add your document saving code here + ///////////////////////////////////////////////// + + modified=false; + return true; +} + +void LSkatDoc::deleteContents() +{ + ///////////////////////////////////////////////// + // TODO: Add implementation to delete the document contents + ///////////////////////////////////////////////// + +} + +// Called after game ends..give points to players +void LSkatDoc::EvaluateGame() +{ + if (score[0]+score[1]!=120) + { + printf("Warning: Score does not end up to 120\n"); + } + stat_games[0]++; + stat_games[1]++; + if (score[0]==score[1]) // drawn + { + stat_points[0]++; + stat_points[1]++; + } + else if (score[0]>score[1]) + { + stat_won[0]++; + stat_points[0]+=2; + if (score[0]>=90) stat_points[0]++; // Schneider + if (score[0]>=120) stat_points[0]++; // SChwarz + } + else + { + stat_won[1]++; + stat_points[1]+=2; + if (score[1]>=90) stat_points[1]++; // Schneider + if (score[1]>=120) stat_points[1]++; // SChwarz + } +} + +void LSkatDoc::EndGame(bool aborted) +{ + if (aborted) + { + stat_brk[0]++; + stat_brk[1]++; + } + else + { + startplayer=1-began_game; + } + isrunning=0; + wasgame=true; +} + +void LSkatDoc::NewGame() +{ + int i,r; + int num[NO_OF_CARDS]; + + isintro=0; + + began_game=startplayer; + for (i=0;i<NO_OF_TILES;i++) + { + cardheight[i]=2; + } + trump=(CCOLOUR)(random(4)); + if (global_debug>5) printf("Trump=%d\n",trump); + if (random(8)==0) trump=Grand; // grand + + // Fast drawing of random cards + for (i=0;i<NO_OF_CARDS;i++) + { + num[i]=i; + } + for (i=0;i<NO_OF_CARDS;i++) + { + r=random(NO_OF_CARDS-i); // cards available 32-i (+1) + card[i]=num[r]; + num[r]=num[NO_OF_CARDS-i-1]; // shift numbers + } + isrunning=1; + movestatus=-1; + currentplayer=startplayer; + laststartplayer=-1; + moveno=0; + computerscore=0; + lock=false; + for (i=0;i<2;i++) + { + score[i]=0; + curmove[i]=-1; + } +} + +int LSkatDoc::GetMove(int no) {return curmove[no];} + +CCOLOUR LSkatDoc::GetTrump() +{ + return trump; +} +void LSkatDoc::SetTrump(CCOLOUR i) +{ + trump=i; +} + +// pos=0..7, height=2..1..(0 no card left), player=0..1 +int LSkatDoc::GetCard(int player, int pos,int height) +{ + int i; + if (height==0) return -1; + height=2-height; + + i=NO_OF_TILES*player+8*height+pos; + return card[i]; +} + +// pos=0..7, player=0..1 +int LSkatDoc::GetHeight(int player, int pos) +{ + int i; + i=8*player+pos; + return cardheight[i]; +} +// pos=0..7, player=0..1 +void LSkatDoc::SetHeight(int player, int pos,int h) +{ + int i; + i=8*player+pos; + cardheight[i]=h; +} + + +int LSkatDoc::random(int max) +{ +double value; +int r; + r=rand(); + value=(double)((double)r*(double)max)/(double)RAND_MAX; + return (int)value; +} + +void LSkatDoc::initrandom() +{ + srand( (unsigned)time( NULL ) ); // randomize +} + +bool LSkatDoc::IsRunning() {return isrunning;} + +bool LSkatDoc::LegalMove(int p1, int p2) +{ + CCOLOUR col1,col2,col3; + CCARD card1,card2,card3; + card1=(CCARD)((p1)/4); + col1=(CCOLOUR)((p1)%4); + card2=(CCARD)((p2)/4); + col2=(CCOLOUR)((p2)%4); + + // force trump colour + if (card1==Jack) col1=trump; + if (card2==Jack) col2=trump; + + // same colour always ok + if (col1==col2) return true; + + // Search for same colour + bool flag=true; + for (int i=0;i<8;i++) + { + int h,c; + h=GetHeight(1-startplayer,i); + if (h==0) continue; + c=GetCard(1-startplayer,i,h); + card3=(CCARD)((c)/4); + col3=(CCOLOUR)((c)%4); + if (card3==Jack) col3=trump; + + if (col3==col1) + { + flag=false; + break; + } + } + if (flag) return true; + + return false; +} + +int LSkatDoc::PrepareMove(int player,int pos) +{ + int h,card; + h=GetHeight(player,pos); + if (h==0) return -1; // not possible + if (player!=currentplayer) return -2; // wrong player + + card=GetCard(player,pos,h); + + // New round + if (currentplayer==startplayer) + { + curmove[0]=-1; + curmove[1]=-1; + } + else + { + if (!LegalMove(curmove[startplayer],card)) + { + printf("Illegal move\n"); + return -3; + } + } + lock=true; + + movestatus=card; + SetHeight(player,pos,h-1); + return 1; +} +int LSkatDoc::MakeMove() +{ + lock=false; + curmove[currentplayer]=movestatus; + if (currentplayer==startplayer) + { + moveno++; + currentplayer=1-startplayer; + } + else + { + laststartplayer=startplayer; + + if (WonMove(curmove[startplayer],curmove[1-startplayer])) + { + // switch startplayer + startplayer=1-startplayer; + } + else + { + } + currentplayer=startplayer; + score[startplayer]+=CardValue(curmove[0]); + score[startplayer]+=CardValue(curmove[1]); + if (moveno==NO_OF_TILES) + { + EndGame(false); + return 2; + } + } + movestatus=-1; + return 1; +} +int LSkatDoc::CardValue(int card) +{ + int card1; + + card1=card/4; + return cardvalues[card1]; +} + +int LSkatDoc::WonMove(int c1,int c2) +{ + CCOLOUR col1,col2; + CCARD card1,card2; + + card1=(CCARD)((c1)/4); + col1=(CCOLOUR)((c1)%4); + card2=(CCARD)((c2)/4); + col2=(CCOLOUR)((c2)%4); + + // Two jacks + if (card1==Jack && card2==Jack) + { + if (col1<col2) return 0; + else return 1; + } + // One Jack wins always + if (card1==Jack) return 0; + if (card2==Jack) return 1; + + // higher one wins if same colour + if (col1==col2) + { + if (card1==Ten) + { + if (card2==Ace) return 1; + else return 0; + } + if (card2==Ten) + { + if (card1==Ace) return 0; + return 1; + } + + if ((int)card1<(int)card2) return 0; + return 1; + } + // trump wins + if (col1==trump) return 0; + if (col2==trump) return 1; + + // first one wins + return 0; + +} + +int LSkatDoc::GetMoveStatus() {return movestatus;} +void LSkatDoc::SetMoveStatus(int i) { movestatus=i; } +int LSkatDoc::GetCurrentPlayer() {return currentplayer;} +void LSkatDoc::SetCurrentPlayer(int i) {currentplayer=i;} +int LSkatDoc::GetStartPlayer() {return startplayer;} +void LSkatDoc::SetStartPlayer(int i) {startplayer=i;} + +void LSkatDoc::SetName(int no, QString n) { names[no]=n; } +QString LSkatDoc::GetName(int no) {return names[no];} +int LSkatDoc::GetScore(int no) {return score[no];} + +int LSkatDoc::GetMoveNo() {return moveno;} +/* +void LSkatDoc::SetDeckNo(int no) {deckno=no;} +int LSkatDoc::GetDeckNo() {return deckno;} +*/ + + +int LSkatDoc::GetLastStartPlayer() {return laststartplayer;} + +KG_INPUTTYPE LSkatDoc::GetPlayedBy(int no) {return playedby[no];} +void LSkatDoc::SetPlayedBy(int no,KG_INPUTTYPE type) {playedby[no]=type;} +int LSkatDoc::GetComputerLevel() {return computerlevel;} +void LSkatDoc::SetComputerLevel(int lev) {computerlevel=lev;} + +void LSkatDoc::SetComputerScore(int sc) {computerscore=sc;} +int LSkatDoc::GetComputerScore() {return computerscore;} +void LSkatDoc::SetLock() {lock=true;} +void LSkatDoc::ReleaseLock() {lock=false;} +bool LSkatDoc::IsLocked() {return lock;} +bool LSkatDoc::IsIntro() {return isintro;} +bool LSkatDoc::WasRunning() {return wasgame;} +void LSkatDoc::SetIntro(bool b) {isintro=b;} + +int LSkatDoc::LoadBitmap(QString path) +{ + int i; + QString buf; + if (global_debug>5) printf("Loading bitmaps\n"); + for (i=0;i<NO_OF_TRUMPS;i++) + { + buf.sprintf("%st%d.png",path.latin1(),i+1); + if(!mPixTrump[i].load(buf)) + { + printf("Fatal error: bitmap %s not found \n",buf.latin1()); + } + } + + + for (i=0;i<3;i++) + { + buf.sprintf("%stype%d.png",path.latin1(),i+1); + if (!mPixType[i].load(buf)) + { + printf("Fatal error: bitmap %s not found \n",buf.latin1()); + } + } + + buf.sprintf("%sbackground.png",path.latin1()); + + mPixBackground.load(buf); + if (!mPixBackground.load(buf)) + { + printf("Fatal error: bitmap %s not found \n",buf.latin1()); + } + + for (i=0;i<NO_OF_ANIM;i++) + { + buf.sprintf("%s4000%02d.png",path.latin1(),i); + if(!mPixAnim[i].load(buf)) + { + printf("Fatal error: bitmap %s not found \n",buf.latin1()); + } + } + return 1; +} + + +int LSkatDoc::LoadCards(QString path) +{ + QString buf; + for (int i=0;i<NO_OF_CARDS;i++) + { + buf.sprintf("%s%d.png",path.latin1(),i+1); + if(!mPixCard[i].load(buf)) + { + printf("Fatal error: bitmap %s not found \n",buf.latin1()); + return 0; + } + } + cardsize=mPixCard[0].size(); + return 1; +} + +int LSkatDoc::LoadDeck(QString path) +{ + if (!mPixDeck.load(path))return 0; + return 1; +} + +void LSkatDoc::SetInputHandler(KEInput *i) +{ + inputHandler=i; +} +KEInput *LSkatDoc::QueryInputHandler() +{ + return inputHandler; +} + +int LSkatDoc::SwitchStartPlayer() +{ + startplayer=1-startplayer; + return startplayer; +} + +bool LSkatDoc::IsServer() +{ + return server; +} +void LSkatDoc::SetServer(bool b) +{ + server=b; +} +void LSkatDoc::SetHost(QString h) +{ + host=h; +} +void LSkatDoc::SetName(const QString& n) +{ + Name=n; +} +void LSkatDoc::SetPort(short p) +{ + port=p; +} +QString LSkatDoc::QueryHost() +{ + return host; +} +short LSkatDoc::QueryPort() +{ + return port; +} +QString LSkatDoc::QueryName() const +{ + return Name; +} +int *LSkatDoc::GetCardP() +{ + return card; +} +int *LSkatDoc::GetCardHeightP() +{ + return cardheight; +} + +void LSkatDoc::SetCard(int no,int c) +{ + card[no]=c; +} +void LSkatDoc::SetRemoteSwitch(bool b) +{ + remoteswitch=b; +} +bool LSkatDoc::IsRemoteSwitch() +{ + return remoteswitch; +} + +int LSkatDoc::GetStatWon(int no) +{ + return stat_won[no]; +} +int LSkatDoc::GetStatGames(int no) +{ + return stat_games[no]; +} +int LSkatDoc::GetStatAborted(int no) +{ + return stat_brk[no]; +} +int LSkatDoc::GetStatPoints(int no) +{ + return stat_points[no]; +} + +QString LSkatDoc::GetProcess() +{ + return procfile; +} + +void LSkatDoc::ClearStats() +{ + for (int j=0;j<2;j++) + { + stat_won[j]=0; + stat_points[j]=0; + stat_games[j]=0; + stat_brk[j]=0; + } +} +void LSkatDoc::ReadConfig(KConfig *config) +{ + KConfig emailCfg( "emaildefaults", true ); + emailCfg.setGroup( "UserInfo" ); + QString name = emailCfg.readEntry( "FullName" ); + if ( name.isEmpty() ) + { + struct passwd *pw = getpwuid( getuid() ); + if ( pw ) + name = QString::fromLocal8Bit( pw->pw_gecos ); + } + + config->setGroup("Parameter"); + host=config->readEntry("host"); + port=(unsigned short)config->readNumEntry("port",7432); + procfile=config->readEntry("process",QCString("lskatproc")); + Name=config->readEntry("gamename"); + names[0]=config->readEntry("Name1",i18n("Alice")); + // names[1]=config->readEntry("Name2",i18n("Bob")); + names[1]=config->readEntry("Name2", name.isEmpty() ? i18n("Bob") : name); + + + // This is for debug and testing as you can run it from the CVS without + // installing the carddecks ! + // For the release version you can remove the aruments to the following two + // functions !!!! + cardPath=config->readPathEntry("cardpath", KCardDialog::getDefaultCardDir()); + deckPath=config->readPathEntry("deckpath", KCardDialog::getDefaultDeck()); + + // Debug only + if (global_debug>3) + printf("cardPath=%s\ndeckPath=%s\n",cardPath.latin1(),deckPath.latin1()); + + startplayer=config->readNumEntry("Startplayer",0); + if (startplayer>1 || startplayer<0) startplayer=0; + began_game=startplayer; + computerlevel=config->readNumEntry("Level",2); + playedby[0]=(KG_INPUTTYPE)config->readNumEntry("Player1", + (int)KG_INPUTTYPE_PROCESS); + playedby[1]=(KG_INPUTTYPE)config->readNumEntry("Player2", + (int)KG_INPUTTYPE_INTERACTIVE); + + stat_won[0]=config->readNumEntry("Stat1W",0); + stat_won[1]=config->readNumEntry("Stat2W",0); + stat_brk[0]=config->readNumEntry("Stat1B",0); + stat_brk[1]=config->readNumEntry("Stat2B",0); + stat_points[0]=config->readNumEntry("Stat1P",0); + stat_points[1]=config->readNumEntry("Stat2P",0); + stat_games[0]=config->readNumEntry("Stat1G",0); + stat_games[1]=config->readNumEntry("Stat2G",0); +} + +/** write config file */ +void LSkatDoc::WriteConfig(KConfig *config) +{ + config->setGroup("Parameter"); + config->writeEntry("host",host); + config->writeEntry("port",port); + config->writeEntry("process",procfile); + config->writePathEntry("tmppath",picpath); + config->writeEntry("delpath",delpath); + config->writeEntry("Name1",names[0]); + config->writeEntry("Name2",names[1]); + config->writeEntry("gamename",Name); + + config->writeEntry("Startplayer",startplayer); + config->writeEntry("Level",computerlevel); + config->writeEntry("Player1",int(playedby[0])); + config->writeEntry("Player2",int(playedby[1])); + + config->writeEntry("Stat1W",stat_won[0]); + config->writeEntry("Stat2W",stat_won[1]); + config->writeEntry("Stat1B",stat_brk[0]); + config->writeEntry("Stat2B",stat_brk[1]); + config->writeEntry("Stat1P",stat_points[0]); + config->writeEntry("Stat2P",stat_points[1]); + config->writeEntry("Stat1G",stat_games[0]); + config->writeEntry("Stat2G",stat_games[1]); + + config->writePathEntry("cardpath",cardPath); + config->writePathEntry("deckpath",deckPath); + + config->sync(); +} + +#include "lskatdoc.moc" diff --git a/lskat/lskat/lskatdoc.h b/lskat/lskat/lskatdoc.h new file mode 100644 index 00000000..1b880360 --- /dev/null +++ b/lskat/lskat/lskatdoc.h @@ -0,0 +1,235 @@ +/*************************************************************************** + lskatdoc.h - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef LSKATDOC_H +#define LSKATDOC_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +// include files for QT +#include <qobject.h> +#include <qstring.h> +#include <qptrlist.h> + +#include <kconfig.h> +#include "lskat.h" +#include "KEInput.h" + +// forward declaration of the LSkat classes +class LSkatView; + +/** LSkatDoc provides a document object for a document-view model. + * + * The LSkatDoc class provides a document object that can be used in conjunction with the classes LSkatApp and LSkatView + * to create a document-view model for standard KDE applications based on KApplication and KTMainWindow. Thereby, the document object + * is created by the LSkatApp instance and contains the document structure with the according methods for manipulation of the document + * data by LSkatView objects. Also, LSkatDoc contains the methods for serialization of the document data from and to files. + * + * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. + * @version KDevelop version 0.4 code generation + */ +class LSkatDoc : public QObject +{ + Q_OBJECT + public: + /** Constructor for the fileclass of the application */ + LSkatDoc(QWidget *parent, const char *name=0); + /** Destructor for the fileclass of the application */ + ~LSkatDoc(); + + /** adds a view to the document which represents the document contents. Usually this is your main view. */ + void addView(LSkatView *view); + /** removes a view from the list of currently connected views */ + void removeView(LSkatView *view); + /** sets the modified flag for the document after a modifying action on the view connected to the document.*/ + void setModified(bool _m=true){ modified=_m; } + /** returns if the document is modified or not. Use this to determine if your document needs saving by the user on closing.*/ + bool isModified(){ return modified; } + /** "save modified" - asks the user for saving if the document is modified */ + bool saveModified(); + /** deletes the document's contents */ + void deleteContents(); + /** initializes the document generally */ + bool newDocument(KConfig *config,QString path); + /** closes the acutal document */ + void closeDocument(); + /** loads the document by filename and format and emits the updateViews() signal */ + bool openDocument(const QString &filename, const char *format=0); + /** saves the document under filename and format.*/ + bool saveDocument(const QString &filename, const char *format=0); + /** sets the path to the file connected with the document */ + void setAbsFilePath(const QString &filename); + /** returns the pathname of the current document file*/ + const QString &getAbsFilePath() const; + /** sets the filename of the document */ + void setTitle(const QString &_t); + /** returns the title of the document */ + const QString &getTitle() const; + + int random(int max); + void NewGame(); + void EndGame(bool aborted=false); + void ClearStats(); + void EvaluateGame(); + int GetCard(int player,int pos,int height=0); + int GetHeight(int player, int pos); + void SetHeight(int player, int pos,int h); + int GetMove(int i); + int PrepareMove(int player,int pos); + int MakeMove(); + bool IsRunning(); + CCOLOUR GetTrump(); + void SetTrump(CCOLOUR i); + int GetMoveStatus(); + void SetMoveStatus(int i); + int GetCurrentPlayer(); + void SetCurrentPlayer(int i); + int GetStartPlayer(); + void SetStartPlayer(int i); + void SetName(int no,QString n); + QString GetName(int no); + int GetScore(int no); + int GetMoveNo(); + bool LegalMove(int card1, int card2); + int WonMove(int card1,int card2); + int CardValue(int card); + /* + int GetDeckNo(); + void SetDeckNo(int no); + */ + int GetLastStartPlayer(); + KG_INPUTTYPE GetPlayedBy(int no); + void SetPlayedBy(int no,KG_INPUTTYPE type); + int GetComputerLevel(); + void SetComputerLevel(int lev); + void SetComputerScore(int sc); + int GetComputerScore(); + void SetLock(); + void ReleaseLock(); + bool IsLocked(); + bool IsIntro(); + bool WasRunning(); + void SetIntro(bool b); + + // Stats + int GetStatWon(int no); + int GetStatGames(int no); + int GetStatAborted(int no); + int GetStatPoints(int no); + + void WriteConfig(KConfig *config); + void ReadConfig(KConfig *config); + + void SetInputHandler(KEInput *i); + KEInput *QueryInputHandler(); + void InitMove(LSkatView *sender,int player,int x,int y); + int SwitchStartPlayer(); + void UpdateViews(int mode); + bool IsServer(); + void SetServer(bool b); + void SetHost(QString h); + void SetName(const QString& n); + void SetPort(short p); + QString QueryHost(); + short QueryPort(); + QString QueryName() const; + // Only for fast remote access + int *GetCardP(); + int *GetCardHeightP(); + void SetCard(int i,int c); + bool IsRemoteSwitch(); + void SetRemoteSwitch(bool b); + QString GetProcess(); + int LoadCards(QString path); + int LoadDeck(QString path); + bool SetCardDeckPath(QString deck,QString card); + QString GetDeckpath() {return deckPath;} + QString GetCardpath() {return cardPath;} + bool LoadGrafix(QString path); + + protected: + void initrandom(); + int LoadBitmap(QString path); + +public: + QPixmap mPixCard[NO_OF_CARDS]; + QPixmap mPixTrump[NO_OF_TRUMPS]; + QPixmap mPixDeck; + QPixmap mPixBackground; + QSize cardsize; + QPixmap mPixType[3]; + QPixmap mPixAnim[NO_OF_ANIM]; + + private: + QString procfile; + QString picpath; + int delpath; + bool remoteswitch; + KEInput *inputHandler; + short port; + QString host; + QString Name; + bool server; + bool lock; + int startplayer; + int cardheight[16]; + int card[NO_OF_CARDS]; + int curmove[2]; + int moveno; + int isrunning; + bool isintro; + bool wasgame; + int movestatus; + int currentplayer; + CCOLOUR trump; + QString names[2]; + int score[2]; + int laststartplayer; + int began_game; + + KG_INPUTTYPE playedby[2]; + int computerlevel; + int computerscore; + + int stat_won[2]; // how many wins + int stat_points[2]; // how many points + int stat_games[2]; // how many games + int stat_brk[2]; // how many games aborted + + int cardvalues[14]; + + public slots: + /** calls repaint() on all views connected to the document object and is called by the view by which the document has been changed. + * As this view normally repaints itself, it is excluded from the paintEvent. + */ + void slotUpdateAllViews(LSkatView *sender); + + public: + /** the list of the views currently connected to the document */ + static QPtrList<LSkatView> *pViewList; + + private: + /** the modified flag of the current document */ + bool modified; + QString title; + QString absFilePath; + QString deckPath,cardPath; +}; + +#endif // LSKATDOC_H diff --git a/lskat/lskat/lskatui.rc b/lskat/lskat/lskatui.rc new file mode 100644 index 00000000..867f21c0 --- /dev/null +++ b/lskat/lskat/lskatui.rc @@ -0,0 +1,25 @@ +<!DOCTYPE kpartgui> +<kpartgui name="standard_containers" version="4"> +<MenuBar> + <Menu name="game" noMerge="1"><text>&Game</text> + <Action name="new_game"/> + <Separator /> + <Action name="end_game"/> + <Separator /> + <Action name="clear_statistics"/> + <Action name="send_message"/> + <Separator /> + <Action name="game_exit"/> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="show_statusbar" append="show_merge"/> + <Action name="startplayer" append="save_merge"/> + <Action name="player1" append="save_merge"/> + <Action name="player2" append="save_merge"/> + <Action name="choose_level" append="save_merge"/> + <Action name="select_carddeck" append="save_merge"/> + <Action name="change_names" append="save_merge"/> + </Menu> +</MenuBar> +<StatusBar/> +</kpartgui> diff --git a/lskat/lskat/lskatview.cpp b/lskat/lskat/lskatview.cpp new file mode 100644 index 00000000..c14d5cee --- /dev/null +++ b/lskat/lskat/lskatview.cpp @@ -0,0 +1,934 @@ +/*************************************************************************** + lskatview.cpp - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for Qt +#include <qpixmap.h> +#include <qcolor.h> +#include <qrect.h> +#include <qfontmetrics.h> +#include <qpoint.h> +#include <qstring.h> +#include <qpainter.h> +#include <qdatetime.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <klocale.h> +#include <math.h> +#include <stdio.h> +#include <kglobalsettings.h> + + +// application specific includes +#include "lskatview.h" +#include "lskatdoc.h" +#include "lskat.h" +#include "KEInput.h" +#include "KEMessage.h" + +#define CARD_X_OFFSET 32 // offset fromleft side +#define CARD_Y_OFFSET 5 // offset from top +#define CARD_X_SPACE 10 // space between cards +#define CARD_Y_SPACE 5 // space between cards +#define CARD_Y_BOARD_OFFSET 20 // space between players + +#define CARD_X_DECK 5 // shift deck and card +#define CARD_Y_DECK 3 // shift deck and card + +#define CARD_X_MOVE1 430 // positon of first moved card +#define CARD_Y_MOVE1 140 +#define CARD_X_MOVE2 450 // psoiton of second moved card +#define CARD_Y_MOVE2 190 + +// Probably most unnecessary and unused now +#define STATUS_X0 15 // pos in status win +#define STATUS_X1 60 +#define STATUS_X2 100 +#define STATUS_Y0 26 +#define STATUS_Y1 44 +#define STATUS_Y2 62 +#define STATUS_Y3 80 +#define STATUS_XT 128 +#define STATUS_YT 47 +#define STATUS_XTYPE 135 +#define STATUS_YTYPE 12 + +#define FINAL_XT1 15 +#define FINAL_XT2 -55 +#define FINAL_YT 15 + +#define FINAL_X0 140 +#define FINAL_Y0 35 + +#define FINAL_X1 110 +#define FINAL_Y1 90 + +#define FINAL_X2 130 +#define FINAL_Y2 65 + +#define FINAL_X3 30 +#define FINAL_X4 90 +#define FINAL_X5 170 +#define FINAL_X6 230 + +#define FINAL_Y3 95 +#define FINAL_Y4 125 + +#define FINAL_X7 30 +#define FINAL_Y7 155 + +//#define COL_STATUSLIGHT white +#define COL_STATUSBORDER black +//#define COL_STATUSFIELD QColor(192,192,192) +//#define COL_STATUSDARK QColor(65,65,65) +#define COL_STATUSFIELD QColor(130,130,255) +#define COL_STATUSDARK QColor(0,0,65) +#define COL_STATUSLIGHT QColor(210,210,255) +#define COL_PLAYER QColor(255,255,0) + +#define DLGBOXTITLE TITLE + +#define MOVECOUNTER 20 // so many moves when playing card +#define MOVE_TIMER_DELAY 7 // timer in milllisec default 7 + +LSkatView::LSkatView(QWidget *parent, const char *name) : QWidget(parent, name) +{ + setBackgroundMode(PaletteBase); + // setBackgroundMode(NoBackground); + + status_rect1=QRect(412,CARD_Y_OFFSET+5,180,95+25); + status_rect2=QRect(412,310,180,95+25); + status_rect3=QRect(CARD_X_OFFSET+60,CARD_Y_OFFSET+5+100+15+20, + 400,320-100-CARD_Y_OFFSET-30); + + setBackgroundColor(QColor(0,0,128)); + setBackgroundPixmap( getDocument()->mPixBackground ); + + moveTimer=new QTimer(this); + moveTimer->stop(); + connect(moveTimer,SIGNAL(timeout()),this,SLOT(moveTimerReady())); + + introcnt=0; + introTimer=new QTimer(this); + introTimer->stop(); + connect(introTimer,SIGNAL(timeout()),this,SLOT(introTimerReady())); + introTimer->start(75,FALSE); + + for (int i=0;i<NO_OF_CARDS;i++) + { + introCards[i]=getDocument()->random(NO_OF_CARDS); + } +} + +// Access the document with the game data +LSkatDoc *LSkatView::getDocument() const +{ + LSkatApp *theApp=(LSkatApp *) parentWidget(); + return theApp->getDocument(); +} + +// draw a border around a rect +// p: Painter +// rect: The rect to draw a border +// offset: An offset to the rect to make it smaller +// width: The width of the border +// mode: 0: Light border, 1: dark border +void LSkatView::drawBorder(QPainter *p,QRect rect,int offset,int width,int mode) +{ +QPen graypen; +int i; +QPoint p1,p2; + + if (mode!=0 && mode!=1) return; + + p1=rect.topLeft(); + p2=rect.bottomRight(); + + if (mode==0) p->setPen(COL_STATUSLIGHT); + else if (mode==1) p->setPen(COL_STATUSDARK); + + for (i=0;i<width;i++) + { + p->moveTo(p1.x()+offset+i,p2.y()-offset-i); + p->lineTo(p1.x()+offset+i,p1.y()+offset+i); + p->lineTo(p2.x()-offset-i,p1.y()+offset+i); + } + if (mode==1) p->setPen(COL_STATUSLIGHT); + else if (mode==0) p->setPen(COL_STATUSDARK); + for (i=0;i<width;i++) + { + p->moveTo(p1.x()+offset+i,p2.y()-offset-i); + p->lineTo(p2.x()-offset-i,p2.y()-offset-i); + p->lineTo(p2.x()-offset-i,p1.y()+offset+i); + } +} + +// draw a move by animating the movment and turning of the +// card. This is called until the card reaches its final +// position +void LSkatView::drawMove(QPainter *p) +{ + int m1,m2; + int below; + QPoint point1,point2; + + m1=getDocument()->GetMove(0); + m2=getDocument()->GetMove(1); + point1=QPoint(CARD_X_MOVE1,CARD_Y_MOVE1); + point2=QPoint(CARD_X_MOVE2,CARD_Y_MOVE2); + + below=getDocument()->GetLastStartPlayer(); + if (below<0) below=getDocument()->GetStartPlayer(); + + if (below==0) + { + if (m1>=0) p->drawPixmap(point1,getDocument()->mPixCard[m1]); + if (m2>=0) p->drawPixmap(point2,getDocument()->mPixCard[m2]); + } + else + { + if (m2>=0) p->drawPixmap(point2,getDocument()->mPixCard[m2]); + if (m1>=0) p->drawPixmap(point1,getDocument()->mPixCard[m1]); + } + + int card; + QPoint point; + card=getDocument()->GetMoveStatus(); + if (card>=0) + { + + if (cardmoveunder>=0) + { + // turn new card + if ((double)cardmovecnt/(double)MOVECOUNTER>0.5) + { + QPixmap pix1(getDocument()->mPixCard[cardmoveunder]); + int wid=pix1.width(); + QWMatrix m; + m.scale(2.0*((double)cardmovecnt/(double)MOVECOUNTER-0.5),1.0); + pix1=pix1.xForm(m); + point=QPoint((wid-pix1.width())/2,0); + p->drawPixmap(cardorigin+point,pix1); + } + // turn deck + else + { + QPixmap pix1(getDocument()->mPixDeck); + int wid=pix1.width(); + QWMatrix m; + m.scale(1.0-2.0*((double)cardmovecnt/(double)MOVECOUNTER),1.0); + pix1=pix1.xForm(m); + point=QPoint((wid-pix1.width())/2,0); + p->drawPixmap(cardorigin+point,pix1); + } + } /* end turn card */ + + point=cardorigin+(cardend-cardorigin)*cardmovecnt/MOVECOUNTER; + p->drawPixmap(point,getDocument()->mPixCard[card]); + + } +} + +// Show the intro (Cards+Text) +// This is called repeatetly +void LSkatView::drawIntro(QPainter *p) +{ + int i,c1,c2,x,cnt,y,col,col2,col3,col4; + // The window width; + // int win_width = p->window().width(); + QPoint point,point1,p2; + QString s; + // Get a nice font + QFont font = KGlobalSettings::generalFont(); + font.setPointSize(48); + // Get the font info to determine text sizes + QFontMetrics fontMetrics(font); + + p->setFont(font); + + cnt=introcnt; + if (cnt>NO_OF_CARDS) cnt=NO_OF_CARDS; + + + i=0; + point=QPoint(20,20); + point1=QPoint(550,20); + + for (i=0;i<cnt;i++) + { + x=(int)((i+10)*5*sin(1.5*i*M_PI/(float)NO_OF_CARDS)); + c1=introCards[i]; + c2=introCards[(i+17)%NO_OF_CARDS]; + p2=QPoint(i*10+x, i*10); + p->drawPixmap(point+p2,getDocument()->mPixCard[c1]); + p2=QPoint(-i*10-x, i*10); + p->drawPixmap(point1+p2,getDocument()->mPixCard[c2]); + } + + // All text are positioned that they end up at x=310-textwidth/2 + // All texts are drawn twice with different colors to produce a shadow + col=255-8*i; + if (col<0) col=0; + col2=2*col/3; + col3=255-2*i; + col4=2*col3/3; + s=i18n("Lieutenant Skat"); + x=310-fontMetrics.width(s)/2; + y=-20+(int)(200.0*sin(0.5*M_PI/(float)NO_OF_CARDS*cnt)); + p->setPen(QColor(col4,col2,0)); + p->drawText(x-2,y+2,s); + + p->setPen(QColor(col3,col,0)); + p->drawText(x,y,s); + + s=i18n("for"); + y=270+(NO_OF_CARDS-cnt)*3; + x=-fontMetrics.width(s)/2+(int)(310.0*sin(0.5*M_PI/(float)NO_OF_CARDS*cnt)); + p->setPen(QColor(col4,col2,0)); + p->drawText(x-2,y+2,s); + + p->setPen(QColor(col3,col,0)); + p->drawText(x,y,s); + + s=i18n("K D E"); + y=350+(NO_OF_CARDS-cnt)*3; + // x=640-(int)(380.0*sin(0.5*M_PI/(float)NO_OF_CARDS*cnt)); + x=570-fontMetrics.width(s)/2-(int)(260.0*sin(0.5*M_PI/(float)NO_OF_CARDS*cnt)); + p->setPen(QColor(col4,col2,0)); + p->drawText(x-2,y+2,s); + + p->setPen(QColor(col3,col,0)); + p->drawText(x,y,s); +} + +// Draw all cards to create the game board +void LSkatView::drawDeck(QPainter *p) +{ + int x,y,card; + int player,pos,height; + QPoint point; + + for (y=0;y<4;y++) + { + if (y<2) player=0; + else player=1; + + for (x=0;x<4;x++) + { + pos=x+4*(y%2); + + point=calcCardPos(x,y); + if (getDocument()->IsRunning()) + { + height=getDocument()->GetHeight(player,pos); + card=getDocument()->GetCard(player,pos,height); + + + if (height==2) + p->drawPixmap(point-QPoint(CARD_X_DECK,CARD_Y_DECK),getDocument()->mPixDeck); + + if (cardmovecnt<1 || x!=cardmovex || y!=cardmovey) + { + if (height>0 ) p->drawPixmap(point,getDocument()->mPixCard[card]); + } + else + { + // moved to drawMove + // if (height>0 ) p->drawPixmap(point,getDocument()->mPixDeck); + } + } + else + { + p->drawPixmap(point,getDocument()->mPixDeck); + } + } + } +} +// Draw the winner field +void LSkatView::drawFinal(QPainter *p) +{ + int sc1,sc0,pt0,pt1; + //QPoint p1,p2; + int trump; + //QRect r; + QString ld; + int ts[10]; + + QFont font24 = KGlobalSettings::generalFont(); + font24.setPointSize(24); + QFont font14 = KGlobalSettings::generalFont(); + font14.setPointSize(13); + + //p1=status_rect3.topLeft(); + //p2=status_rect3.bottomRight(); + + sc0=getDocument()->GetScore(0); + sc1=getDocument()->GetScore(1); + + if (sc0>=120) pt0=4; + else if (sc0>=90) pt0=3; + else if (sc0>60) pt0=2; + else if (sc0==60) pt0=1; + else pt0=0; + if (sc1>=120) pt1=4; + else if (sc1>=90) pt1=3; + else if (sc1>60) pt1=2; + else if (sc1==60) pt1=1; + else pt1=0; + + + trump=getDocument()->GetTrump(); + + + + QString line1,line2,line3,line4,line5; + QString col1_3,col2_3,col3_3,col4_3; + QString col1_4,col2_4,col3_4,col4_4; + QRect sumrect; + QRect rect; + QRect brect1,brect2,brect3,brect4,brect5; + QRect brect1_3,brect2_3,brect3_3,brect4_3; + QRect brect1_4,brect2_4,brect3_4,brect4_4; + + // Calculate geometry + line1=i18n("Game over"); + rect=p->window(); + //rect1.moveBy(0,FINAL_Y0-24); + p->setFont(font24); + brect1=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line1); + //QRect wrect=p->window(); + sumrect=brect1; + + if (sc0+sc1!=120) // aborted + { + line2=i18n("Game was aborted - no winner"); + int hp=getDocument()->mPixTrump[trump].height()+5; + rect=QRect(0,hp>sumrect.height()?hp:sumrect.height(),p->window().width(),p->window().height()); + p->setFont(font14); + brect2=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line2); + sumrect|=brect2; + } + else + { + if (sc0==sc1) + { + line2=i18n(" Game is drawn"); + } + else if (sc0>sc1) + { + line2=i18n("Player 1 - %1 won ").arg(getDocument()->GetName(0)); + } + else + { + line2=i18n("Player 2 - %1 won ").arg(getDocument()->GetName(1)); + } + int hp=getDocument()->mPixTrump[trump].height()+5; + rect=QRect(0,hp>sumrect.height()?hp:sumrect.height(),p->window().width(),p->window().height()); + p->setFont(font14); + brect2=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line2); + sumrect|=brect2; + + p->setFont(font14); + col1_3=i18n("Score:"); + col1_4=QString(" "); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect1_3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col1_3); + ts[0]=brect1_3.width()+10; + + col2_3=getDocument()->GetName(0); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect2_3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col2_3); + + col2_4=getDocument()->GetName(1); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect2_4=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col2_4); + rect=brect2_3|brect2_4; + ts[1]=ts[0]+rect.width()+10; + + + col3_3.sprintf("%d",sc0); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect3_3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col3_3); + + col3_4.sprintf("%d",sc1); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect3_4=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col3_4); + rect=brect3_3|brect3_4; + ts[2]=ts[1]+rect.width()+30; + + col4_3=i18n("%1 points").arg(pt0); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect4_3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col4_3); + + col4_4=i18n("%1 points").arg(pt1); + rect=QRect(0,0,p->window().width(),p->window().height()); + brect4_4=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,col4_4); + + rect=brect4_3|brect4_4; + ts[3]=ts[2]+rect.width()+10; + ts[4]=0; + + line3=col1_3+QString("\t")+col2_3+QString("\t")+col3_3+QString("\t")+col4_3; + line4=col1_4+QString("\t")+col2_4+QString("\t")+col3_4+QString("\t")+col4_4; + brect3=QRect(sumrect.left(),sumrect.bottom()+10,ts[3],brect4_3.height()); + brect4=QRect(sumrect.left(),sumrect.bottom()+10+brect4_3.height()+6,ts[3],brect4_4.height()); + sumrect|=brect3; + sumrect|=brect4; + + + p->setFont(font14); + if (sc0>=120) + { + line5=i18n("%1 won to nil. Congratulations!").arg(getDocument()->GetName(0)); + rect=QRect(0,sumrect.height()+10,p->window().width(),p->window().height()); + brect5=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line5); + sumrect|=brect5; + } + else if (sc0>=90) + { + if (sc0==90) + line5=i18n("%1 won with 90 points. Super!").arg(getDocument()->GetName(0)); + else + line5=i18n("%1 won over 90 points. Super!").arg(getDocument()->GetName(0)); + rect=QRect(0,sumrect.height()+10,p->window().width(),p->window().height()); + brect5=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line5); + sumrect|=brect5; + } + if (sc1>=120) + { + line5=i18n("%1 won to nil. Congratulations!").arg(getDocument()->GetName(1)); + rect=QRect(0,sumrect.height()+10,p->window().width(),p->window().height()); + brect5=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line5); + sumrect|=brect5; + } + else if (sc1>=90) + { + if (sc1==90) + line5=i18n("%1 won with 90 points. Super!").arg(getDocument()->GetName(1)); + else + line5=i18n("%1 won over 90 points. Super!").arg(getDocument()->GetName(1)); + rect=QRect(0,sumrect.height()+10,p->window().width(),p->window().height()); + brect5=p->boundingRect(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line5); + sumrect|=brect5; + } + } + + + QPoint offset=QPoint(status_rect3.left()-sumrect.left(),status_rect3.top()); + sumrect.moveBy(offset.x(),offset.y()); + + // draw actual strings and symbols + QRect borderrect=QRect(sumrect.left()-20,sumrect.top()-20,sumrect.width()+40,sumrect.height()+40); + p->drawRect(borderrect); + drawBorder(p,borderrect,0,4,0); + drawBorder(p,borderrect,10,1,1); + + + p->setPen(black); + p->setFont(font24); + rect=sumrect; + rect.setTop(brect1.top()+offset.y()); + //brect1.moveBy(offset.x(),offset.y()); + p->drawText(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line1); + + p->setFont(font14); + p->setPen(COL_PLAYER); + rect=sumrect; + rect.setTop(brect2.top()+offset.y()); + //brect2.moveBy(offset.x(),offset.y()); + p->drawText(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line2); + + p->drawPixmap(sumrect.topLeft()+QPoint(-5,-5), getDocument()->mPixTrump[trump]); + p->drawPixmap(sumrect.topLeft()+QPoint(5,-5)+QPoint(sumrect.width()-getDocument()->mPixTrump[trump].width(),0), + getDocument()->mPixTrump[trump]); + + + if (!col1_3.isNull()) + { + p->setTabArray(ts); + p->setFont(font14); + p->setPen(Qt::black); + rect=sumrect; + rect.setTop(brect3.top()+offset.y()); + + // Workaround for the next line where the ExpandTab crashes!!! + drawTabText(p,rect,line3,ts); + // p->drawText(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop|Qt::ExpandTabs,line3); + rect=sumrect; + rect.setTop(brect4.top()+offset.y()); + // Workaround for the next line where the ExpandTab crashes!!! + drawTabText(p,rect,line4,ts); + // p->drawText(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop|Qt::ExpandTabs,line4); + } + if (!line5.isNull()) + { + p->setFont(font14); + p->setPen(Qt::black); + rect=sumrect; + rect.setTop(brect5.top()+offset.y()); + p->drawText(rect,Qt::AlignHCenter|Qt::SingleLine|Qt::AlignTop,line5); + } +} + +// This function is just a workaround for the QT function drawText +// with Qt::EXpandTAbs eanbled. For some strange reasons this crashes... +void LSkatView::drawTabText(QPainter *p,QRect rect,QString s,int *ts) +{ + int lcnt=0; + + // p->setPen(Qt::black); + // p->drawRect(rect); + while(s.length()>0 && (lcnt==0 || ts[lcnt-1]) ) + { + int lpos=s.find("\t"); + int rpos=s.length()-lpos-1; + if (lpos<0) + { + lpos=s.length(); + rpos=0; + } + QString tmp=s.left(lpos); + s=s.right(rpos); + QRect rect2=rect; + if (lcnt>0) + rect2.setLeft(rect.left()+ts[lcnt-1]); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,tmp); + lcnt++; + } +} + +// Draw the status field at the right side +void LSkatView::drawStatus(QPainter *p) +{ + QPoint p1,p2; + int trump; + QRect drawrect; + // For loop + QRect srect[2]; + srect[0]=status_rect1; + srect[1]=status_rect2; + + QFont font10 = KGlobalSettings::generalFont(); + font10.setPointSize(13); + p->setFont(font10); + + trump=getDocument()->GetTrump(); + + + // draw text + QString ld; + QString line1,line2,line3,line4,line2a,line2b,line2c; + QRect sumrect,rect,rect2,brect1,brect2,brect3,brect4; + QPoint pa; + + for (int pl=0;pl<2;pl++) + { + drawrect=QRect(srect[pl].left()+14,srect[pl].top()+14,srect[pl].width()-28,srect[pl].height()-28); + p1=drawrect.topLeft(); + p2=drawrect.bottomRight(); + + // Draw border and field + p->setPen(COL_STATUSBORDER); + p->setBrush(COL_STATUSFIELD); + p->drawRect(srect[pl]); + drawBorder(p,srect[pl],0,4,0); + drawBorder(p,srect[pl],10,1,1); + + + // Player pl ------------------- + // line1=QString(i18n("Player 1"))+QString(QCString(" - "))+getDocument()->GetName(0); + line1=getDocument()->GetName(pl); + brect1=p->boundingRect(drawrect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line1); + sumrect=brect1; + + if (getDocument()->IsRunning()) + { + // Geometry and strings + line2=i18n("Score:"); + rect=QRect(drawrect.left(),sumrect.bottom()+16,drawrect.width(),drawrect.height()-sumrect.height()); + brect2=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2); + sumrect|=brect2; + line3=i18n("Move:"); + rect=QRect(drawrect.left(),sumrect.bottom()+10,drawrect.width(),drawrect.height()-sumrect.height()); + brect3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line3); + sumrect|=brect3; + + rect=brect2|brect3; + rect.setWidth(rect.width()+10); + line2a.sprintf("%3d",getDocument()->GetScore(pl)); + line2b.sprintf("%3d",getDocument()->GetMoveNo()); + + // paint + if (getDocument()->GetStartPlayer()==pl) p->setPen(COL_PLAYER); + else p->setPen(black); + p->drawText(brect1,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line1); + p->setPen(black); + p->drawText(brect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2); + p->drawText(brect3,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line3); + rect2=QRect(brect2.left()+rect.width(),brect2.top(),drawrect.width()-brect2.width()-rect.width(),brect2.height()); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2a); + rect2=QRect(brect3.left()+rect.width(),brect3.top(),drawrect.width()-brect3.width()-rect.width(),brect3.height()); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2b); + + pa=QPoint(drawrect.width()-getDocument()->mPixTrump[trump].width(),drawrect.height()-getDocument()->mPixTrump[trump].height()); + if (getDocument()->GetStartPlayer()==pl) + p->drawPixmap(p1+pa+QPoint(3,3),getDocument()->mPixTrump[trump]); + + pa=QPoint(drawrect.width()-getDocument()->mPixType[getDocument()->GetPlayedBy(pl)-1].width(),0); + p->drawPixmap(p1+pa+QPoint(3,-3), getDocument()->mPixType[getDocument()->GetPlayedBy(pl)-1]); + } + else // draw all time score + { + // Geometry and strings + line2=i18n("Points:"); + rect=QRect(drawrect.left(),sumrect.bottom()+6,drawrect.width(),drawrect.height()-sumrect.height()); + brect2=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2); + sumrect|=brect2; + + line3=i18n("Won:"); + rect=QRect(drawrect.left(),sumrect.bottom()+6,drawrect.width(),drawrect.height()-sumrect.height()); + brect3=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line3); + sumrect|=brect3; + + line4=i18n("Games:"); + rect=QRect(drawrect.left(),sumrect.bottom()+6,drawrect.width(),drawrect.height()-sumrect.height()); + brect4=p->boundingRect(rect,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line4); + sumrect|=brect4; + + rect=brect2|brect3|brect4; + rect.setWidth(rect.width()+10); + line2a.sprintf("%d",getDocument()->GetStatPoints(pl)); + line2b.sprintf("%d",getDocument()->GetStatWon(pl)); + line2c.sprintf("%d",getDocument()->GetStatGames(pl)); + + // paint + p->setPen(COL_PLAYER); + p->drawText(brect1,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line1); + p->setPen(black); + p->drawText(brect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2); + p->drawText(brect3,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line3); + p->drawText(brect4,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line4); + rect2=QRect(brect2.left()+rect.width(),brect2.top(),drawrect.width()-brect2.width()-rect.width()+5,brect2.height()); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2a); + rect2=QRect(brect3.left()+rect.width(),brect3.top(),drawrect.width()-brect3.width()-rect.width()+5,brect3.height()); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2b); + rect2=QRect(brect4.left()+rect.width(),brect4.top(),drawrect.width()-brect4.width()-rect.width()+5,brect4.height()); + p->drawText(rect2,Qt::AlignLeft|Qt::SingleLine|Qt::AlignTop,line2c); + + pa=QPoint(drawrect.width()-getDocument()->mPixType[getDocument()->GetPlayedBy(pl)-1].width(),0); + p->drawPixmap(p1+pa+QPoint(3,-3), getDocument()->mPixType[getDocument()->GetPlayedBy(pl)-1]); + + } + + }// end pl +} + +// paint function +void LSkatView::Paint(QPainter *p) +{ + // If game is running + drawStatus(p); + drawDeck(p); + if (getDocument()->IsRunning()) + { + drawMove(p); + } + else if (getDocument()->WasRunning() && !getDocument()->IsIntro()) + { + drawFinal(p); + } +} + +// paint event +void LSkatView::paintEvent( QPaintEvent * e) +{ + if (getDocument()->IsIntro()) + { + QPixmap pm(this->rect().size()); + QPainter p; + QBrush brush; + p.begin(&pm,this); + brush.setPixmap( getDocument()->mPixBackground ); + p.fillRect(0,0,this->rect().width(),this->rect().height(),brush); + drawIntro(&p); + p.end(); + bitBlt(this,0,0,&pm); + } + else + { + QPainter paint( this ); + paint.setClipRect(e->rect()); + Paint( &paint ); + } +} + + +// x=0..4, y=0..4 +QPoint LSkatView::calcCardPos(int x,int y) +{ + QPoint point; + point=QPoint(CARD_X_OFFSET+x*(CARD_X_SPACE+getDocument()->cardsize.width()), + CARD_Y_OFFSET+y*(CARD_Y_SPACE+getDocument()->cardsize.height())); + if (y>=2) point+=QPoint(0,CARD_Y_BOARD_OFFSET); + point+=QPoint(CARD_X_DECK,CARD_Y_DECK); + return point; +} + +// mouse click event +void LSkatView::mousePressEvent( QMouseEvent *mouse ) +{ + if (mouse->button()!=LeftButton) return ; + if (!getDocument()->IsRunning()) return ; + + if (getDocument()->GetMoveStatus()!=-1) return ; + + QPoint point; + int mx,my,player; + + point=mouse->pos(); + point-=QPoint(CARD_X_OFFSET,CARD_Y_OFFSET); + if (point.y()>2*(getDocument()->cardsize.height()+CARD_Y_SPACE)) + { + point-=QPoint(0,CARD_Y_BOARD_OFFSET+2*(getDocument()->cardsize.height()+CARD_Y_SPACE)); + player=1; + } + else + { + player=0; + } + if (point.x()<0 || point.y()<0) return ; + mx=point.x()/(getDocument()->cardsize.width()+CARD_X_SPACE); + my=point.y()/(getDocument()->cardsize.height()+CARD_Y_SPACE); + if (mx>3 || my>1) return ; + + if (global_debug>10) + printf("Type=%d Next=%d player=%d\n", + getDocument()->QueryInputHandler()->QueryType(player), + getDocument()->QueryInputHandler()->QueryNext(),player); + if (getDocument()->QueryInputHandler()->IsInteractive(player) && + getDocument()->QueryInputHandler()->QueryNext()==player && + !getDocument()->IsLocked()) + { + KEMessage *msg=new KEMessage; + msg->AddData(QCString("Move"),(short)player); + msg->AddData(QCString("MoveX"),(short)mx); + msg->AddData(QCString("MoveY"),(short)my); + getDocument()->QueryInputHandler()->SetInput(msg); + delete msg; + } + else + { + QString m; + switch(getDocument()->random(4)) + { + case 0: + m=i18n("Hold on... the other player hasn't been yet..."); + break; + case 1: + m=i18n("Hold your horses..."); + break; + case 2: + m=i18n("Ah ah ah... only one go at a time..."); + break; + default: + m=i18n("Please wait... it is not your turn."); + } + KMessageBox::information(this,m); + } +} + + +void LSkatView::InitMove(int player,int mx,int my) +{ + cardmovex=mx; + cardmovey=my+2*player; + cardmoveunder=getDocument()->GetCard(player,mx+4*my,getDocument()->GetHeight(player,mx+4*my)); + introTimer->stop(); + moveTimer->start(MOVE_TIMER_DELAY,FALSE); + cardmovecnt=0; + cardorigin=calcCardPos(mx,my+2*player); + if (getDocument()->GetCurrentPlayer()==0) + cardend=QPoint(CARD_X_MOVE1,CARD_Y_MOVE1); + else cardend=QPoint(CARD_X_MOVE2,CARD_Y_MOVE2); + update(QRect( + cardorigin-QPoint(CARD_X_DECK,CARD_Y_DECK), + getDocument()->cardsize+QSize(CARD_X_DECK,CARD_Y_DECK))); + + QPoint point1=QPoint(CARD_X_MOVE1,CARD_Y_MOVE1); + QPoint point2=QPoint(CARD_X_MOVE2,CARD_Y_MOVE2); + update(QRect(point1,getDocument()->cardsize)); + update(QRect(point2,getDocument()->cardsize)); +} +void LSkatView::introTimerReady() +{ + if (!getDocument()->IsIntro()) + { + introTimer->stop(); + return ; + } + introcnt++; + if (introcnt>NO_OF_CARDS*4) + { + introcnt=0; + for (int i=0;i<NO_OF_CARDS;i++) + { + introCards[i]=getDocument()->random(NO_OF_CARDS); + } + } + else if (introcnt<NO_OF_CARDS) + { + repaint(false); + } +} + +void LSkatView::moveTimerReady() +{ + QPoint pos; + QString ld,s; + if (cardmovecnt>=MOVECOUNTER) + { + LSkatApp *m=(LSkatApp *) parentWidget(); + moveTimer->stop(); + cardmovecnt=0; + update(QRect(cardend,getDocument()->cardsize)); + update(QRect(cardorigin,getDocument()->cardsize)); + update(status_rect1); + update(status_rect2); + m->MoveFinished(); + + } + else + { + pos=cardorigin+(cardend-cardorigin)*cardmovecnt/MOVECOUNTER; + update(QRect(pos,getDocument()->cardsize)); + cardmovecnt++; + pos=cardorigin+(cardend-cardorigin)*cardmovecnt/MOVECOUNTER; + update(QRect(pos,getDocument()->cardsize)); + // Turning of the card + if ( cardmoveunder>=0) + { + update(QRect(cardorigin,getDocument()->cardsize)); + } + } +} + +void LSkatView::updateStatus() +{ + update(status_rect1); + update(status_rect2); +} + +#include "lskatview.moc" diff --git a/lskat/lskat/lskatview.h b/lskat/lskat/lskatview.h new file mode 100644 index 00000000..05b31356 --- /dev/null +++ b/lskat/lskat/lskatview.h @@ -0,0 +1,91 @@ +/*************************************************************************** + lskatview.h - description + ------------------- + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef LSKATVIEW_H +#define LSKATVIEW_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#include <qrect.h> +#include "lskat.h" + +class LSkatDoc; + +/** The LSkatView class provides the view widget for the LSkatApp instance. + * The View instance inherits QWidget as a base class and represents the view object of a KTMainWindow. As LSkatView is part of the + * docuement-view model, it needs a reference to the document object connected with it by the LSkatApp class to manipulate and display + * the document structure provided by the LSkatDoc class. + * + * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. + * @version KDevelop version 0.4 code generation + */ +class LSkatView : public QWidget +{ + Q_OBJECT + public: + /** Constructor for the main view */ + LSkatView(QWidget *parent = 0, const char *name=0); + + /** returns a pointer to the document connected to the view instance. Mind that this method requires a LSkatApp instance as a parent + * widget to get to the window document pointer by calling the LSkatApp::getDocument() method. + * + * @see LSkatApp#getDocument + */ + LSkatDoc *getDocument() const; + + void paintEvent( QPaintEvent * p); + void Paint(QPainter *p); + void InitMove(int player,int x,int y); + void updateStatus(); + + protected: + void drawDeck(QPainter *p); + void drawIntro(QPainter *p); + void drawMove(QPainter *p); + void drawStatus(QPainter *p); + void drawFinal(QPainter *p); + void drawBorder(QPainter *p,QRect rect,int offset,int width,int mode); + QPoint calcCardPos(int x,int y); + + void mousePressEvent ( QMouseEvent *m ); + + protected slots: + void moveTimerReady(); + void introTimerReady(); + void drawTabText(QPainter *p,QRect rect,QString s,int *ts); + + + private: + QRect status_rect1; + QRect status_rect2; + QRect status_rect3; + QTimer *moveTimer; + QTimer *introTimer; + int introcnt; + int cardmovecnt; + int cardmovex,cardmovey; + int cardmoveunder; + QPoint cardorigin; + QPoint cardend; + int introCards[NO_OF_CARDS]; + +}; + +#endif // LSKATVIEW_H diff --git a/lskat/lskat/main.cpp b/lskat/lskat/main.cpp new file mode 100644 index 00000000..50910540 --- /dev/null +++ b/lskat/lskat/main.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + begin : Tue May 2 15:47:11 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <kcmdlineargs.h> +#include <klocale.h> +#include <kaboutdata.h> +#include "lskat.h" + +static KCmdLineOptions options[] = +{ + { "d", 0, 0}, + { "debug <level>", I18N_NOOP("Enter debug level"), 0 }, + KCmdLineLastOption +}; + +int global_debug; + +int main(int argc, char *argv[]) +{ + + global_debug=0; + KAboutData aboutData( "lskat", I18N_NOOP("Lieutenant Skat"), + "1.0", + I18N_NOOP("Card Game"), + KAboutData::License_GPL, + "(c) 2000, Martin Heni"); + aboutData.addAuthor("Martin Heni",0, "[email protected]"); + aboutData.addCredit("Laura", I18N_NOOP("Beta testing"), 0); + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + /* command line handling */ + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if (args->isSet("debug")) + { + QString s = args->getOption("debug"); + global_debug = s.toInt(); + qDebug("Debug level set to %d\n", global_debug); + } + args->clear(); + + KApplication app; + + if (app.isRestored()) + { + RESTORE(LSkatApp); + } + else + { + LSkatApp *lskat = new LSkatApp(); + lskat->show(); + } + + return app.exec(); +} diff --git a/lskat/lskat/msgdlg.cpp b/lskat/lskat/msgdlg.cpp new file mode 100644 index 00000000..daea1dac --- /dev/null +++ b/lskat/lskat/msgdlg.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + Msgdlg - Send message to remote + ------------------- + begin : Thu Mar 30 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/* + Msgdlg.cpp + + $Id$ + + Msg dialog for player names + + (c) Martin Heni, [email protected] + June 1999 + + License: GPL + +*/ + +#include <qgroupbox.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include "msgdlg.h" + + + +// Create the dialog for changing the player names +MsgDlg::MsgDlg( QWidget *parent, const char *name,const char * /*sufi */ ) + : QDialog( parent, name,TRUE ) +{ + setCaption(i18n("Send Message to Remote Player")); + setMinimumSize(400,160); + setMaximumSize(600,360); + resize( 400, 160 ); + + QGroupBox* grp; + grp = new QGroupBox(i18n("Enter Message"), this); + grp->resize(380,100); + grp->move(10,10); + + MultiLine = new QMultiLineEdit( grp, "MLineEdit" ); + MultiLine->setGeometry( 10, 20, 360, 70 ); + MultiLine->setText(QCString("") ); + + QPushButton *PushButton; + PushButton = new QPushButton( i18n("Send" ), this, "PushButton_1" ); + PushButton->setGeometry( 20, 120, 65, 30 ); + connect( PushButton, SIGNAL(clicked()), SLOT(accept()) ); + PushButton->setAutoRepeat( FALSE ); + + PushButton = new KPushButton( KStdGuiItem::cancel(), this, "PushButton_2" ); + PushButton->setGeometry( 305, 120, 65, 30 ); + connect( PushButton, SIGNAL(clicked()), SLOT(reject()) ); + PushButton->setAutoRepeat( FALSE ); +} + +QString MsgDlg::GetMsg() +{ + return MultiLine->text(); +} + +#include "msgdlg.moc" diff --git a/lskat/lskat/msgdlg.h b/lskat/lskat/msgdlg.h new file mode 100644 index 00000000..614fa332 --- /dev/null +++ b/lskat/lskat/msgdlg.h @@ -0,0 +1,39 @@ +/*************************************************************************** + LSKat for KDE + ------------------- + begin : March 2000 + copyright : (C) 1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef __MSGDLG_H_ +#define __MSGDLG_H_ +#include <qmultilineedit.h> +#include <qstring.h> +#include <qdialog.h> + +class MsgDlg : public QDialog +{ + Q_OBJECT + + public: + MsgDlg (QWidget* parent = NULL,const char* name = NULL,const char *sufi=NULL); + QString GetMsg(); + +protected slots: + +protected: + QMultiLineEdit *MultiLine; + + + +}; +#endif diff --git a/lskat/lskat/namedlg.cpp b/lskat/lskat/namedlg.cpp new file mode 100644 index 00000000..478f5ea5 --- /dev/null +++ b/lskat/lskat/namedlg.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'namedlg.ui' +** +** Created: Thu Nov 23 11:10:17 2000 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "namedlg.h" + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qlayout.h> +#include <qwhatsthis.h> + +#include <klocale.h> + +#define NAME_MAX_LEN 12 + +/* + * Constructs a NameDlg which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +NameDlg::NameDlg( QWidget *parent, const char *name,bool /* modal */, WFlags /* fl */ ) + : KDialogBase( Plain, i18n("Configure Names"), Ok|Cancel, Ok, + parent, name, true,true ) + +{ + QWidget *page = plainPage(); + if ( !name ) setName( "NameDlg" ); + resize( 252, 186 ); +// setCaption( i18n( "Configure Names" ) ); + vbox = new QVBoxLayout( page,spacingHint() ); + vbox->setSpacing( 6 ); + vbox->setMargin( 11 ); + + hbox = new QHBoxLayout; + hbox->setSpacing( 6 ); + hbox->setMargin( 0 ); + + player_names = new QGroupBox( page, "player_names" ); + player_names->setTitle(i18n("Player Names") ); + player_names->setColumnLayout(0, Qt::Vertical ); + player_names->layout()->setSpacing( 0 ); + player_names->layout()->setMargin( 0 ); + vbox_2 = new QVBoxLayout( player_names->layout() ); + vbox_2->setAlignment( Qt::AlignTop ); + vbox_2->setSpacing( 6 ); + vbox_2->setMargin( 11 ); + + vbox_3 = new QVBoxLayout; + vbox_3->setSpacing( 6 ); + vbox_3->setMargin( 0 ); + + hbox_2 = new QHBoxLayout; + hbox_2->setSpacing( 6 ); + hbox_2->setMargin( 0 ); + + text_player1 = new QLabel( player_names, "text_player1" ); + text_player1->setText( i18n("Player 1:" ) ); + hbox_2->addWidget( text_player1 ); + + edit_player1 = new QLineEdit( player_names, "edit_player1" ); + edit_player1->setMaxLength( NAME_MAX_LEN ); + QWhatsThis::add( edit_player1, i18n( "Enter a player's name" ) ); + + hbox_2->addWidget( edit_player1 ); + vbox_3->addLayout( hbox_2 ); + + hbox_3 = new QHBoxLayout; + hbox_3->setSpacing( 6 ); + hbox_3->setMargin( 0 ); + + text_player2 = new QLabel( player_names, "text_player2" ); + text_player2->setText( i18n("Player 2:" ) ); + hbox_3->addWidget( text_player2 ); + + edit_player2 = new QLineEdit( player_names, "edit_player2" ); + edit_player2->setMaxLength( NAME_MAX_LEN ); + QWhatsThis::add( edit_player2, i18n( "Enter a player's name" ) ); + hbox_3->addWidget( edit_player2 ); + vbox_3->addLayout( hbox_3 ); + vbox_2->addLayout( vbox_3 ); + + // left + QSpacerItem* spacer_3 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ); + hbox->addItem( spacer_3 ); + + hbox->addWidget( player_names ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum ); + hbox->addItem( spacer ); + + // top + QSpacerItem* spacer_4 = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); + vbox->addItem( spacer_4 ); + + vbox->addLayout( hbox ); + QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + vbox->addItem( spacer_2 ); + +} + +/* + * Destroys the object and frees any allocated resources + */ +NameDlg::~NameDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + +// In and output the name strings +void NameDlg::SetNames(QString n1, QString n2) +{ + edit_player1->setText( n1 ); + edit_player2->setText( n2 ); +} +void NameDlg::GetNames(QString &n1, QString &n2) +{ + n1=edit_player1->text( ); + n1.truncate(NAME_MAX_LEN); + n2=edit_player2->text( ); + n2.truncate(NAME_MAX_LEN); +} + +#include "namedlg.moc" diff --git a/lskat/lskat/namedlg.h b/lskat/lskat/namedlg.h new file mode 100644 index 00000000..c5d3391a --- /dev/null +++ b/lskat/lskat/namedlg.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'namedlg.ui' +** +** Created: Thu Nov 23 11:10:15 2000 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef NAMEDLG_H +#define NAMEDLG_H + +#include <kdialogbase.h> +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QGroupBox; +class QLabel; +class QLineEdit; +class QPushButton; + +class NameDlg : public KDialogBase +{ + Q_OBJECT + +public: + NameDlg( QWidget* parent = 0, const char* name = 0, bool modal = TRUE, WFlags fl = 0 ); + ~NameDlg(); + void SetNames(QString n1,QString n2); + void GetNames(QString &n1,QString &n2); + + QGroupBox* player_names; + QLabel* text_player1; + QLineEdit* edit_player1; + QLabel* text_player2; + QLineEdit* edit_player2; + QPushButton* PushButton1; + QPushButton* PushButton2; + +protected: + QHBoxLayout* hbox; + QHBoxLayout* hbox_2; + QHBoxLayout* hbox_3; + QHBoxLayout* hbox_4; + QVBoxLayout* vbox; + QVBoxLayout* vbox_2; + QVBoxLayout* vbox_3; +}; + +#endif // NAMEDLG_H diff --git a/lskat/lskat/networkdlg.cpp b/lskat/lskat/networkdlg.cpp new file mode 100644 index 00000000..f43a1fd9 --- /dev/null +++ b/lskat/lskat/networkdlg.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** + networkdlg.cpp - description + ------------------- + copyright : (C) 2004 by Jakub Stachowski + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include "networkdlg.h" +#include <qspinbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qbuttongroup.h> +#include <qwidgetstack.h> + +extern const char* LSKAT_SERVICE; + +// Create the dialog +NetworkDlg::NetworkDlg( QWidget *parent, const char *name ) + : NetworkDlgBase( parent, name, TRUE ) +{ + browser = new DNSSD::ServiceBrowser(QString::fromLatin1(LSKAT_SERVICE)); + connect(browser,SIGNAL(finished()),SLOT(gamesFound())); + browser->startBrowse(); +} + +NetworkDlg::~NetworkDlg() +{ + delete browser; +} + +void NetworkDlg::SetHost(const QString& host) +{ + hostname->setText(host); +} + +void NetworkDlg::SetName(const QString& name) +{ + serverName->setText(name); +} +QString NetworkDlg::QueryName() const +{ + return serverName->text(); +} + +void NetworkDlg::SetPort(unsigned short port) +{ + this->port->setValue(port); +} + +void NetworkDlg::gamesFound() +{ + bool autoselect=false; + if (!clientName->count() && group->selectedId()==1) autoselect=true; + clientName->clear(); + QStringList names; + QValueList<DNSSD::RemoteService::Ptr>::ConstIterator itEnd = browser->services().end(); + for (QValueList<DNSSD::RemoteService::Ptr>::ConstIterator it = browser->services().begin(); + it!=itEnd; ++it) names << (*it)->serviceName(); + clientName->insertStringList(names); + if (autoselect && clientName->count()) gameSelected(0); +} + +void NetworkDlg::gameSelected(int nr) +{ + if (nr>=browser->services().count() || nr<0) return; + DNSSD::RemoteService::Ptr srv = browser->services()[nr]; + if (!srv->isResolved() && !srv->resolve()) return; + hostname->setText(srv->hostName()); + port->setValue(srv->port()); +} + +unsigned short NetworkDlg::QueryPort() const +{ + return port->value(); +} + +QString NetworkDlg::QueryHost() const +{ + return hostname->text(); +} + +void NetworkDlg::toggleServerClient() +{ + stack->raiseWidget(group->selectedId()); + if (group->selectedId()==1) { + gameSelected(clientName->currentItem()); + hostname->setEnabled(true); + } + else { + hostname->setText(QString::null); + hostname->setEnabled(false); + } +} + +#include "networkdlg.moc" diff --git a/lskat/lskat/networkdlg.h b/lskat/lskat/networkdlg.h new file mode 100644 index 00000000..fb180eeb --- /dev/null +++ b/lskat/lskat/networkdlg.h @@ -0,0 +1,48 @@ +/*************************************************************************** + networkdlg.h - description + ------------------- + copyright : (C) 2004 by Jakub Stachowski + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef NETWORKDLG_H +#define NETWORKDLG_H + +#include <qstring.h> +#include <dnssd/servicebrowser.h> +#include "networkdlgbase.h" + + +class NetworkDlg : public NetworkDlgBase +{ + Q_OBJECT + + public: + NetworkDlg(QWidget* parent=NULL, const char* name=NULL); + ~NetworkDlg(); + void SetName(const QString& name); + void SetHost(const QString& host); + void SetPort(unsigned short port); + QString QueryName() const; + unsigned short QueryPort() const; + QString QueryHost() const; + protected: + virtual void toggleServerClient(); + virtual void gameSelected(int nr); + private slots: + void gamesFound(); + private: + DNSSD::ServiceBrowser* browser; +}; + +#endif // NETWORKDLG_H + diff --git a/lskat/lskat/networkdlgbase.ui b/lskat/lskat/networkdlgbase.ui new file mode 100644 index 00000000..861c77f3 --- /dev/null +++ b/lskat/lskat/networkdlgbase.ui @@ -0,0 +1,306 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>NetworkDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>NetworkDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>320</width> + <height>218</height> + </rect> + </property> + <property name="caption"> + <string>Network Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>group</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Play As</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>serverBtn</cstring> + </property> + <property name="text"> + <string>Server</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>clientBtn</cstring> + </property> + <property name="text"> + <string>Client</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QWidgetStack"> + <property name="name"> + <cstring>stack</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>serverPage</cstring> + </property> + <attribute name="id"> + <number>0</number> + </attribute> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>serverLabel</cstring> + </property> + <property name="text"> + <string>Game name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>serverName</cstring> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>serverName</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>clientPage</cstring> + </property> + <attribute name="id"> + <number>1</number> + </attribute> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>clientLabel</cstring> + </property> + <property name="text"> + <string>Network games:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>clientName</cstring> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>clientName</cstring> + </property> + </widget> + </hbox> + </widget> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>hostLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Host:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + <property name="hAlign" stdset="0"> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>hostname</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>portLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Port:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + <property name="hAlign" stdset="0"> + </property> + <property name="vAlign" stdset="0"> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>port</cstring> + </property> + <property name="maxValue"> + <number>65000</number> + </property> + <property name="value"> + <number>7432</number> + </property> + <property name="whatsThis" stdset="0"> + <string>Choose a port to connect to</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout11</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>51</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButton1</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>61</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>pushButton1</sender> + <signal>clicked()</signal> + <receiver>NetworkDlgBase</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>clientName</sender> + <signal>activated(int)</signal> + <receiver>NetworkDlgBase</receiver> + <slot>gameSelected(int)</slot> + </connection> + <connection> + <sender>serverBtn</sender> + <signal>toggled(bool)</signal> + <receiver>NetworkDlgBase</receiver> + <slot>toggleServerClient()</slot> + </connection> + <connection> + <sender>clientBtn</sender> + <signal>toggled(bool)</signal> + <receiver>NetworkDlgBase</receiver> + <slot>toggleServerClient()</slot> + </connection> +</connections> +<slots> + <slot access="protected">toggleServerClient()</slot> + <slot access="protected">gameSelected(int nr)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/lskat/lskat/templates/cpp_template b/lskat/lskat/templates/cpp_template new file mode 100644 index 00000000..6afef5d4 --- /dev/null +++ b/lskat/lskat/templates/cpp_template @@ -0,0 +1,16 @@ +/*************************************************************************** + |FILENAME| - description + ------------------- + begin : |DATE| + copyright : (C) |YEAR| by |AUTHOR| + email : |EMAIL| + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ diff --git a/lskat/lskat/templates/header_template b/lskat/lskat/templates/header_template new file mode 100644 index 00000000..6afef5d4 --- /dev/null +++ b/lskat/lskat/templates/header_template @@ -0,0 +1,16 @@ +/*************************************************************************** + |FILENAME| - description + ------------------- + begin : |DATE| + copyright : (C) |YEAR| by |AUTHOR| + email : |EMAIL| + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ diff --git a/lskat/lskatproc/KChildConnect.cpp b/lskat/lskatproc/KChildConnect.cpp new file mode 100644 index 00000000..0308a3f0 --- /dev/null +++ b/lskat/lskatproc/KChildConnect.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + KChildConnect.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <stdio.h> +#include "KChildConnect.h" + +#include "KChildConnect.moc" + +KChildConnect::KChildConnect() + : QObject(0,0) +{ + input_pending=false; + inputbuffer=""; +} + +KChildConnect::~KChildConnect() +{ +} + +KR_STATUS KChildConnect::QueryStatus() +{ + return KR_OK; +} + +// Communication with process +bool KChildConnect::SendMsg(KEMessage *msg) +{ + QString sendstring=msg->ToString(); + // Debug only + if (msg->HasKey(QCString("KLogSendMsg"))) + { + char *p; + int size; + FILE *fp; + msg->GetData(QCString("KLogSendMsg"),p,size); + if (p && (fp=fopen(p,"a")) ) + { + fprintf(fp,"------------------------------------\n"); + fprintf(fp,"%s", sendstring.utf8().data()); + fclose(fp); + } + } + // end debug only + return Send(sendstring); +} + +// Send string to parent +bool KChildConnect::Send(QString str) +{ + if (!str || str.length()<1) return true; // no need to send crap + printf("%s",str.latin1()); + fflush(stdout); + return true; +} + +void KChildConnect::Receive(QString input) +{ + // Cut out CR + int len,pos; + QString tmp; + + + // Call us recursive until there are no CR left + len=KEMESSAGE_CR.length(); + pos=input.find(KEMESSAGE_CR); + if (pos>0) + { + tmp=input.left(pos); + if (tmp.length()>0) Receive(tmp); // CR free + input=input.right(input.length()-pos-len); + if (input.length()>0) Receive(input); + return ; + } + +// printf(" ---> KChildConnect::Receive: '%s'\n",(const char *)input); + if (input==QString(KEMESSAGE_HEAD) && !input_pending) + { + input_pending=true; + inputcache.clear(); + return ; + } + if (!input_pending) return ; // ignore + if (input!=QString(KEMESSAGE_TAIL)) + { + inputcache.append(input.latin1()); + return; + } + input_pending=0; + + KEMessage *msg=new KEMessage; + char *it; + for (it=inputcache.first();it!=0;it=inputcache.next()) + { + msg->AddString(QCString(it)); + } + +// printf("+- CHILDprocess:: GOT MESSAGE::Emmiting slotReceiveMsg\n"); + emit signalReceiveMsg(msg,ID); + + delete msg; +} + +void KChildConnect::SetID(int id) +{ + ID=id; +} +int KChildConnect::QueryID() +{ + return ID; +} + diff --git a/lskat/lskatproc/KChildConnect.h b/lskat/lskatproc/KChildConnect.h new file mode 100644 index 00000000..9cad1a5d --- /dev/null +++ b/lskat/lskatproc/KChildConnect.h @@ -0,0 +1,45 @@ +/*************************************************************************** + KChildConnect.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +#ifndef _KCHILDCONNECT_H_ +#define _KCHILDCONNECT_H_ + +#include <qobject.h> +#include <qstrlist.h> +#include "KEMessage.h" + + +class KChildConnect: public QObject +{ + Q_OBJECT + + protected: + QStrList inputcache; + bool input_pending; + QString inputbuffer; + int ID; + + public: + KChildConnect(); + ~KChildConnect(); + void Receive(QString input); + int QueryID(); + void SetID(int id); + + virtual bool SendMsg(KEMessage *msg); + virtual bool Send(QString str); + virtual KR_STATUS QueryStatus(); + + public slots: + + + signals: + void signalReceiveMsg(KEMessage *msg,int id); +}; + +#endif diff --git a/lskat/lskatproc/KConnectTypes.h b/lskat/lskatproc/KConnectTypes.h new file mode 100644 index 00000000..12e9561a --- /dev/null +++ b/lskat/lskatproc/KConnectTypes.h @@ -0,0 +1,38 @@ +/*************************************************************************** + KConnectTypes.h - description + ------------------- + begin : Sun Apr 9 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KCONNECTTYPES_H_ +#define _KCONNECTTYPES_H_ + +enum KGM_TYPE {KGM_TYPE_INVALID=0,KGM_TYPE_SHORT=1,KGM_TYPE_LONG=2, + KGM_TYPE_FLOAT=3,KGM_TYPE_DATA=4}; + +enum KG_INPUTTYPE { + KG_INPUTTYPE_INVALID=0, + KG_INPUTTYPE_INTERACTIVE=1, + KG_INPUTTYPE_PROCESS=2, + KG_INPUTTYPE_REMOTE=3}; + +enum KR_STATUS { + KR_NO_SOCKET=-2, + KR_WAIT_FOR_CLIENT=-1, + KR_INVALID=0, + // >0 OK + KR_OK=1, + KR_CLIENT=2, + KR_SERVER=3 + }; +#endif diff --git a/lskat/lskatproc/KEMessage.cpp b/lskat/lskatproc/KEMessage.cpp new file mode 100644 index 00000000..db598573 --- /dev/null +++ b/lskat/lskatproc/KEMessage.cpp @@ -0,0 +1,326 @@ +/*************************************************************************** + KEMessage.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "KEMessage.h" + +void KEMessage::AddEntry(QString key,KMessageEntry *entry) +{ + // printf(" AddingEntry: %s with data field %p\n",(char *)key,entry->QueryData()); + if (!entry) return ; + dict.insert(key,entry); + keys.append(key.latin1()); +} + +void KEMessage::AddDataType(QString key,int size,const char *data,KGM_TYPE type) +{ +// printf("AddDataType for %s size=%d\n",(const char *)key,size); + if (size<=0) return ; + KMessageEntry *entry=new KMessageEntry; + entry->SetType(type); + entry->CopyData(size,data); + AddEntry(key,entry); +} + +void KEMessage::AddData(QString key,short data) +{ + AddDataType(key,sizeof(short),(char *)&data,KGM_TYPE_SHORT); +} + +void KEMessage::AddData(QString key,long data) +{ + AddDataType(key,sizeof(long),(char *)&data,KGM_TYPE_LONG); +} + +void KEMessage::AddData(QString key,float data) +{ + AddDataType(key,sizeof(float),(char *)&data,KGM_TYPE_FLOAT); +} + +void KEMessage::AddData(QString key,const char *data,int size) +{ + if (size<0) size=strlen(data)+1; // +1 for 0 Byte + AddDataType(key,size,data,KGM_TYPE_DATA); +} + +KGM_TYPE KEMessage::QueryType(QString key) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return (KGM_TYPE)0; + return entry->QueryType(); +} + +bool KEMessage::HasKey(QString key) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + return true; +} + +bool KEMessage::GetData(QString key,short &s) +{ + short *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_SHORT) return false; + // printf("GetShortData: %p for %s\n",entry->QueryData(),(char *)key); + result=(short *)entry->QueryData(); + s=*result; + return true; +} + +bool KEMessage::GetData(QString key,long &l) +{ + long *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_LONG) return false; + result=(long *)entry->QueryData(); + l=*result; + return true; +} + +bool KEMessage::GetData(QString key,float &f) +{ + float *result; + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_FLOAT) return false; + // printf("GetFloatData: %p for %s\n",entry->QueryData(),(char *)key); + result=(float *)entry->QueryData(); + f=*result; + return true; +} + +bool KEMessage::GetData(QString key,char * &c,int &size) +{ + KMessageEntry *entry; + entry=dict.find(key); + if (!entry) return false; + if (entry->QueryType()!=KGM_TYPE_DATA) return false; + c=entry->QueryData(); + size=entry->QuerySize(); + return true; +} + +QString KEMessage::EntryToString(char *key,KMessageEntry *entry) +{ + QString s,tmp; + int size,i; + KGM_TYPE type; + char *data; + s=QCString(""); + if (!entry) return s; + size=entry->QuerySize(); + type=entry->QueryType(); + data=entry->QueryData(); + + // Key + /* + tmp.sprintf("%s%s%d%s%d%s", + key,KEMESSAGE_SEP, + size,KEMESSAGE_SEP, + (int)type,KEMESSAGE_SEP); + */ + tmp=QCString(key); + s+=tmp; + s+=KEMESSAGE_SEP; + tmp.sprintf("%d",size); + s+=tmp; + s+=KEMESSAGE_SEP; + tmp.sprintf("%d",(int)type); + s+=tmp; + s+=KEMESSAGE_SEP; + + + // We ignore the type of data and process them all as + // byte sequence + for (i=0;i<size;i++) + { + // Convert to 4 bit value ... someone can improves + tmp.sprintf("%c%c", + 'a'+(data[i]&15), + 'a'+((data[i]>>4)&15)); + s+=tmp; + } + s+=KEMESSAGE_CR; + + return s; +} + +QString KEMessage::StringToEntry(QString str,KMessageEntry *entry) +{ + int pos,oldpos,cnt,len; + QString key,size,type,data; + const char *p; + char *q; + char c; + + len=KEMESSAGE_SEP.length(); + + if (!entry) return QString(); + pos=str.find(KEMESSAGE_SEP,0); + if (pos<0) return QString(); // wrong format + key=str.left(pos); + + + oldpos=pos; + pos=str.find(KEMESSAGE_SEP,oldpos+len); + if (pos<0) return QString(); // wrong format + size=str.mid(oldpos+len,pos-oldpos-len); + + + oldpos=pos; + pos=str.find(KEMESSAGE_SEP,oldpos+len); + if (pos<0) return QString(); // wrong format + type=str.mid(oldpos+len,pos-oldpos-len); + + + data=str.right(str.length()-pos-len); + + + cnt=size.toInt(); + entry->SetType((KGM_TYPE)type.toInt()); + + // I hope this works with unicode strings as well + p=data.latin1(); + q=(char *)calloc(data.length()/2,sizeof(char)); + if (!q) return QString(); + for(pos=0;pos<cnt;pos++) + { + if (pos*2+1>(int)data.length()) return QString(); // SEVERE ERROR + c=*(p+2*pos)-'a' | ((*(p+2*pos+1)-'a')<<4); + q[pos]=c; + } + entry->CopyData(cnt,q); + + free(q); + return key; +} + +QString KEMessage::ToString() +{ + QString s; + KMessageEntry *entry; + char *it; + s=KEMESSAGE_HEAD+KEMESSAGE_CR; + for (it=keys.first();it!=0;it=keys.next()) + { + entry=dict.find(QCString(it)); + s+=EntryToString(it,entry); + } + s+=KEMESSAGE_TAIL+KEMESSAGE_CR; + return s; +} + +bool KEMessage::AddString(QString s) +{ + // break s into key,size and data + QString key; + KMessageEntry *entry=new KMessageEntry; + key=StringToEntry(s,entry); + if (!key) return false; + AddEntry(key,entry); + return true; +} +bool KEMessage::AddStringMsg(QString str) +{ + bool result; + QString data; + int pos,oldpos,len; + + len=KEMESSAGE_CR.length(); + + pos=str.find(KEMESSAGE_CR); + if (pos<0) return false; // wrong format + if (str.left(pos)!=(KEMESSAGE_HEAD)) return false; // wrong message + + do + { + oldpos=pos; + pos=str.find(KEMESSAGE_CR,oldpos+len); + if (pos<0) return false; // wrong format + data=str.mid(oldpos+len,pos-oldpos-len); + if (data!=(KEMESSAGE_TAIL)) + { + result=AddString(data); + if (!result) return false; // wrong format + } + }while(data!=(KEMESSAGE_TAIL)); + + return result; +} + +void KEMessage::RemoveAll() +{ + keys.clear(); + dict.clear(); +} + +void KEMessage::Remove(QString key) +{ + keys.remove(key.latin1()); + dict.remove(key); +} + +uint KEMessage::QueryNumberOfKeys() +{ + return keys.count(); +} +QStrList *KEMessage::QueryKeys() +{ + return &keys; +} + +KEMessage::~KEMessage() +{ + // printf("Deleteing KEMessage %p\n",this); +} +KEMessage::KEMessage() +{ + // printf("KEMessage construct %p\n",this); + dict.setAutoDelete(true); +} +KEMessage::KEMessage(KEMessage &msg) +{ + // printf("KEMessage copy constructor from %p to %p\n",&msg,this); + *this=msg; +} +KEMessage &KEMessage::operator=(KEMessage &msg) +{ + // KEMessage *newmsg=new KEMessage; + KMessageEntry *entry; + KMessageEntry *newentry; + char *it; + // printf("Assigning = KEMessage from %p to %p\n",&msg,this); + for (it=msg.keys.first();it!=0;it=msg.keys.next()) + { + entry=msg.dict.find(QCString(it)); + newentry=new KMessageEntry; + *newentry=*entry; + AddEntry(QCString(it),newentry); + + } + // return *newmsg; + return *this; +} diff --git a/lskat/lskatproc/KEMessage.h b/lskat/lskatproc/KEMessage.h new file mode 100644 index 00000000..0a1913cc --- /dev/null +++ b/lskat/lskatproc/KEMessage.h @@ -0,0 +1,66 @@ +/*************************************************************************** + KEMessage.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KEMESSAGE_H_ +#define _KEMESSAGE_H_ + +#include <string.h> +#include <qstring.h> +#include <qstrlist.h> +#include <qdict.h> +#include "KMessageEntry.h" + +#define KEMESSAGE_HEAD QString(QCString("BEGIN_V1000")) +#define KEMESSAGE_TAIL QString(QCString("END_V1000")) +#define KEMESSAGE_CR QString(QCString("\n")) +#define KEMESSAGE_SEP QString(QCString(":::")) + +class KEMessage +{ + private: + QStrList keys; + QDict<KMessageEntry> dict; + + protected: + void AddEntry(QString key,KMessageEntry *entry); + public: + QStrList *QueryKeys(); + uint QueryNumberOfKeys(); + void AddDataType(QString key,int size,const char *data,KGM_TYPE type); + void AddData(QString key,short data); + void AddData(QString key,long data); + void AddData(QString key,float data); + void AddData(QString key,const char *data,int size=-1); + bool GetData(QString key,short &s); + bool GetData(QString key,long &l); + bool GetData(QString key,float &f); + bool GetData(QString key,char * &c,int &size); + bool HasKey(QString key); + void Remove(QString key); + KGM_TYPE QueryType(QString key); + QString ToString(); + QString EntryToString(char *key,KMessageEntry *entry); + QString StringToEntry(QString str,KMessageEntry *entry); + bool AddString(QString s); + bool AddStringMsg(QString str); + void RemoveAll(); + ~KEMessage(); + KEMessage(); + KEMessage(KEMessage &msg); + KEMessage &operator=(KEMessage &msg); +}; + +#endif diff --git a/lskat/lskatproc/KInputChildProcess.cpp b/lskat/lskatproc/KInputChildProcess.cpp new file mode 100644 index 00000000..a821aa7a --- /dev/null +++ b/lskat/lskatproc/KInputChildProcess.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + KInputChildProcess.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <qstring.h> + +#include "KInputChildProcess.h" +#include "KInputChildProcess.moc" + + +KInputChildProcess::~KInputChildProcess() +{ + delete buffer; + delete childConnect; +} +KInputChildProcess::KInputChildProcess(int size_buffer) + : QObject(0,0) +{ + buffersize=size_buffer; + if (buffersize<1) buffersize=1024; + buffer=new char[buffersize]; + inputbuffer=""; + terminateChild=false; +} +bool KInputChildProcess::exec() +{ + int pos; + QString s; + + childConnect=new KChildConnect; + if (!childConnect) return false; + connect(childConnect,SIGNAL(signalReceiveMsg(KEMessage *,int)), + this,SLOT(slotReceiveMsg(KEMessage *,int))); + do + { + // Wait for input + if (feof(stdin)) + { + sleep(1); + continue; + } + + if (!fgets(buffer,buffersize,stdin) ) + { + continue; + } + s=buffer; + s=inputbuffer+s; + // printf("ChildABC '%s'\n",(const char *)s); + // fflush(stdout); + pos=s.findRev(KEMESSAGE_CR); + if (pos<0) + { + inputbuffer=s; + } + else if (pos+KEMESSAGE_CR.length()==s.length()) + { + // CR at the end...calling receive + childConnect->Receive(s); + } + else + { + inputbuffer=s.right(s.length()-pos-KEMESSAGE_CR.length()); + s=s.left(pos+KEMESSAGE_CR.length()); + // printf("s='%s' in='%s'\n",(const char *)s,(const char *)inputbuffer); + childConnect->Receive(s); + } + }while(!terminateChild); + return true; +} + +void KInputChildProcess::Terminate() +{ + terminateChild=true; +} +bool KInputChildProcess::IsTerminated() +{ + return terminateChild; +} + +bool KInputChildProcess::ReceiveMsg(KEMessage *msg,int id) +{ + return false; +} +void KInputChildProcess::slotReceiveMsg(KEMessage *msg,int id) +{ + if (!ReceiveMsg(msg,id)) // made for virtual override + { + // otherwise emit signal + emit signalReceiveMsg(msg,id); + } +} +bool KInputChildProcess::SendMsg(KEMessage *msg) +{ + if (childConnect) return childConnect->SendMsg(msg); + return false; +} + + diff --git a/lskat/lskatproc/KInputChildProcess.h b/lskat/lskatproc/KInputChildProcess.h new file mode 100644 index 00000000..b4694df5 --- /dev/null +++ b/lskat/lskatproc/KInputChildProcess.h @@ -0,0 +1,57 @@ +/*************************************************************************** + KInputChildProcess.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KINPUTCHILDPROCESS_H_ +#define _KINPUTCHILDPROCESS_H_ + +#include <qobject.h> +#include "KEMessage.h" +#include "KChildConnect.h" + + +class KInputChildProcess : public QObject +{ + Q_OBJECT + + private: + char *buffer; + QString inputbuffer; + int buffersize; + bool terminateChild; + protected: + KChildConnect *childConnect; + + public: + KInputChildProcess(int size_buffer=4096); + ~KInputChildProcess(); + bool exec(); + virtual bool ReceiveMsg(KEMessage *msg,int id); + // Forward calls to childconnect + bool SendMsg(KEMessage *msg); + // Immediately kills child's exec ! + void Terminate(); + bool IsTerminated(); + + + public slots: + void slotReceiveMsg(KEMessage *msg,int id); + + signals: + void signalReceiveMsg(KEMessage *msg,int id); +}; + + +#endif diff --git a/lskat/lskatproc/KMessageEntry.cpp b/lskat/lskatproc/KMessageEntry.cpp new file mode 100644 index 00000000..e91f645a --- /dev/null +++ b/lskat/lskatproc/KMessageEntry.cpp @@ -0,0 +1,98 @@ +/*************************************************************************** + KMessageEntry.cpp - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/*************************************************************************** + FILENAME| - description + ------------------- + begin : Tue Apr 4 2000 + copyright : (C) |1995-2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "KMessageEntry.h" + + +void KMessageEntry::SetType(KGM_TYPE t) +{ + type=t; +} + +KGM_TYPE KMessageEntry::QueryType() +{ + return type; +} + +int KMessageEntry::QuerySize() +{ + return size; +} + +char * KMessageEntry::QueryData() +{ + return data; +} + +bool KMessageEntry::CopyData(int s,const char *c) +{ + if (s<1) return false; + data=(char *)calloc(s,1); + if (!data) return false; + // printf(" MessageEntry Copy Data to calloc %p\n",data); + memcpy(data,c,s); + size=s; + return true; +} + +KMessageEntry::KMessageEntry() +{ + // printf("KMessageEntry construct %p\n",this); + size=0; + type=(KGM_TYPE)0; + data=(char *)0; +} + +KMessageEntry::KMessageEntry(KMessageEntry &entry) +{ + // printf("KMessageEntry copy constructor from %p to %p\n",&entry,this); + *this=entry; +} +KMessageEntry &KMessageEntry::operator=(KMessageEntry &entry) +{ + // printf("KMessageEntry operator= from %p to %p\n",&entry,this); + SetType(entry.type); + CopyData(entry.size,entry.data); + return *this; +} + +KMessageEntry::~KMessageEntry() +{ + // printf("MessageEntry destructor %p\n",this); + // printf(" MessageEntry free %p\n",data); + if (data) free(data); + data=(char *)0; +} + diff --git a/lskat/lskatproc/KMessageEntry.h b/lskat/lskatproc/KMessageEntry.h new file mode 100644 index 00000000..947ce1ff --- /dev/null +++ b/lskat/lskatproc/KMessageEntry.h @@ -0,0 +1,44 @@ +/*************************************************************************** + KMessageEntry.h - description + ------------------- + begin : Tue May 2 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef _KMESSAGEENTRY_H_ +#define _KMESSAGEENTRY_H_ + +#include <string.h> +#include "KConnectTypes.h" + + + +class KMessageEntry +{ + private: + int size; + KGM_TYPE type; + char *data; + + public: + void SetType(KGM_TYPE t); + KGM_TYPE QueryType(); + int QuerySize(); + char *QueryData(); + bool CopyData(int s,const char *c); + KMessageEntry(); + KMessageEntry(KMessageEntry &entry); + KMessageEntry &operator=(KMessageEntry &entry); + ~KMessageEntry(); +}; + +#endif diff --git a/lskat/lskatproc/Makefile.am b/lskat/lskatproc/Makefile.am new file mode 100644 index 00000000..4f99375b --- /dev/null +++ b/lskat/lskatproc/Makefile.am @@ -0,0 +1,13 @@ +bin_PROGRAMS = lskatproc + +lskatproc_SOURCES = lskatproc.cpp KChildConnect.cpp KInputChildProcess.cpp KEMessage.cpp KMessageEntry.cpp main.cpp + +lskatproc_LDADD = $(LIB_KFILE) + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +METASOURCES = AUTO + +# the library search path. +lskatproc_LDFLAGS = $(all_libraries) $(KDE_RPATH) diff --git a/lskat/lskatproc/docs/Makefile.am b/lskat/lskatproc/docs/Makefile.am new file mode 100644 index 00000000..271bd418 --- /dev/null +++ b/lskat/lskatproc/docs/Makefile.am @@ -0,0 +1,4 @@ +####### kdevelop will overwrite this part!!! (begin)########## + + +####### kdevelop will overwrite this part!!! (end)############ diff --git a/lskat/lskatproc/docs/en/Makefile.am b/lskat/lskatproc/docs/en/Makefile.am new file mode 100644 index 00000000..271bd418 --- /dev/null +++ b/lskat/lskatproc/docs/en/Makefile.am @@ -0,0 +1,4 @@ +####### kdevelop will overwrite this part!!! (begin)########## + + +####### kdevelop will overwrite this part!!! (end)############ diff --git a/lskat/lskatproc/lskatproc.cpp b/lskat/lskatproc/lskatproc.cpp new file mode 100644 index 00000000..c1fdcfba --- /dev/null +++ b/lskat/lskatproc/lskatproc.cpp @@ -0,0 +1,596 @@ +/*************************************************************************** + lskatproc.cpp - description + ------------------- + begin : Sun Apr 9 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "lskatproc.h" + +#define MIN_TIME 1000 // usec + +// ------------ class game --------------------------------- +lgame::lgame() +{ + int i; + for (i=0;i<14;i++) cardvalues[i]=0; + cardvalues[(int)Ace]=11; + cardvalues[(int)Ten]=10; + cardvalues[(int)King]=4; + cardvalues[(int)Queen]=3; + cardvalues[(int)Jack]=2; + curmove[0]=-1; + curmove[1]=-1; + score[0]=0; + score[1]=0; + level=0; + endgame=false; + for (i=0;i<NO_OF_CARDS;i++) played[i]=0; +} + +lgame::lgame(lgame &game) +{ + *this=game; +} + +lgame &lgame::operator=(lgame &game) +{ + int i; + currentplayer=game.currentplayer; + startplayer=game.startplayer; + trump=game.trump; + movenumber=game.movenumber; + score[0]=game.score[0]; + score[1]=game.score[1]; + curmove[0]=game.curmove[0]; + curmove[1]=game.curmove[1]; + for (i=0;i<NO_OF_CARDS;i++) played[i]=game.played[i]; + for (i=0;i<NO_OF_CARDS;i++) card[i]=game.card[i]; + for (i=0;i<16;i++) cardheight[i]=game.cardheight[i]; + endgame=game.endgame; + level=game.level; + return *this; +} + +int lgame::MakeMove(int c,int pos) +{ + int h; + curmove[currentplayer]=c; + h=GetHeight(currentplayer,pos); + if (currentplayer==startplayer) + { + movenumber++; + SetHeight(currentplayer,pos,h-1); + currentplayer=1-startplayer; + } + else + { + if (!LegalMove(curmove[startplayer],c)) return -1; + SetHeight(currentplayer,pos,h-1); + if (WonMove(curmove[startplayer],curmove[1-startplayer])) + { + // switch startplayer + startplayer=1-startplayer; + } + currentplayer=startplayer; + score[startplayer]+=CardValue(curmove[0]); + score[startplayer]+=CardValue(curmove[1]); + + if (movenumber==NO_OF_TILES) + { + endgame=true; + return 2; + } + } + return 1; +} + +void lgame::Init() +{ + int player,i,h,j,card; + // check what cards are played + for (player=0;player<2;player++) + { + for (i=0;i<8;i++) + { + h=GetHeight(player,i); + for (j=h;j<2;j++) + { + card=GetCard(player,i,j+1); + if (card>=0) played[card]=1; + } + } + } +} + +// Add value of both cards to the score of startplayer +void lgame::AddScore(int c1,int c2) +{ + score[startplayer]+=CardValue(c1); + score[startplayer]+=CardValue(c2); +} +// Switch the startplayer +void lgame::SwitchStartplayer() +{ + startplayer=1-startplayer; +} + +// pos=0..7, player=0..1 +void lgame::SetHeight(int player, int pos,int h) +{ + int i; + i=8*player+pos; + cardheight[i]=h; +} +bool lgame::LegalMove(int p1, int p2) +{ + CCOLOUR col1,col2,col3; + CCARD card1,card2,card3; + card1=(CCARD)((p1)/4); + col1=(CCOLOUR)((p1)%4); + card2=(CCARD)((p2)/4); + col2=(CCOLOUR)((p2)%4); + + // force trump colour + if (card1==Jack) col1=trump; + if (card2==Jack) col2=trump; + + // same colour always ok + if (col1==col2) return true; + + // Search for same colour + bool flag=true; + for (int i=0;i<8;i++) + { + int h,c; + h=GetHeight(1-startplayer,i); + if (h==0) continue; + c=GetCard(1-startplayer,i,h); + card3=(CCARD)((c)/4); + col3=(CCOLOUR)((c)%4); + if (card3==Jack) col3=trump; + + if (col3==col1) + { + flag=false; + break; + } + } + if (flag) return true; + + + return false; +} +int lgame::CardValue(int card) +{ + int card1; + + card1=card/4; + return cardvalues[card1]; +} +int lgame::WonMove(int c1,int c2) +{ + CCOLOUR col1,col2; + CCARD card1,card2; + + card1=(CCARD)((c1)/4); + col1=(CCOLOUR)((c1)%4); + card2=(CCARD)((c2)/4); + col2=(CCOLOUR)((c2)%4); + + // Two jacks + if (card1==Jack && card2==Jack) + { + if (col1<col2) return 0; + else return 1; + } + // One Jack wins always + if (card1==Jack) return 0; + if (card2==Jack) return 1; + + // higher one wins if same colour + if (col1==col2) + { + if (card1==Ten) + { + if (card2==Ace) return 1; + else return 0; + } + if (card2==Ten) + { + if (card1==Ace) return 0; + return 1; + } + + if ((int)card1<(int)card2) return 0; + return 1; + } + // trump wins + if (col1==trump) return 0; + if (col2==trump) return 1; + + // first one wins + return 0; + +} +// pos=0..7, height=2..1..(0 no card left), player=0..1 +int lgame::GetCard(int player, int pos,int height) +{ + int i; + if (height==0) return -1; + height=2-height; + + i=NO_OF_TILES*player+8*height+pos; + return card[i]; +} + + + +// pos=0..7, player=0..1 +int lgame::GetHeight(int player, int pos) +{ + int i; + i=8*player+pos; + return cardheight[i]; +} + +// Returns a value for the given side +// applies all rules +int lgame::Subvalue(int side) +{ + int sc,card; + int i,h,c; + CCOLOUR col1; + CCARD card1; + int trum1; + int jack1; + int havecol[4]; + bool haveten[4]; + bool haveace[4]; + bool havejack[4]; + + sc=0; + trum1=0; + for (i=0;i<4;i++) + { + havecol[i]=false; + haveten[i]=false; + haveace[i]=false; + havejack[i]=false; + } + jack1=0; + for (i=0;i<8;i++) + { + h=GetHeight(side,i); + c=GetCard(side,i,h); + if (c<0) continue; + + card1=(CCARD)((c)/4); + col1=(CCOLOUR)((c)%4); + + if (col1==trump) trum1++; + havecol[(int)col1]++; + if (card1==Ten) + { + haveten[(int)col1]=true; + } + else if (card1==Ace) + { + haveace[(int)col1]=true; + } + else if (card1==Jack) + { + havejack[(int)col1]=true; + jack1++; + } + if (col1!=trump) + { + if (card1==Seven) sc-=60; + if (card1==Eight) sc-=50; + if (card1==Nine) sc-=40; + if (card1==Queen) sc-=10; + } + } + for (i=0;i<4;i++) + { + if (havecol[i]==0 && i!=trump) sc+=1000; + if (havecol[i]>5) sc+=800; + + if (haveten[i]&&havecol[i]<2) + { + card=8*i+Ace; + if (!played[card] && !haveace[i]) sc-=2500; // free ten + } + if (haveace[i]) sc+=1500; // ace + if (havejack[i]) + { + if (trump==Grand) sc+=4000+300*(4-i); + else sc+=2700+100*(4-i); + } + } + // evaluate + sc+=trum1*2500; + if (trum1==0) sc-=7000; + else if (trum1==1) sc-=5000; + return sc; +} + +int lgame::Value(int player) +{ + int sc; + sc=0; + + // Someone won? + if (score[0]>90) sc+=90000; + else if (score[0]>60) sc+=70000; + else if (score[0]==60) sc+=40000; + + if (score[1]>90) sc-=90000; + else if (score[1]>60) sc-=70000; + else if (score[1]==60) sc-=40000; + + // Reward points + sc+=(score[0]-score[1])*650; + + // Calulate cards + sc+=Subvalue(0); + sc-=Subvalue(1); + + // random + sc+=random(500)-250; + + if (player==1) return -sc; + return sc; +} + + +// -------------class lskatproc ---------------------------- +lskatproc::lskatproc() + : KInputChildProcess(4096) +{ + + initrandom(); +} + +lskatproc::~lskatproc(){ +} + + + +bool lskatproc::ReceiveMsg(KEMessage* msg,int id) +{ +// time_t timee,timea; +short x,y; + + SendDebug("Receiv Msg"); + // end of process + if (msg->HasKey(QCString("Terminate"))) + { + Terminate(); + } + // Init of process + if (msg->HasKey(QCString("Init"))) + { + // No init necessary + } + // Make a move + if (msg->HasKey(QCString("Cards"))) + { + SendDebug("Process HasKey(Cards)"); + // new game object + lgame game; + // extract data from message + game.ExtractGame(msg); + game.Init(); // must be AFTER ExtractGame + + // Debug stuff only + sprintf(buf,"Trump=%d move=%d sc1=%d sc2=%d", + game.trump,game.curmove[1-game.currentplayer],game.score[0],game.score[1]); + SendDebug(buf); + + if (game.currentplayer==0 && game.startplayer==0) + sprintf(buf,"+++ Computer ACTS as player ONE\n"); + else if (game.currentplayer==0 && game.startplayer==1) + sprintf(buf,"+++ Computer REACTS as player ONE\n"); + else if (game.currentplayer==1 && game.startplayer==1) + sprintf(buf,"+++ Computer ACTS as player TWO\n"); + else + sprintf(buf,"+++ Computer REACTS as player TWO\n"); + SendDebug(buf); + + // fills data + x=0;y=0; + GetComputerMove(game,x,y,0); + sprintf(buf,"Computer move player=%d x=%d y=%d",game.currentplayer,x,y); + SendDebug(buf); + + + // report move + msg->RemoveAll(); + msg->AddData(QCString("Move"),game.currentplayer); + msg->AddData(QCString("MoveX"),x); + msg->AddData(QCString("MoveY"),y); + + //timee=time(0); + // Sleep a minimum amount to slow down moves + //if ( 1000*(timee-timea) < MIN_TIME) usleep((MIN_TIME-1000*(timee-timea))); + SendDebug("Sending move back to main"); + + if (!IsTerminated()) SendMsg(msg); + fflush(stdout); // I do not know why it is needed..send does it too? + } + + return true; +} + + +/* --------------------------------------------------------------------------- */ +/* Computer Routinen */ +/* --------------------------------------------------------------------------- */ + +// extract game from msg +int lgame::ExtractGame(KEMessage *msg) +{ + int i; + short tmp; + char *p; + int size; + + msg->GetData(QCString("Startplayer"),startplayer); + msg->GetData(QCString("CurrentPlayer"),currentplayer); + msg->GetData(QCString("Cards"),p,size); + msg->GetData(QCString("Level"),level); + level--; // start with level 0 + for (i=0;i<NO_OF_CARDS;i++) + { + card[i]=((int *)p)[i]; + } + msg->GetData(QCString("Height"),p,size); + for (i=0;i<NO_OF_TILES;i++) + { + cardheight[i]=((int *)p)[i]; + } + msg->GetData(QCString("Trump"),tmp); + trump=(CCOLOUR)tmp; + short mm; + msg->GetData(QCString("CurrentMove"),mm); + curmove[1-currentplayer]=(int)mm; + curmove[currentplayer]=-1; + msg->GetData(QCString("No"),movenumber); + msg->GetData(QCString("Sc1"),score[0]); + msg->GetData(QCString("Sc2"),score[1]); + return 1; +} + +long lgame::random(long max) +{ +double value; +int r; + r=rand(); + value=(double)((double)r*(double)max)/(double)RAND_MAX; + return (long)value; +} + +void lskatproc::initrandom() +{ + srand( (unsigned)time( NULL ) ); // randomize +} + + +int lskatproc::GetComputerMove(lgame game,short &x,short &y,int rek) +{ + int i,maxvalue,maxmove,h,c; + //short oldscore; + bool startflag; + int startplayer; + int value; + lgame cgame; + char sbuf[100]; + short mx,my; + + + for (i=0;i<2*rek;i++) sbuf[i]=' '; + sbuf[2*rek]=0; + + x=0; + y=0; + if (game.currentplayer==game.startplayer) startflag=true; + else startflag=false; + + startplayer=game.startplayer; + + maxmove=0; + maxvalue=LOWERT; + + sprintf(buf,"%s:Prepareing computer move (cur=%d) startflag=%d", + sbuf,game.currentplayer,startflag); + //SendDebug(buf); + for (i=0;i<8;i++) + { + sprintf(buf,"%s:Checking for card %d of player %d\n",sbuf,i,game.currentplayer); + // SendDebug(buf); + cgame=game; + h=cgame.GetHeight(cgame.currentplayer,i); + if (h<1) + { + sprintf(buf,"%s:i=%d:: no cards left",sbuf,i); + // SendDebug(buf); + continue; // no cards left + } + c=cgame.GetCard(cgame.currentplayer,i,h); + if (cgame.MakeMove(c,i)<0) + { + sprintf(buf,"%s:i=%d:: no legal move c1=%d c2=%d", + sbuf,i,cgame.curmove[cgame.startplayer],c); + // SendDebug(buf); + continue; // wrong card + } + if (!startflag) // we are second + { + sprintf(buf,"LEVEL %d %d",cgame.level,rek); + SendDebug(buf); + // Still recursion necessary and game not yet ended? + if (rek<2*cgame.level && !cgame.endgame) + { + // If we have the same startplayer the movesequence + // is not switched and we can take the negative value + // otherwise we play again, and have to take the poitiv value + if (cgame.startplayer==startplayer) + { + value=-GetComputerMove(cgame,mx,my,rek+1); + // if (value==-LOWERT) value=LOWERT; // no move possible + } + else + value=GetComputerMove(cgame,mx,my,rek+1); + } + else // evaluate position + { + value=cgame.Value(1-startplayer); + } + } + else // we are first player + { + // Alwayss the other player moves now + value=-GetComputerMove(cgame,mx,my,rek+1); + } + + sprintf(buf,"%s:i=%d:: Value=%d",sbuf,i,value); + SendDebug(buf); + + if (value>maxvalue) + { + maxvalue=value; + maxmove=i; + } + } + x=maxmove%4; + y=maxmove/4; + return maxvalue; +} + +void lskatproc::SendDebug(const char *s) +{ + KEMessage *msg=new KEMessage; + msg->AddData(QCString("Debug"),s); +// msg->AddData("KLogSendMsg","debug.log"); +// DEBUG +// SendMsg(msg); +// printf("%s\n",s); + + delete msg; +} diff --git a/lskat/lskatproc/lskatproc.h b/lskat/lskatproc/lskatproc.h new file mode 100644 index 00000000..b5840461 --- /dev/null +++ b/lskat/lskatproc/lskatproc.h @@ -0,0 +1,104 @@ +/*************************************************************************** + lskatproc.h - description + ------------------- + begin : Sun Apr 9 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef LSKATPROC_H +#define LSKATPROC_H +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <math.h> +#include <string.h> + +#include "KInputChildProcess.h" + +/** + *@author Martin Heni + */ + + + +#define LOWERT -999999999L +#define SIEG_WERT 9999999L + + +#define START_REK 1 // (0) 1:Nur Stellungsbewertung bei Level 1 + // 0:Level 1 schon eine Rekursion + +typedef enum {Club=0,Spade=1,Heart=2,Diamond=3,Grand=4} CCOLOUR; +typedef enum {Ace=0,King=1,Queen=2,Jack=3,Ten=4,Nine=5,Eight=6,Seven=7} CCARD; +#define NO_OF_CARDS 32 +#define NO_OF_TILES 16 +#define NO_OF_TRUMPS 5 + +class lgame +{ + public: + lgame(); + lgame(lgame &game); + lgame &operator=(lgame &game); + + int WonMove(int c1,int c2); + int CardValue(int card); + bool LegalMove(int p1, int p2); + void SetHeight(int player, int pos,int h); + int GetHeight(int player, int pos); + int GetCard(int player, int pos,int height); + int Value(int player); + void AddScore(int c1,int c2); + void SwitchStartplayer(); + int MakeMove(int c,int pos); + void Init(); + long random(long max); + int Subvalue(int side); + int ExtractGame(KEMessage *msg); + + short currentplayer; + short startplayer; + int card[NO_OF_CARDS]; + int cardheight[16]; + int cardvalues[14]; + short score[2]; + CCOLOUR trump; + short movenumber; + int curmove[2]; + bool endgame; + int played[NO_OF_CARDS]; // cards already played + short level; +}; + + +class lskatproc : public KInputChildProcess +{ + +private: + +public: + lskatproc(); + ~lskatproc(); + + virtual bool ReceiveMsg(KEMessage *msg,int id); + + + void initrandom(); + int GetComputerMove(lgame game,short &x,short &y,int rek); + void SendDebug(const char *s); + + private: + char buf[1024]; +}; + +#endif diff --git a/lskat/lskatproc/main.cpp b/lskat/lskatproc/main.cpp new file mode 100644 index 00000000..d25cd8c9 --- /dev/null +++ b/lskat/lskatproc/main.cpp @@ -0,0 +1,28 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Sun Apr 9 22:56:15 CEST 2000 + copyright : (C) 2000 by Martin Heni + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <stdio.h> +#include "lskatproc.h" + + + + +int main(int argc, char *argv[]) +{ + lskatproc mComm; + return mComm.exec() ? 0 : 1; +} diff --git a/lskat/lskatproc/templates/cpp_template b/lskat/lskatproc/templates/cpp_template new file mode 100644 index 00000000..6afef5d4 --- /dev/null +++ b/lskat/lskatproc/templates/cpp_template @@ -0,0 +1,16 @@ +/*************************************************************************** + |FILENAME| - description + ------------------- + begin : |DATE| + copyright : (C) |YEAR| by |AUTHOR| + email : |EMAIL| + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ diff --git a/lskat/lskatproc/templates/header_template b/lskat/lskatproc/templates/header_template new file mode 100644 index 00000000..6afef5d4 --- /dev/null +++ b/lskat/lskatproc/templates/header_template @@ -0,0 +1,16 @@ +/*************************************************************************** + |FILENAME| - description + ------------------- + begin : |DATE| + copyright : (C) |YEAR| by |AUTHOR| + email : |EMAIL| + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ |