author | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
commit | 5042e3cf0d3514552769e441f5aad590c8eaf967 (patch) (side-by-side diff) | |
tree | 4a5ea45f3519d981a172ab5275bf38c6fa778dec /qmake | |
parent | 108c1c753e74e989cc13923086996791428c9af4 (diff) | |
download | opie-5042e3cf0d3514552769e441f5aad590c8eaf967.zip opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.gz opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.bz2 |
Adding qmake in preperation for new build system
147 files changed, 78867 insertions, 0 deletions
diff --git a/qmake/CHANGES b/qmake/CHANGES new file mode 100644 index 0000000..995c16e --- a/dev/null +++ b/qmake/CHANGES @@ -0,0 +1,40 @@ +1.04a - + + subdirs supports multiple project files in a single directory. + +1.03a - + + New function $$system() to extract the value of a shell call. + +1.02a - + + Dependancy / Mocable caching. qmake can cache these expensive operations with qmake_cache + CONFIG. + + The parser has been improved to cover more error cases, as well as more forgiving + + qmake now includes a special else scope to invert the previous test + + Ability to add user defined targets to UnixMakefiles. + +1.01a - + + New system for library linking. This system allows a user several different features: + + 1) libtool like library dependancies to static libraries build with qmake + 2) library dependencies, when on .pro depends on another library - it will + automatically build that other library (unix makefiles only) + 3) automatic detection of configurations for Qt, if CONFIG qt is specified + it will find the settings for the most recent Qt itself. + + Project Builder for Mac OS X is now a supported backend for qmake. + + qmake now offers a 'make uninstall' feature, to reverse the actions of a 'make install'. + + qmake can now do recursive searches in project-file mode (-r option). + +1.00a - + + First release, shipped with Qt 3.0. + + qmake ships with support for Unix make, MSVC (both dsp and nmake), Borland make. diff --git a/qmake/LICENSE.GPL b/qmake/LICENSE.GPL new file mode 100644 index 0000000..1700eb1 --- a/dev/null +++ b/qmake/LICENSE.GPL @@ -0,0 +1,349 @@ + + The Qt GUI Toolkit is Copyright (C) 1994-2000 Trolltech AS. + + You may use, distribute and copy the Qt GUI Toolkit under the terms of + GNU General Public License version 2, which is displayed below. + +------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 + + Appendix: 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., 675 Mass Ave, Cambridge, MA 02139, 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/qmake/Makefile b/qmake/Makefile new file mode 100644 index 0000000..104cc44 --- a/dev/null +++ b/qmake/Makefile @@ -0,0 +1,173 @@ +TOPDIR=$(shell pwd) +QMAKESPECSDIR=$(OPIEDIR) + +######################################################################## +## This file was autogenerated by configure, all changes will be lost ## +######################################################################## +CC = gcc +CXX = g++ + +#qmake code +OBJS=project.o main.o makefile.o unixmake2.o unixmake.o borland_bmake.o \ + msvc_nmake.o msvc_dsp.o msvc_vcproj.o option.o winmakefile.o \ + projectgenerator.o metrowerks_xml.o pbuilder_pbx.o msvc_objectmodel.o + +#qt code +QOBJS=qstring.o qtextstream.o qiodevice.o qglobal.o qgdict.o qcstring.o \ + qdatastream.o qgarray.o qbuffer.o qglist.o qptrcollection.o qfile.o \ + qfile_unix.o qregexp.o qgvector.o qgcache.o qbitarray.o qdir.o \ + qfileinfo_unix.o qdir_unix.o qfileinfo.o qdatetime.o qstringlist.o qmap.o \ + qconfig.o + +CFLAGS= \ + -I. -Igenerators -Igenerators/unix -Igenerators/win32 -Igenerators/mac \ + -I$(TOPDIR)/include -I$(TOPDIR)/include/qmake -I$(QMAKESPECSDIR)/default \ + -I$(TOPDIR)/include/private \ + -DQT_NO_TEXTCODEC -DQT_LITE_COMPONENT -DQT_NO_STL -DQT_NO_COMPRESS -I$(QMAKESPECDIR)/qws/linux-x86-g++ +CXXFLAGS= $(CFLAGS) +LFLAGS= + +qmake: $(OBJS) $(QOBJS) + $(CXX) -o $@ $(OBJS) $(QOBJS) $(LFLAGS) + $(if $(OPIEDIR),rm -f $(OPIEDIR)/bin/$@) + $(if $(OPIEDIR),ln -s ../qmake/$@ $(OPIEDIR)/bin/$@) + +install: qmake + [ -d $(INSTALL_ROOT)$(QTDIR)/bin ] || mkdir -p $(INSTALL_ROOT)$(QTDIR)/bin + -cp -f $(QTDIR)/bin/qmake $(INSTALL_ROOT)$(QTDIR)/bin + [ -d $(INSTALL_ROOT)$(QTDIR) ] || mkdir -p $(INSTALL_ROOT)$(QTDIR) + -cp -r -f $(QMAKESPECDIR) $(INSTALL_ROOT)$(QTDIR) + +clean:: + rm -f $(OBJS) $(QOBJS) + +distclean:: clean + rm -rf qmake .deps + +# don't use optimization for these +qtextstream.o: $(TOPDIR)/tools/qtextstream.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qtextstream.cpp + +qiodevice.o: $(TOPDIR)/tools/qiodevice.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qiodevice.cpp + +qglobal.o: $(TOPDIR)/tools/qglobal.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qglobal.cpp + +qgdict.o: $(TOPDIR)/tools/qgdict.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qgdict.cpp + +qcstring.o: $(TOPDIR)/tools/qcstring.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qcstring.cpp + +qstring.o: $(TOPDIR)/tools/qstring.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qstring.cpp + +qdatastream.o: $(TOPDIR)/tools/qdatastream.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qdatastream.cpp + +qgarray.o: $(TOPDIR)/tools/qgarray.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qgarray.cpp + +qbuffer.o: $(TOPDIR)/tools/qbuffer.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qbuffer.cpp + +qglist.o: $(TOPDIR)/tools/qglist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qglist.cpp + +qptrcollection.o: $(TOPDIR)/tools/qptrcollection.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qptrcollection.cpp + +qfile.o: $(TOPDIR)/tools/qfile.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qfile.cpp + +qfile_unix.o: $(TOPDIR)/tools/qfile_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qfile_unix.cpp + +qregexp.o: $(TOPDIR)/tools/qregexp.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qregexp.cpp + +qgvector.o: $(TOPDIR)/tools/qgvector.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qgvector.cpp + +qgcache.o: $(TOPDIR)/tools/qgcache.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qgcache.cpp + +qbitarray.o: $(TOPDIR)/tools/qbitarray.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qbitarray.cpp + +qdir.o: $(TOPDIR)/tools/qdir.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qdir.cpp + +qfileinfo_unix.o: $(TOPDIR)/tools/qfileinfo_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qfileinfo_unix.cpp + +qdir_unix.o: $(TOPDIR)/tools/qdir_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qdir_unix.cpp + +qfileinfo.o: $(TOPDIR)/tools/qfileinfo.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qfileinfo.cpp + +qdatetime.o: $(TOPDIR)/tools/qdatetime.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qdatetime.cpp + +qstringlist.o: $(TOPDIR)/tools/qstringlist.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qstringlist.cpp + +qmap.o: $(TOPDIR)/tools/qmap.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qmap.cpp + +qconfig.o: $(TOPDIR)/tools/qconfig.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(TOPDIR)/tools/qconfig.cpp + +winmakefile.o: generators/win32/winmakefile.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/winmakefile.cpp + +project.o: project.cpp project.h option.h + $(CXX) -c -o $@ $(CXXFLAGS) project.cpp + +main.o: main.cpp project.h + $(CXX) -c -o $@ $(CXXFLAGS) main.cpp + +option.o: option.cpp option.h + $(CXX) -c -o $@ $(CXXFLAGS) option.cpp + +makefile.o: generators/makefile.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/makefile.cpp + +unixmake.o: generators/unix/unixmake.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/unix/unixmake.cpp + +unixmake2.o: generators/unix/unixmake2.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/unix/unixmake2.cpp + +borland_bmake.o: generators/win32/borland_bmake.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/borland_bmake.cpp + +msvc_objectmodel.o: generators/win32/msvc_objectmodel.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp + +msvc_vcproj.o: generators/win32/msvc_vcproj.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_vcproj.cpp + +msvc_nmake.o: generators/win32/msvc_nmake.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_nmake.cpp + +metrowerks_xml.o: generators/mac/metrowerks_xml.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/mac/metrowerks_xml.cpp + +pbuilder_pbx.o: generators/mac/pbuilder_pbx.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp + +msvc_dsp.o: generators/win32/msvc_dsp.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_dsp.cpp + +projectgenerator.o: generators/projectgenerator.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/projectgenerator.cpp + +#default rules +.c.o: + $(CC) -c -o $@ $(CFLAGS) $< + +.cpp.o: + $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/generators/mac/metrowerks_xml.cpp b/qmake/generators/mac/metrowerks_xml.cpp new file mode 100644 index 0000000..125749d --- a/dev/null +++ b/qmake/generators/mac/metrowerks_xml.cpp @@ -0,0 +1,822 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "metrowerks_xml.h" +#include "option.h" +#include <qdir.h> +#include <qdict.h> +#include <qregexp.h> +#include <stdlib.h> +#include <time.h> +#ifdef Q_OS_MAC +#include <Carbon/Carbon.h> +#include <sys/types.h> +#include <sys/stat.h> +#endif + + +MetrowerksMakefileGenerator::MetrowerksMakefileGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE) +{ + +} + +bool +MetrowerksMakefileGenerator::writeMakefile(QTextStream &t) +{ + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + /* for now just dump, I need to generated an empty xml or something.. */ + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + if(project->first("TEMPLATE") == "app" || + project->first("TEMPLATE") == "lib") { + return writeMakeParts(t); + } + else if(project->first("TEMPLATE") == "subdirs") { + writeHeader(t); + qDebug("Not supported!"); + return TRUE; + } + return FALSE; +} + +bool +MetrowerksMakefileGenerator::writeMakeParts(QTextStream &t) +{ + //..grrr.. libs! + QStringList extra_objs; + bool do_libs = TRUE; + if(project->first("TEMPLATE") == "app") + extra_objs += project->variables()["QMAKE_CRT_OBJECTS"]; + else if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) + do_libs = FALSE; + if(do_libs) + extra_objs += project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator val_it = extra_objs.begin(); + val_it != extra_objs.end(); ++val_it) { + if((*val_it).startsWith("-L")) { + QString dir((*val_it).right((*val_it).length() - 2)); + fixEnvVariables(dir); + if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 && + project->variables()["INCLUDEPATH"].findIndex(dir) == -1) + project->variables()["INCLUDEPATH"].append(dir); + } else if((*val_it).startsWith("-l")) { + QString lib("lib" + (*val_it).right((*val_it).length() - 2) + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + if(project->variables()["LIBRARIES"].findIndex(lib) == -1) + project->variables()["LIBRARIES"].append(lib); + } else + if((*val_it) == "-framework") { + ++val_it; + if(val_it == extra_objs.end()) + break; + QString frmwrk = (*val_it) + ".framework"; + if(project->variables()["FRAMEWORKS"].findIndex(frmwrk) == -1) + project->variables()["FRAMEWORKS"].append(frmwrk); + } else if((*val_it).left(1) != "-") { + QString lib=(*val_it); + int s = lib.findRev('/'); + if(s != -1) { + QString dir = lib.left(s); + lib = lib.right(lib.length() - s - 1); + fixEnvVariables(dir); + if(project->variables()["DEPENDPATH"].findIndex(dir) == -1 && + project->variables()["INCLUDEPATH"].findIndex(dir) == -1) + project->variables()["INCLUDEPATH"].append(dir); + } + project->variables()["LIBRARIES"].append(lib); + } + } + //let metrowerks find the files & set the files to the type I expect + QDict<void> seen(293); + QString paths[] = { QString("SRCMOC"), QString("FORMS"), QString("UICDECLS"), + QString("UICIMPLS"), QString("SOURCES"),QString("HEADERS"), + QString::null }; + for(int y = 0; paths[y] != QString::null; y++) { + QStringList &l = project->variables()[paths[y]]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { + //establish file types + seen.insert((*val_it), (void *)1); + createFork((*val_it)); //the file itself + QStringList &d = findDependencies((*val_it)); //depends + for(QStringList::Iterator dep_it = d.begin(); dep_it != d.end(); ++dep_it) { + if(!seen.find((*dep_it))) { + seen.insert((*dep_it), (void *)1); + createFork((*dep_it)); + } + } + //now chop it + int s = (*val_it).findRev('/'); + if(s != -1) { + QString dir = (*val_it).left(s); + (*val_it) = (*val_it).right((*val_it).length() - s - 1); + QString tmpd=dir, tmpv; + if(fixifyToMacPath(tmpd, tmpv)) { + bool add_in = TRUE; + QString deps[] = { QString("DEPENDPATH"), + QString("INCLUDEPATH"), QString::null }, + dd, dv; + for(int yy = 0; deps[yy] != QString::null; yy++) { + QStringList &l2 = project->variables()[deps[yy]]; + for(QStringList::Iterator val_it2 = l2.begin(); + val_it2 != l2.end(); ++val_it2) { + QString dd= (*val_it2), dv; + if(!fixifyToMacPath(dd, dv)) + continue; + if(dd == tmpd && tmpv == dv) { + add_in = FALSE; + break; + } + } + } + if(add_in) + project->variables()["INCLUDEPATH"].append(dir); + } + } + } + } + //need a defines file + if(!project->isEmpty("DEFINES")) { + QString pre_pref = project->first("TARGET_STEM"); + if(project->first("TEMPLATE") == "lib") + pre_pref += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["CODEWARRIOR_PREFIX_HEADER"].append(pre_pref + "_prefix.h"); + } + + QString xmlfile = findTemplate(project->first("QMAKE_XML_TEMPLATE")); + QFile file(xmlfile); + if(!file.open(IO_ReadOnly )) { + fprintf(stderr, "Cannot open XML file: %s\n", + project->first("QMAKE_XML_TEMPLATE").latin1()); + return FALSE; + } + QTextStream xml(&file); + createFork(Option::output.name()); + + int rep; + QString line; + while ( !xml.eof() ) { + line = xml.readLine(); + while((rep = line.find(QRegExp("\\$\\$[!a-zA-Z0-9_-]*"))) != -1) { + QString torep = line.mid(rep, line.find(QRegExp("[^\\$!a-zA-Z0-9_-]"), rep) - rep); + QString variable = torep.right(torep.length()-2); + + t << line.left(rep); //output the left side + line = line.right(line.length() - (rep + torep.length())); //now past the variable + if(variable == "CODEWARRIOR_HEADERS" || variable == "CODEWARRIOR_SOURCES" || + variable == "CODEWARRIOR_LIBRARIES" || variable == "CODEWARRIOR_QPREPROCESS" || + variable == "CODEWARRIOR_QPREPROCESSOUT") { + QString outcmd=variable.right(variable.length() - variable.findRev('_') - 1); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + QString kind = "Text"; + if(arg == "LIBRARIES") + kind = "Library"; + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString flag; + if(project->isActiveConfig("debug")) { + bool debug = TRUE; + if(outcmd == "QPREPROCESS") { + debug = FALSE; + } else { + for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { + if((*it).endsWith((*hit))) { + debug = FALSE; + break; + } + } + } + if(debug) + flag = "Debug"; + } + t << "\t\t\t\t<FILE>" << endl + << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl + << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl + << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl + << "\t\t\t\t\t<FILEKIND>" << kind << "</FILEKIND>" << endl + << "\t\t\t\t\t<FILEFLAGS>" << flag << "</FILEFLAGS>" << endl + << "\t\t\t\t</FILE>" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_SOURCES_LINKORDER" || + variable == "CODEWARRIOR_HEADERS_LINKORDER" || + variable == "CODEWARRIOR_LIBRARIES_LINKORDER" || + variable == "CODEWARRIOR_QPREPROCESS_LINKORDER" || + variable == "CODEWARRIOR_QPREPROCESSOUT_LINKORDER") { + QString outcmd=variable.mid(variable.find('_')+1, + variable.findRev('_')-(variable.find('_')+1)); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t<FILEREF>" << endl + << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl + << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl + << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl + << "\t\t\t\t</FILEREF>" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_HEADERS_GROUP" || + variable == "CODEWARRIOR_SOURCES_GROUP" || + variable == "CODEWARRIOR_LIBRARIES_GROUP" || + variable == "CODEWARRIOR_QPREPROCESS_GROUP" || + variable == "CODEWARRIOR_QPREPROCESSOUT_GROUP") { + QString outcmd = variable.mid(variable.find('_')+1, + variable.findRev('_')-(variable.find('_')+1)); + QStringList args; + if(outcmd == "QPREPROCESS") + args << "UICS" << "MOCS"; + else if(outcmd == "QPREPROCESSOUT") + args << "SRCMOC" << "UICIMPLS" << "UICDELCS"; + else + args << outcmd; + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString arg = (*arit); + if(!project->variables()[arg].isEmpty()) { + QStringList &list = project->variables()[arg]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t<FILEREF>" << endl + << "\t\t\t\t\t<TARGETNAME>" << var("TARGET_STEM") << "</TARGETNAME>" + << endl + << "\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl + << "\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl + << "\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl + << "\t\t\t\t</FILEREF>" << endl; + } + } + } + } else if(variable == "CODEWARRIOR_FRAMEWORKS") { + if(!project->isEmpty("FRAMEWORKS")) { + QStringList &list = project->variables()["FRAMEWORKS"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "\t\t\t\t<FRAMEWORK>" << endl + << "\t\t\t\t\t<FILEREF>" << endl + << "\t\t\t\t\t\t<PATHTYPE>Name</PATHTYPE>" << endl + << "\t\t\t\t\t\t<PATH>" << (*it) << "</PATH>" << endl + << "\t\t\t\t\t\t<PATHFORMAT>MacOS</PATHFORMAT>" << endl + << "\t\t\t\t\t</FILEREF>" << endl + << "\t\t\t\t</FRAMEWORK>" << endl; + } + } + } else if(variable == "CODEWARRIOR_DEPENDPATH" || variable == "CODEWARRIOR_INCLUDEPATH" || + variable == "CODEWARRIOR_FRAMEWORKPATH") { + QString arg=variable.right(variable.length()-variable.find('_')-1); + QStringList list; + if(arg == "INCLUDEPATH") { + list = project->variables()[arg]; + list << Option::mkfile::qmakespec; + list << QDir::current().currentDirPath(); + + QStringList &l = project->variables()["QMAKE_LIBS_PATH"]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { + QString p = (*val_it), v; + if(!fixifyToMacPath(p, v)) + continue; + + t << "\t\t\t\t\t<SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>SearchPath</NAME>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>Path</NAME>" + << "<VALUE>" << p << "</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t</SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>" << endl + << "\t\t\t\t\t</SETTING>" << endl; + } + } else if(variable == "DEPENDPATH") { + QStringList &l = project->variables()[arg]; + for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) + { + //apparently tmake used colon separation... + QStringList damn = QStringList::split(':', (*val_it)); + if(!damn.isEmpty()) + list += damn; + else + list.append((*val_it)); + } + } else { + list = project->variables()[arg]; + } + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString p = (*it), v, recursive = "false", framework = "false"; + if(p.startsWith("recursive--")) { + p = p.right(p.length() - 11); + recursive = "true"; + } + if(!fixifyToMacPath(p, v)) + continue; + if(arg == "FRAMEWORKPATH") + framework = "true"; + + t << "\t\t\t\t\t<SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>SearchPath</NAME>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>Path</NAME>" + << "<VALUE>" << p << "</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << v << "</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t</SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>Recursive</NAME><VALUE>" << recursive << "</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>FrameworkPath</NAME><VALUE>" << framework << "</VALUE></SETTING>" << endl + << "\t\t\t\t\t\t<SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>" << endl + << "\t\t\t\t\t</SETTING>" << endl; + } + } else if(variable == "CODEWARRIOR_WARNING" || variable == "!CODEWARRIOR_WARNING") { + bool b = ((!project->isActiveConfig("warn_off")) && + project->isActiveConfig("warn_on")); + if(variable.startsWith("!")) + b = !b; + t << (int)b; + } else if(variable == "CODEWARRIOR_TEMPLATE") { + if(project->first("TEMPLATE") == "app" ) { + t << "Executable"; + } else if(project->first("TEMPLATE") == "lib") { + if(project->isActiveConfig("staticlib")) + t << "Library"; + else + t << "SharedLibrary"; + } + } else if(variable == "CODEWARRIOR_OUTPUT_DIR") { + QString outdir = "{Project}/", volume; + if(!project->isEmpty("DESTDIR")) + outdir = project->first("DESTDIR"); + if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console")) + outdir += var("TARGET") + ".app/Contents/MacOS/"; + if(fixifyToMacPath(outdir, volume, FALSE)) { + t << "\t\t\t<SETTING><NAME>Path</NAME><VALUE>" << outdir << "</VALUE></SETTING>" + << endl + << "\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" << endl + << "\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << volume << "</VALUE></SETTING>" + << endl; + } + } else if(variable == "CODEWARRIOR_PACKAGER_PANEL") { + if(project->first("TEMPLATE") == "app" && !project->isActiveConfig("console")) { + QString outdir = "{Project}/", volume; + if(!project->isEmpty("DESTDIR")) + outdir = project->first("DESTDIR"); + outdir += var("TARGET") + ".app"; + if(fixifyToMacPath(outdir, volume, FALSE)) { + t << "\t\t<SETTING><NAME>MWMacOSPackager_UsePackager</NAME>" + << "<VALUE>1</VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_FolderToPackage</NAME>" << "\n" + << "\t\t\t<SETTING><NAME>Path</NAME><VALUE>" << outdir + << "</VALUE></SETTING>" << "\n" + << "\t\t\t<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>" + << "\n" + << "\t\t\t<SETTING><NAME>PathRoot</NAME><VALUE>" << volume + << "</VALUE></SETTING>" << "\n" + << "\t\t</SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_CreateClassicAlias</NAME>" + << "<VALUE>0</VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_ClassicAliasMethod</NAME>" + << "<VALUE>UseTargetOutput</VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_ClassicAliasPath</NAME>" + << "<VALUE></VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_CreatePkgInfo</NAME>" + << "<VALUE>1</VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_PkgCreatorType</NAME>" + << "<VALUE>CUTE</VALUE></SETTING>" << "\n" + << "\t\t<SETTING><NAME>MWMacOSPackager_PkgFileType</NAME>" + << "<VALUE>APPL</VALUE></SETTING>" << endl; + } + } + } else if(variable == "CODEWARRIOR_FILETYPE") { + if(project->first("TEMPLATE") == "lib") + t << "MYDL"; + else + t << "MEXE"; + } else if(variable == "CODEWARRIOR_QTDIR") { + t << getenv("QTDIR"); + } else if(variable == "CODEWARRIOR_CACHEMODDATES") { + t << "true"; + } else { + t << var(variable); + } + } + t << line << endl; + } + t << endl; + file.close(); + + if(mocAware()) { + QString mocs = project->first("MOCS"); + QFile mocfile(mocs); + if(!mocfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open MOCS file: %s\n", mocs.latin1()); + } else { + createFork(mocs); + QTextStream mocs(&mocfile); + QStringList &list = project->variables()["SRCMOC"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString src = findMocSource((*it)); + if(src.findRev('/') != -1) + src = src.right(src.length() - src.findRev('/') - 1); + mocs << src << endl; + } + mocfile.close(); + } + } + + if(!project->isEmpty("FORMS")) { + QString uics = project->first("UICS"); + QFile uicfile(uics); + if(!uicfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open UICS file: %s\n", uics.latin1()); + } else { + createFork(uics); + QTextStream uics(&uicfile); + QStringList &list = project->variables()["FORMS"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString ui = (*it); + if(ui.findRev('/') != -1) + ui = ui.right(ui.length() - ui.findRev('/') - 1); + uics << ui << endl; + } + uicfile.close(); + } + } + + if(!project->isEmpty("CODEWARRIOR_PREFIX_HEADER")) { + QFile prefixfile(project->first("CODEWARRIOR_PREFIX_HEADER")); + if(!prefixfile.open(IO_WriteOnly)) { + fprintf(stderr, "Cannot open PREFIX file: %s\n", prefixfile.name().latin1()); + } else { + createFork(project->first("CODEWARRIOR_PREFIX_HEADER")); + QTextStream prefix(&prefixfile); + QStringList &list = project->variables()["DEFINES"]; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + if((*it).find('=') != -1) { + int x = (*it).find('='); + prefix << "#define " << (*it).left(x) << " " << (*it).right((*it).length() - x - 1) << endl; + } else { + prefix << "#define " << (*it) << endl; + } + } + prefixfile.close(); + } + } + return TRUE; +} + + + +void +MetrowerksMakefileGenerator::init() +{ + if(init_flag) + return; + init_flag = TRUE; + + if ( project->isEmpty("QMAKE_XML_TEMPLATE") ) + project->variables()["QMAKE_XML_TEMPLATE"].append("mwerkstmpl.xml"); + + QStringList &configs = project->variables()["CONFIG"]; + if(project->isActiveConfig("qt")) { + if(configs.findIndex("moc")) configs.append("moc"); + if ( !( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") || + (project->first("TARGET") == "qt-mt") ) ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if(configs.findIndex("moc")) + configs.append("moc"); + if ( !project->isActiveConfig("debug") ) + project->variables()["DEFINES"].append("QT_NO_DEBUG"); + } + + //version handling + if(project->variables()["VERSION"].isEmpty()) + project->variables()["VERSION"].append("1.0." + + (project->isEmpty("VER_PAT") ? QString("0") : + project->first("VER_PAT")) ); + QStringList ver = QStringList::split('.', project->first("VERSION")); + ver << "0" << "0"; //make sure there are three + project->variables()["VER_MAJ"].append(ver[0]); + project->variables()["VER_MIN"].append(ver[1]); + project->variables()["VER_PAT"].append(ver[2]); + + if( !project->isEmpty("LIBS") ) + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + if( project->variables()["QMAKE_EXTENSION_SHLIB"].isEmpty() ) + project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dylib" ); + + if ( project->isActiveConfig("moc") ) { + QString mocfile = project->first("TARGET"); + if(project->first("TEMPLATE") == "lib") + mocfile += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["MOCS"].append(mocfile + ".mocs"); + setMocAware(TRUE); + } + if(!project->isEmpty("FORMS")) { + QString uicfile = project->first("TARGET"); + if(project->first("TEMPLATE") == "lib") + uicfile += project->isActiveConfig("staticlib") ? "_static" : "_shared"; + project->variables()["UICS"].append(uicfile + ".uics"); + } + if(project->isEmpty("DESTDIR")) + project->variables()["DESTDIR"].append(QDir::currentDirPath()); + MakefileGenerator::init(); + + if ( project->isActiveConfig("opengl") ) { + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_OPENGL"]; + if ( (project->first("TARGET") == "qt") || (project->first("TARGET") == "qte") || + (project->first("TARGET") == "qt-mt") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL_QT"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + } + + if(project->isActiveConfig("qt")) + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + if(project->isEmpty("FRAMEWORKPATH")) + project->variables()["FRAMEWORKPATH"].append("/System/Library/Frameworks/"); + + //set the target up + project->variables()["TARGET_STEM"] = project->variables()["TARGET"]; + if(project->first("TEMPLATE") == "lib") { + if(project->isActiveConfig("staticlib")) + project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + ".lib"; + else + project->variables()["TARGET"].first() = "lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB"); + + project->variables()["CODEWARRIOR_VERSION"].append(project->first("VER_MAJ") + + project->first("VER_MIN") + + project->first("VER_PAT")); + } else { + project->variables()["CODEWARRIOR_VERSION"].append("0"); + if(project->isEmpty("QMAKE_ENTRYPOINT")) + project->variables()["QMAKE_ENTRYPOINT"].append("start"); + project->variables()["CODEWARRIOR_ENTRYPOINT"].append( + project->first("QMAKE_ENTRYPOINT")); + } +} + + +QString +MetrowerksMakefileGenerator::findTemplate(QString file) +{ + QString ret; + if(!QFile::exists(ret = file) && + !QFile::exists((ret = Option::mkfile::qmakespec + QDir::separator() + file)) && + !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/mac-mwerks/" + file)) && + !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) + return ""; + return ret; +} + +bool +MetrowerksMakefileGenerator::createFork(const QString &f) +{ +#if defined(Q_OS_MACX) + FSRef fref; + FSSpec fileSpec; + if(QFile::exists(f)) { + mode_t perms = 0; + { + struct stat s; + stat(f.latin1(), &s); + if(!(s.st_mode & S_IWUSR)) { + perms = s.st_mode; + chmod(f.latin1(), perms | S_IWUSR); + } + } + FILE *o = fopen(f.latin1(), "a"); + if(!o) + return FALSE; + if(FSPathMakeRef((const UInt8 *)f.latin1(), &fref, NULL) == noErr) { + if(FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL) == noErr) + FSpCreateResFile(&fileSpec, 'CUTE', 'TEXT', smSystemScript); + else + qDebug("bogus %d", __LINE__); + } else + qDebug("bogus %d", __LINE__); + fclose(o); + if(perms) + chmod(f.latin1(), perms); + } +#else + Q_UNUSED(f) +#endif + return TRUE; +} + +bool +MetrowerksMakefileGenerator::fixifyToMacPath(QString &p, QString &v, bool ) +{ + v = "Absolute"; + if(p.find(':') != -1) //guess its macish already + return TRUE; + + static QString st_volume; + if(st_volume.isEmpty()) { + st_volume = var("QMAKE_VOLUMENAME"); +#ifdef Q_OS_MAC + if(st_volume.isEmpty()) { + uchar foo[512]; + HVolumeParam pb; + memset(&pb, '\0', sizeof(pb)); + pb.ioVRefNum = 0; + pb.ioNamePtr = foo; + if(PBHGetVInfoSync((HParmBlkPtr)&pb) == noErr) { + int len = foo[0]; + memcpy(foo,foo+1, len); + foo[len] = '\0'; + st_volume = (char *)foo; + } + } +#endif + } + QString volume = st_volume; + + fixEnvVariables(p); + if(p.startsWith("\"") && p.endsWith("\"")) + p = p.mid(1, p.length() - 2); + if(p.isEmpty()) + return FALSE; + if(!p.endsWith("/")) + p += "/"; + if(QDir::isRelativePath(p)) { + if(p.startsWith("{")) { + int eoc = p.find('}'); + if(eoc == -1) + return FALSE; + volume = p.mid(1, eoc - 1); + p = p.right(p.length() - eoc - 1); + } else { + QFileInfo fi(p); + if(fi.convertToAbs()) //strange + return FALSE; + p = fi.filePath(); + } + } + p = QDir::cleanDirPath(p); + if(!volume.isEmpty()) + v = volume; + p.replace("/", ":"); + if(p.right(1) != ":") + p += ':'; + return TRUE; +} + +void +MetrowerksMakefileGenerator::processPrlFiles() +{ + QPtrList<MakefileDependDir> libdirs; + libdirs.setAutoDelete(TRUE); + const QString lflags[] = { "QMAKE_LIBS", QString::null }; + for(int i = 0; !lflags[i].isNull(); i++) { + for(bool ret = FALSE; TRUE; ret = FALSE) { + QStringList l_out; + QStringList &l = project->variables()[lflags[i]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString opt = (*it); + if(opt.startsWith("-")) { + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace( "\"", ""), + l.replace( "\"", ""))); + } else if(opt.left(2) == "-l") { + QString lib = opt.right(opt.length() - 2), prl; + for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { + prl = mdd->local_dir + Option::dir_sep + "lib" + lib + Option::prl_ext; + if(processPrlFile(prl)) { + if(prl.startsWith(mdd->local_dir)) + prl.replace(0, mdd->local_dir.length(), mdd->real_dir); + QRegExp reg("^.*lib(" + lib + "[^.]*)\\." + + project->first("QMAKE_EXTENSION_SHLIB") + "$"); + if(reg.exactMatch(prl)) + prl = "-l" + reg.cap(1); + opt = prl; + ret = TRUE; + break; + } + } + } else if(opt == "-framework") { + l_out.append(opt); + ++it; + opt = (*it); + QString prl = "/System/Library/Frameworks/" + opt + + ".framework/" + opt + Option::prl_ext; + if(processPrlFile(prl)) + ret = TRUE; + } + if(!opt.isEmpty()) + l_out.append(opt); + } else { + if(processPrlFile(opt)) + ret = TRUE; + if(!opt.isEmpty()) + l_out.append(opt); + } + } + if(ret) + l = l_out; + else + break; + } + } +} + +void +MetrowerksMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) +{ + if(var == "QMAKE_PRL_LIBS") { + QStringList &out = project->variables()["QMAKE_LIBS"]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + bool append = TRUE; + if((*it).startsWith("-")) { + if((*it).startsWith("-l") || (*it).startsWith("-L")) { + append = out.findIndex((*it)) == -1; + } else if((*it).startsWith("-framework")) { + ++it; + for(QStringList::ConstIterator outit = out.begin(); + outit != out.end(); ++it) { + if((*outit) == "-framework") { + ++outit; + if((*outit) == (*it)) { + append = FALSE; + break; + } + } + } + } + } else if(QFile::exists((*it))) { + append = out.findIndex((*it)); + } + if(append) + out.append((*it)); + } + } else { + MakefileGenerator::processPrlVariable(var, l); + } +} + + +bool +MetrowerksMakefileGenerator::openOutput(QFile &file) const +{ + QString outdir; + if(!file.name().isEmpty()) { + QFileInfo fi(file); + if(fi.isDir()) + outdir = file.name() + QDir::separator(); + } + if(!outdir.isEmpty() || file.name().isEmpty()) + file.setName(outdir + project->first("TARGET") + ".xml"); + return MakefileGenerator::openOutput(file); +} diff --git a/qmake/generators/mac/metrowerks_xml.h b/qmake/generators/mac/metrowerks_xml.h new file mode 100644 index 0000000..ae3cfae --- a/dev/null +++ b/qmake/generators/mac/metrowerks_xml.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __METROWERKSMAKE_H__ +#define __METROWERKSMAKE_H__ + +#include "makefile.h" + +class MetrowerksMakefileGenerator : public MakefileGenerator +{ + bool createFork(const QString &f); + bool fixifyToMacPath(QString &c, QString &v, bool exists=TRUE); + + bool init_flag; + + bool writeMakeParts(QTextStream &); + bool writeSubDirs(QTextStream &); + + bool writeMakefile(QTextStream &); + QString findTemplate(QString file); + void init(); +public: + MetrowerksMakefileGenerator(QMakeProject *p); + ~MetrowerksMakefileGenerator(); + + bool openOutput(QFile &file) const; +protected: + virtual void processPrlFiles(); + virtual void processPrlVariable(const QString &var, const QStringList &l); + virtual bool doDepends() const { return FALSE; } //never necesary +}; + +inline MetrowerksMakefileGenerator::~MetrowerksMakefileGenerator() +{ } + +#endif /* __METROWERKSMAKE_H__ */ diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp new file mode 100644 index 0000000..8525058 --- a/dev/null +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -0,0 +1,983 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "pbuilder_pbx.h" +#include "option.h" +#include <qdir.h> +#include <qdict.h> +#include <qregexp.h> +#include <stdlib.h> +#include <time.h> +#ifdef Q_OS_UNIX +# include <sys/types.h> +# include <sys/stat.h> +#endif + +// Note: this is fairly hacky, but it does the job... + + +ProjectBuilderMakefileGenerator::ProjectBuilderMakefileGenerator(QMakeProject *p) : UnixMakefileGenerator(p) +{ + +} + +bool +ProjectBuilderMakefileGenerator::writeMakefile(QTextStream &t) +{ + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + /* for now just dump, I need to generated an empty xml or something.. */ + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + project->variables()["MAKEFILE"].clear(); + project->variables()["MAKEFILE"].append("Makefile"); + if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { + return writeMakeParts(t); + } else if(project->first("TEMPLATE") == "subdirs") { + writeSubdirs(t, FALSE); + return TRUE; + } + return FALSE; +} + +bool +ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) +{ + int i; + QStringList tmp; + bool did_preprocess = FALSE; + + //HEADER + t << "// !$*UTF8*$!" << "\n" + << "{" << "\n" + << "\t" << "archiveVersion = 1;" << "\n" + << "\t" << "classes = {" << "\n" << "\t" << "};" << "\n" + << "\t" << "objectVersion = " << pbuilderVersion() << ";" << "\n" + << "\t" << "objects = {" << endl; + + //MAKE QMAKE equivlant + if(!project->isActiveConfig("no_autoqmake") && project->projectFile() != "(stdin)") { + QString mkfile = pbx_dir + Option::dir_sep + "qt_makeqmake.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "QMAKE = " << + (project->isEmpty("QMAKE_QMAKE") ? QString("$(QTDIR)/bin/qmake") : + var("QMAKE_QMAKE")) << endl; + writeMakeQmake(mkt); + mkf.close(); + } + QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Qmake\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() << + " -f " << mkfile << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + //DUMP SOURCES + QMap<QString, QStringList> groups; + QString srcs[] = { "SOURCES", "SRCMOC", "UICIMPLS", QString::null }; + for(i = 0; !srcs[i].isNull(); i++) { + tmp = project->variables()[srcs[i]]; + QStringList &src_list = project->variables()["QMAKE_PBX_" + srcs[i]]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) { + QString file = fileFixify((*it)); + if(file.endsWith(Option::moc_ext)) + continue; + bool in_root = TRUE; + QString src_key = keyFor(file); + if(!project->isActiveConfig("flat")) { + QString flat_file = fileFixify(file, QDir::currentDirPath(), Option::output_dir, TRUE); + if(QDir::isRelativePath(flat_file) && flat_file.find(Option::dir_sep) != -1) { + QString last_grp("QMAKE_PBX_" + srcs[i] + "_HEIR_GROUP"); + QStringList dirs = QStringList::split(Option::dir_sep, flat_file); + dirs.pop_back(); //remove the file portion as it will be added via src_key + for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { + QString new_grp(last_grp + Option::dir_sep + (*dir_it)), + new_grp_key(keyFor(new_grp)), last_grp_key(keyFor(last_grp)); + if(dir_it == dirs.begin()) { + if(!groups.contains(new_grp)) + project->variables()["QMAKE_PBX_" + srcs[i]].append(new_grp_key); + } else { + groups[last_grp] += new_grp_key; + } + last_grp = new_grp; + } + groups[last_grp] += src_key; + in_root = FALSE; + } + } + if(in_root) + src_list.append(src_key); + //source reference + t << "\t\t" << src_key << " = {" << "\n" + << "\t\t\t" << "isa = PBXFileReference;" << "\n" + << "\t\t\t" << "path = \"" << file << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(file) << ";" << "\n" + << "\t\t" << "};" << "\n"; + //build reference + QString obj_key = file + ".o"; + obj_key = keyFor(obj_key); + t << "\t\t" << obj_key << " = {" << "\n" + << "\t\t\t" << "fileRef = " << src_key << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t\t" << "ATTRIBUTES = (" << "\n" + << "\t\t\t\t" << ");" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_OBJ"].append(obj_key); + } + if(!src_list.isEmpty()) { + QString grp; + if(srcs[i] == "SOURCES") { + if(project->first("TEMPLATE") == "app" && !project->isEmpty("RC_FILE")) { //Icon + QString icns_file = keyFor("ICNS_FILE"); + src_list.append(icns_file); + t << "\t\t" << icns_file << " = {" << "\n" + << "\t\t\t" << "isa = PBXFileReference;" << "\n" + << "\t\t\t" << "path = \"" << project->first("RC_FILE") << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(project->first("RC_FILE")) << ";" << "\n" + << "\t\t" << "};" << "\n"; + t << "\t\t" << keyFor("ICNS_FILE_REFERENCE") << " = {" << "\n" + << "\t\t\t" << "fileRef = " << icns_file << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + } + grp = "Sources"; + } else if(srcs[i] == "SRCMOC") { + grp = "Mocables"; + } else if(srcs[i] == "UICIMPLS") { + grp = "UICables"; + } + QString grp_key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(grp_key); + t << "\t\t" << grp_key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_" + srcs[i], "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = " << grp << ";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + } + for(QMap<QString, QStringList>::Iterator grp_it = groups.begin(); + grp_it != groups.end(); ++grp_it) { + t << "\t\t" << keyFor(grp_it.key()) << " = {" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "children = (" << "\n" + << valGlue(grp_it.data(), "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "name = \"" << grp_it.key().section(Option::dir_sep, -1) << "\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + + //PREPROCESS BUILDPHASE (just a makefile) + if(!project->isEmpty("UICIMPLS") || !project->isEmpty("SRCMOC") || + !project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) { + QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + did_preprocess = TRUE; + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "MOC = " << var("QMAKE_MOC") << endl; + mkt << "UIC = " << var("QMAKE_UIC") << endl; + mkt << "LEX = " << var("QMAKE_LEX") << endl; + mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl; + mkt << "YACC = " << var("QMAKE_YACC") << endl; + mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl; + mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + mkt << "MOVE = " << var("QMAKE_MOVE") << endl << endl; + mkt << "FORMS = " << varList("UICIMPLS") << endl; + mkt << "MOCS = " << varList("SRCMOC") << endl; + mkt << "PARSERS ="; + if(!project->isEmpty("YACCSOURCES")) { + QStringList &yaccs = project->variables()["YACCSOURCES"]; + for(QStringList::Iterator yit = yaccs.begin(); yit != yaccs.end(); ++yit) { + QFileInfo fi((*yit)); + mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE) + << Option::yacc_mod << Option::cpp_ext.first(); + } + } + if(!project->isEmpty("LEXSOURCES")) { + QStringList &lexs = project->variables()["LEXSOURCES"]; + for(QStringList::Iterator lit = lexs.begin(); lit != lexs.end(); ++lit) { + QFileInfo fi((*lit)); + mkt << " " << fi.dirPath() << Option::dir_sep << fi.baseName(TRUE) + << Option::lex_mod << Option::cpp_ext.first(); + } + } + mkt << "\n"; + mkt << "preprocess: $(FORMS) $(MOCS) $(PARSERS)" << endl; + mkt << "preprocess_clean: mocclean uiclean parser_clean" << endl << endl; + mkt << "mocclean:" << "\n"; + if(!project->isEmpty("SRCMOC")) + mkt << "\t-rm -f $(MOCS)" << "\n"; + mkt << "uiclean:" << "\n"; + if(!project->isEmpty("UICIMPLS")) + mkt << "\t-rm -f $(FORMS)" << "\n"; + mkt << "parser_clean:" << "\n"; + if(!project->isEmpty("YACCSOURCES") || !project->isEmpty("LEXSOURCES")) + mkt << "\t-rm -f $(PARSERS)" << "\n"; + writeUicSrc(mkt, "FORMS"); + writeMocSrc(mkt, "HEADERS"); + writeMocSrc(mkt, "SOURCES"); + writeMocSrc(mkt, "UICDECLS"); + writeYaccSrc(mkt, "YACCSOURCES"); + writeLexSrc(mkt, "LEXSOURCES"); + mkf.close(); + } + QString target_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + t << "\t\t" << target_key << " = {" << "\n" + << "\t\t\t" << "buildArgumentsString = \"-f " << mkfile << "\";" << "\n" + << "\t\t\t" << "buildPhases = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "buildToolPath = \"/usr/bin/gnumake\";"<< "\n" + << "\t\t\t" << "buildWorkingDirectory = \"" << QDir::currentDirPath() << "\";" << "\n" + << "\t\t\t" << "dependencies = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXLegacyTarget;" << "\n" + << "\t\t\t" << "name = QtPreprocessors;" << "\n" + << "\t\t\t" << "productName = QtPreprocessors;" << "\n" + << "\t\t\t" << "settingsToExpand = 6;" << "\n" + << "\t\t\t" << "settingsToPassInEnvironment = 287;" << "\n" + << "\t\t\t" << "settingsToPassOnCommandLine = 280;" << "\n" + << "\t\t\t" << "shouldsUseHeadermap = 0;" << "\n" + << "\t\t" << "};" << "\n"; + + QString target_depend_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET_DEPEND"); + project->variables()["QMAKE_PBX_TARGETDEPENDS"].append(target_depend_key); + t << "\t\t" << target_depend_key << " = {" << "\n" + << "\t\t\t" << "isa = PBXTargetDependency;" << "\n" + << "\t\t\t" << "target = " << target_key << ";" << "\n" + << "\t\t" << "};" << "\n"; + } + //SOURCE BUILDPHASE + if(!project->isEmpty("QMAKE_PBX_OBJ")) { + QString grp = "Build Sources", key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << varGlue("QMAKE_PBX_OBJ", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXSourcesBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES + QStringList &libdirs = project->variables()["QMAKE_PBX_LIBPATHS"]; + QString libs[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null }; + for(i = 0; !libs[i].isNull(); i++) { + tmp = project->variables()[libs[i]]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end();) { + bool remove = FALSE; + QString library, name, opt = (*it).stripWhiteSpace(); + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2); + fixEnvVariables(r); + libdirs.append(r); + } else if(opt.startsWith("-l")) { + name = opt.right(opt.length() - 2); + QString lib("lib" + name); + for(QStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) { + if(project->isActiveConfig("link_prl")) { + /* This isn't real nice, but it is real usefull. This looks in a prl + for what the library will ultimately be called so we can stick it + in the ProjectFile. If the prl format ever changes (not likely) then + this will not really work. However, more concerning is that it will + encode the version number in the Project file which might be a bad + things in days to come? --Sam + */ + QString prl_file = (*lit) + Option::dir_sep + lib + Option::prl_ext; + if(QFile::exists(prl_file)) { + QMakeProject proj; + if(proj.read(prl_file, QDir::currentDirPath())) { + if(!proj.isEmpty("QMAKE_PRL_TARGET")) { + library = (*lit) + Option::dir_sep + proj.first("QMAKE_PRL_TARGET"); + debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)", + opt.latin1(), prl_file.latin1(), library.latin1()); + remove = TRUE; + } + } + + } + } + if(!remove) { + QString extns[] = { ".dylib", ".so", ".a", QString::null }; + for(int n = 0; !remove && !extns[n].isNull(); n++) { + QString tmp = (*lit) + Option::dir_sep + lib + extns[n]; + if(QFile::exists(tmp)) { + library = tmp; + debug_msg(1, "pbuilder: Found library (%s) via %s", + opt.latin1(), library.latin1()); + remove = TRUE; + } + } + } + } + } else if(opt == "-framework") { + ++it; + if(it == tmp.end()) + break; + QStringList &fdirs = project->variables()["QMAKE_FRAMEWORKDIR"]; + if(fdirs.isEmpty()) + fdirs.append("/System/Library/Frameworks/"); + for(QStringList::Iterator fit = fdirs.begin(); fit != fdirs.end(); ++fit) { + if(QFile::exists((*fit) + QDir::separator() + (*it) + ".framework")) { + --it; + it = tmp.remove(it); + remove = TRUE; + library = (*fit) + Option::dir_sep + (*it) + ".framework"; + break; + } + } + } else if(opt.left(1) != "-") { + remove = TRUE; + library = opt; + } + if(!library.isEmpty()) { + if(name.isEmpty()) { + int slsh = library.findRev(Option::dir_sep); + if(slsh != -1) + name = library.right(library.length() - slsh - 1); + } + library = fileFixify(library); + QString key = keyFor(library); + bool is_frmwrk = (library.endsWith(".framework")); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "isa = " << (is_frmwrk ? "PBXFrameworkReference" : "PBXFileReference") << ";" << "\n" + << "\t\t\t" << "name = \"" << name << "\";" << "\n" + << "\t\t\t" << "path = \"" << library << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(library) << ";" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_LIBRARIES"].append(key); + QString obj_key = library + ".o"; + obj_key = keyFor(obj_key); + t << "\t\t" << obj_key << " = {" << "\n" + << "\t\t\t" << "fileRef = " << key << ";" << "\n" + << "\t\t\t" << "isa = PBXBuildFile;" << "\n" + << "\t\t\t" << "settings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t" << "};" << "\n"; + project->variables()["QMAKE_PBX_BUILD_LIBRARIES"].append(obj_key); + } + if(remove) + it = tmp.remove(it); + else + ++it; + } + project->variables()[libs[i]] = tmp; + } + } + //SUBLIBS BUILDPHASE (just another makefile) + if(!project->isEmpty("SUBLIBS")) { + QString mkfile = pbx_dir + Option::dir_sep + "qt_sublibs.mak"; + QFile mkf(mkfile); + if(mkf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkfile.latin1()); + QTextStream mkt(&mkf); + writeHeader(mkt); + mkt << "SUBLIBS= "; + tmp = project->variables()["SUBLIBS"]; + QStringList::Iterator it; + for(it = tmp.begin(); it != tmp.end(); ++it) + t << "tmp/lib" << (*it) << ".a "; + t << endl << endl; + mkt << "sublibs: $(SUBLIBS)" << endl << endl; + tmp = project->variables()["SUBLIBS"]; + for(it = tmp.begin(); it != tmp.end(); ++it) + t << "tmp/lib" << (*it) << ".a" << ":\n\t" + << var(QString("MAKELIB") + (*it)) << endl << endl; + mkf.close(); + } + QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE"); + mkfile = fileFixify(mkfile, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Sublibs\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"make -C " << QDir::currentDirPath() << + " -f " << mkfile << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + //LIBRARY BUILDPHASE + if(!project->isEmpty("QMAKE_PBX_LIBRARIES")) { + tmp = project->variables()["QMAKE_PBX_LIBRARIES"]; + if(!tmp.isEmpty()) { + QString grp("External Frameworks and Libraries"), key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\"" << ";" << "\n" + << "\t\t\t" << "path = \"\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + } + { + QString grp("Frameworks & Libraries"), key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << varGlue("QMAKE_PBX_BUILD_LIBRARIES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXFrameworksBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console") && + project->first("TEMPLATE") == "app") { //BUNDLE RESOURCES + QString grp("Bundle Resources"), key = keyFor(grp); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 2147483647;" << "\n" + << "\t\t\t" << "files = (" << "\n" + << (!project->isEmpty("RC_FILE") ? keyFor("ICNS_FILE_REFERENCE") : QString("")) + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXResourcesBuildPhase;" << "\n" + << "\t\t\t" << "name = \"" << grp << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + + //DUMP EVERYTHING THAT TIES THE ABOVE TOGETHER + //PRODUCTS + { + QString grp("Products"), key = keyFor(grp); + project->variables()["QMAKE_PBX_GROUPS"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << "\t\t\t\t" << keyFor("QMAKE_PBX_REFERENCE") << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = Products;" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + } + { //INSTALL BUILDPHASE (sh script) + QString targ = project->first("TARGET"); + if(project->first("TEMPLATE") == "app" || + (project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") && + project->isActiveConfig("frameworklib"))) + targ = project->first("QMAKE_ORIG_TARGET"); + int slsh = targ.findRev(Option::dir_sep); + if(slsh != -1) + targ = targ.right(targ.length() - slsh - 1); + fixEnvVariables(targ); + QStringList links; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) + targ += ".app"; + } else if(!project->isActiveConfig("staticlib") && + !project->isActiveConfig("frameworklib")) { + QString li[] = { "TARGET_", "TARGET_x", "TARGET_x.y", QString::null }; + for(int n = 0; !li[n].isNull(); n++) { + QString t = project->first(li[n]); + slsh = t.findRev(Option::dir_sep); + if(slsh != -1) + t = t.right(t.length() - slsh); + fixEnvVariables(t); + links << t; + } + } + QString script = pbx_dir + Option::dir_sep + "qt_install.sh"; + QFile shf(script); + if(shf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", script.latin1()); + QString targ = project->first("QMAKE_ORIG_TARGET"), cpflags; + if(project->first("TEMPLATE") == "app") { + targ = project->first("TARGET"); + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + targ += ".app"; + cpflags += "-r "; + } + } else if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("staticlib")) + targ = project->first("TARGET"); + else + targ = project->first("TARGET_"); + int slsh = targ.findRev(Option::dir_sep); + if(slsh != -1) + targ = targ.right(targ.length() - slsh - 1); + } + QTextStream sht(&shf); + QString dstdir = project->first("DESTDIR"); + fixEnvVariables(dstdir); + + sht << "#!/bin/sh" << endl; + //copy the actual target + sht << "OUT_TARG=\"" << targ << "\"\n" + << "[ -z \"$BUILD_ROOT\" ] || OUT_TARG=\"${BUILD_ROOT}/${OUT_TARG}\"" << endl; + sht << "[ \"$OUT_TARG\" = \"" + << (dstdir.isEmpty() ? QDir::currentDirPath() + QDir::separator(): dstdir) << targ << "\" ] || " + << "[ \"$OUT_TARG\" = \"" << targ << "\" ] || " + << "cp -r \"$OUT_TARG\" " << "\"" << dstdir << targ << "\"" << endl; + //rename as a framework + if(project->first("TEMPLATE") == "lib" && project->isActiveConfig("frameworklib")) + sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << targ << "\"" << endl; + //create all the version symlinks (just to be like unixmake) + for(QStringList::Iterator it = links.begin(); it != links.end(); ++it) { + if(targ != (*it)) + sht << "ln -sf \"" << targ << "\" " << "\"" << dstdir << (*it) << "\"" << endl; + } + shf.close(); +#ifdef Q_OS_UNIX + chmod(script.latin1(), S_IRWXU | S_IRWXG); +#endif + QString phase_key = keyFor("QMAKE_PBX_INSTALL_BUILDPHASE"); + script = fileFixify(script, QDir::currentDirPath()); + project->variables()["QMAKE_PBX_BUILDPHASES"].append(phase_key); + t << "\t\t" << phase_key << " = {" << "\n" + << "\t\t\t" << "buildActionMask = 8;" << "\n" //only on install! + << "\t\t\t" << "files = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "generatedFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXShellScriptBuildPhase;" << "\n" + << "\t\t\t" << "name = \"Qt Install\";" << "\n" + << "\t\t\t" << "neededFileNames = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "shellPath = /bin/sh;" << "\n" + << "\t\t\t" << "shellScript = \"" << script << "\";" << "\n" + << "\t\t" << "};" << "\n"; + } + } + //ROOT_GROUP + t << "\t\t" << keyFor("QMAKE_PBX_ROOT_GROUP") << " = {" << "\n" + << "\t\t\t" << "children = (" << "\n" + << varGlue("QMAKE_PBX_GROUPS", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXGroup;" << "\n" + << "\t\t\t" << "name = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n" + << "\t\t\t" << "path = \"\";" << "\n" + << "\t\t\t" << "refType = 4;" << "\n" + << "\t\t" << "};" << "\n"; + //REFERENCE + t << "\t\t" << keyFor("QMAKE_PBX_REFERENCE") << " = {" << "\n"; + if(project->first("TEMPLATE") == "app") { + QString targ = project->first("QMAKE_ORIG_TARGET"); + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + targ += ".app"; + t << "\t\t\t" << "isa = PBXApplicationReference;" << "\n"; + } else { + t << "\t\t\t" << "isa = PBXExecutableFileReference;" << "\n"; + } + QString app = (!project->isEmpty("DESTDIR") ? project->first("DESTDIR") + project->first("QMAKE_ORIG_TARGET") : + QDir::currentDirPath()) + Option::dir_sep + targ; + t << "\t\t\t" << "name = " << targ << ";" << "\n" + << "\t\t\t" << "path = \"" << targ << "\";" << "\n" + << "\t\t\t" << "refType = " << reftypeForFile(app) << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(project->isActiveConfig("staticlib")) { + lib = project->first("TARGET"); + } else if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("plugin")) + lib = project->first("TARGET"); + else + lib = project->first("TARGET_"); + } + int slsh = lib.findRev(Option::dir_sep); + if(slsh != -1) + lib = lib.right(lib.length() - slsh - 1); + t << "\t\t\t" << "isa = PBXLibraryReference;" << "\n" + << "\t\t\t" << "path = " << lib << ";\n" + << "\t\t\t" << "refType = " << reftypeForFile(lib) << ";" << "\n"; + } + t << "\t\t" << "};" << "\n"; + //TARGET + t << "\t\t" << keyFor("QMAKE_PBX_TARGET") << " = {" << "\n" + << "\t\t\t" << "buildPhases = (" << "\n" + << varGlue("QMAKE_PBX_BUILDPHASES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t\t" << "FRAMEWORK_SEARCH_PATHS = \"\";" << "\n" + << "\t\t\t\t" << "HEADER_SEARCH_PATHS = \"" << fixEnvsList("INCLUDEPATH") << " " << fixEnvs(specdir()) << "\";" << "\n" + << "\t\t\t\t" << "LIBRARY_SEARCH_PATHS = \"" << var("QMAKE_PBX_LIBPATHS") << "\";" << "\n" + << "\t\t\t\t" << "OPTIMIZATION_CFLAGS = \"\";" << "\n" + << "\t\t\t\t" << "OTHER_CFLAGS = \"" << + fixEnvsList("QMAKE_CFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") << + varGlue("DEFINES"," -D"," -D","") << "\";" << "\n" + << "\t\t\t\t" << "LEXFLAGS = \"" << var("QMAKE_LEXFLAGS") << "\";" << "\n" + << "\t\t\t\t" << "YACCFLAGS = \"" << var("QMAKE_YACCFLAGS") << "\";" << "\n" + << "\t\t\t\t" << "OTHER_CPLUSPLUSFLAGS = \"" << + fixEnvsList("QMAKE_CXXFLAGS") << varGlue("PRL_EXPORT_DEFINES"," -D"," -D","") << + varGlue("DEFINES"," -D"," -D","") << "\";" << "\n" + << "\t\t\t\t" << "OTHER_REZFLAGS = \"\";" << "\n" + << "\t\t\t\t" << "SECTORDER_FLAGS = \"\";" << "\n" + << "\t\t\t\t" << "WARNING_CFLAGS = \"\";" << "\n"; +#if 1 + t << "\t\t\t\t" << "BUILD_ROOT = \"" << QDir::currentDirPath() << "\";" << "\n"; +#endif + if(!project->isActiveConfig("staticlib")) + t << "\t\t\t\t" << "OTHER_LDFLAGS = \"" << fixEnvsList("SUBLIBS") << " " << + fixEnvsList("QMAKE_LFLAGS") << " " << fixEnvsList("QMAKE_LIBDIR_FLAGS") << + " " << fixEnvsList("QMAKE_LIBS") << "\";" << "\n"; + if(!project->isEmpty("DESTDIR")) + t << "\t\t\t\t" << "INSTALL_PATH = \"" << project->first("DESTDIR") << "\";" << "\n"; + if(!project->isEmpty("VERSION") && project->first("VERSION") != "0.0.0") + t << "\t\t\t\t" << "DYLIB_CURRENT_VERSION = \"" << project->first("VERSION") << "\";" << "\n"; + if(!project->isEmpty("OBJECTS_DIR")) + t << "\t\t\t\t" << "OBJECT_FILE_DIR = \"" << project->first("OBJECTS_DIR") << "\";" << "\n"; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) + t << "\t\t\t\t" << "WRAPPER_EXTENSION = app;" << "\n"; + t << "\t\t\t\t" << "PRODUCT_NAME = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) { + t << "\t\t\t\t" << "LIBRARY_STYLE = STATIC;" << "\n"; + lib = project->first("TARGET"); + } else { + t << "\t\t\t\t" << "LIBRARY_STYLE = DYNAMIC;" << "\n"; + if(!project->isActiveConfig("frameworklib")) { + if(project->isActiveConfig("plugin")) + lib = project->first("TARGET"); + else + lib = project->first("TARGET_"); + } + } + int slsh = lib.findRev(Option::dir_sep); + if(slsh != -1) + lib = lib.right(lib.length() - slsh - 1); + t << "\t\t\t\t" << "PRODUCT_NAME = " << lib << ";" << "\n"; + } + tmp = project->variables()["QMAKE_PBX_VARS"]; + for(QStringList::Iterator it = tmp.begin(); it != tmp.end(); ++it) + t << "\t\t\t\t" << (*it) << " = \"" << getenv((*it)) << "\";" << "\n"; + t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "conditionalBuildSettings = {" << "\n" + << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "dependencies = (" << "\n" + << varGlue("QMAKE_PBX_TARGETDEPENDS", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "productReference = " << keyFor("QMAKE_PBX_REFERENCE") << ";" << "\n" + << "\t\t\t" << "shouldUseHeadermap = 1;" << "\n"; + if(project->first("TEMPLATE") == "app") { + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + t << "\t\t\t" << "isa = PBXApplicationTarget;" << "\n" + << "\t\t\t" << "productSettingsXML = " << "\"" << "<?xml version=" + << "\\\"1.0\\\" encoding=" << "\\\"UTF-8\\\"" << "?>" << "\n" + << "\t\t\t\t" << "<!DOCTYPE plist SYSTEM \\\"file://localhost/System/" + << "Library/DTDs/PropertyList.dtd\\\">" << "\n" + << "\t\t\t\t" << "<plist version=\\\"0.9\\\">" << "\n" + << "\t\t\t\t" << "<dict>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleDevelopmentRegion</key>" << "\n" + << "\t\t\t\t\t" << "<string>English</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleExecutable</key>" << "\n" + << "\t\t\t\t\t" << "<string>" << project->first("QMAKE_ORIG_TARGET") << "</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleIconFile</key>" << "\n" + << "\t\t\t\t\t" << "<string>" << var("RC_FILE").section(Option::dir_sep, -1) << "</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleInfoDictionaryVersion</key>" << "\n" + << "\t\t\t\t\t" << "<string>6.0</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundlePackageType</key>" << "\n" + << "\t\t\t\t\t" << "<string>APPL</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleSignature</key>" << "\n" + << "\t\t\t\t\t" << "<string>????</string>" << "\n" + << "\t\t\t\t\t" << "<key>CFBundleVersion</key>" << "\n" + << "\t\t\t\t\t" << "<string>0.1</string>" << "\n" + << "\t\t\t\t\t" << "<key>CSResourcesFileMapped</key>" << "\n" + << "\t\t\t\t\t" << "<true/>" << "\n" + << "\t\t\t\t" << "</dict>" << "\n" + << "\t\t\t\t" << "</plist>" << "\";" << "\n"; + } else { + t << "\t\t\t" << "isa = PBXToolTarget;" << "\n"; + } + t << "\t\t\t" << "name = \"" << project->first("QMAKE_ORIG_TARGET") << "\";" << "\n" + << "\t\t\t" << "productName = " << project->first("QMAKE_ORIG_TARGET") << ";" << "\n"; + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if(!project->isActiveConfig("frameworklib")) + lib.prepend("lib"); + t << "\t\t\t" << "isa = PBXLibraryTarget;" << "\n" + << "\t\t\t" << "name = \"" << lib << "\";" << "\n" + << "\t\t\t" << "productName = " << lib << ";" << "\n"; + } + if(!project->isEmpty("DESTDIR")) + t << "\t\t\t" << "productInstallPath = \"" << project->first("DESTDIR") << "\";" << "\n"; + t << "\t\t" << "};" << "\n"; + //DEBUG/RELEASE + for(i = 0; i < 2; i++) { + bool as_release = !i; + if(project->isActiveConfig("debug")) + as_release = i; + QString key = "QMAKE_PBX_" + QString(as_release ? "RELEASE" : "DEBUG"); + key = keyFor(key); + project->variables()["QMAKE_PBX_BUILDSTYLES"].append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << "buildRules = (" << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n" + << "\t\t\t\t" << "COPY_PHASE_STRIP = " << (as_release ? "YES" : "NO") << ";" << "\n"; + if(as_release) + t << "\t\t\t\t" << "DEBUGGING_SYMBOLS = NO;" << "\n"; + t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << "isa = PBXBuildStyle;" << "\n" + << "\t\t\t" << "name = " << (as_release ? "Deployment" : "Development") << ";" << "\n" + << "\t\t" << "};" << "\n"; + } + //ROOT + t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n" + << "\t\t\t" << "buildStyles = (" << "\n" + << varGlue("QMAKE_PBX_BUILDSTYLES", "\t\t\t\t", ",\n\t\t\t\t", "\n") + << "\t\t\t" << ");" << "\n" + << "\t\t\t" << "isa = PBXProject;" << "\n" + << "\t\t\t" << "mainGroup = " << keyFor("QMAKE_PBX_ROOT_GROUP") << ";" << "\n" + << "\t\t\t" << "targets = (" << "\n" + << "\t\t\t\t" << keyFor("QMAKE_PBX_TARGET") << "\n" + << "\t\t\t" << ");" << "\n" + << "\t\t" << "};" << "\n"; + + //FOOTER + t << "\t" << "};" << "\n" + << "\t" << "rootObject = " << keyFor("QMAKE_PBX_ROOT") << ";" << "\n" + << "}" << endl; + + QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"), + QDir::currentDirPath()); + QFile mkwrapf(mkwrap); + if(mkwrapf.open(IO_WriteOnly | IO_Translate)) { + debug_msg(1, "pbuilder: Creating file: %s", mkwrap.latin1()); + QTextStream mkwrapt(&mkwrapf); + writeHeader(mkwrapt); + const char *cleans = "uiclean mocclean preprocess_clean "; + mkwrapt << "#This is a makefile wrapper for PROJECT BUILDER\n" + << "all:" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild") << "\n" + << "install: all" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild install") << "\n" + << "distclean clean: preprocess_clean" << "\n\t" + << "cd " << (project->first("QMAKE_ORIG_TARGET") + ".pbproj/ && pbxbuild clean") << "\n" + << (!did_preprocess ? cleans : "") << ":" << "\n"; + if(did_preprocess) + mkwrapt << cleans << ":" << "\n\t" + << "make -f " + << pbx_dir << Option::dir_sep << "qt_preprocess.mak $@" << endl; + } + return TRUE; +} + +QString +ProjectBuilderMakefileGenerator::fixEnvs(QString file) +{ + QRegExp reg_var("\\$\\((.*)\\)"); + for(int rep = 0; (rep = reg_var.search(file, rep)) != -1; ) { + if(project->variables()["QMAKE_PBX_VARS"].findIndex(reg_var.cap(1)) == -1) + project->variables()["QMAKE_PBX_VARS"].append(reg_var.cap(1)); + rep += reg_var.matchedLength(); + } + return file; +} + +QString +ProjectBuilderMakefileGenerator::fixEnvsList(QString where) +{ + QString ret; + const QStringList &l = project->variables()[where]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + fixEnvs((*it)); + if(!ret.isEmpty()) + ret += " "; + ret += (*it); + } + return ret; +} + +QString +ProjectBuilderMakefileGenerator::keyFor(QString block) +{ +#if 0 //This make this code much easier to debug.. + return block; +#endif + + QString ret; + if(!keys.contains(block)) { +#if 0 + static unsigned int r = 0; + ret.sprintf("%024x", ++r); +#else //not really necesary, but makes it look more interesting.. + static struct { unsigned int a1, a2, a3; } r = { 0, 0, 0 }; + if(!r.a1 && !r.a2 && !r.a3) { + r.a1 = rand(); + r.a2 = rand(); + r.a3 = rand(); + } + switch(rand() % 3) { + case 0: ++r.a1; break; + case 1: ++r.a2; break; + case 2: ++r.a3; break; + } + ret.sprintf("%08x%08x%08x", r.a1, r.a2, r.a3); +#endif + ret = ret.upper(); + keys.insert(block, ret); + } else { + ret = keys[block]; + } + return ret; +} + +bool +ProjectBuilderMakefileGenerator::openOutput(QFile &file) const +{ + if(project->first("TEMPLATE") != "subdirs") { + QFileInfo fi(file); + if(fi.extension() != "pbxproj" || file.name().isEmpty()) { + QString output = file.name(); + if(fi.isDir()) + output += QDir::separator(); + if(fi.extension() != "pbproj") { + if(file.name().isEmpty() || fi.isDir()) + output += project->first("TARGET"); + output += QString(".pbproj") + QDir::separator(); + } else if(output[(int)output.length() - 1] != QDir::separator()) { + output += QDir::separator(); + } + output += QString("project.pbxproj"); + file.setName(output); + } + bool ret = UnixMakefileGenerator::openOutput(file); + ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1); + Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2); + return ret; + } + return UnixMakefileGenerator::openOutput(file); +} + +/* This function is such a hack it is almost pointless, but it + eliminates the warning message from ProjectBuilder that the project + file is for an older version. I guess this could be used someday if + the format of the output is dependant upon the version of + ProjectBuilder as well. +*/ +int +ProjectBuilderMakefileGenerator::pbuilderVersion() const +{ + QString ret; + if(project->isEmpty("QMAKE_PBUILDER_VERSION")) { + QString version, version_plist = project->first("QMAKE_PBUILDER_VERSION_PLIST"); + if(version_plist.isEmpty()) + version_plist = "/Developer/Applications/Project Builder.app/Contents/version.plist"; + else + version_plist = version_plist.replace(QRegExp("\""), ""); + QFile version_file(version_plist); + if(version_file.open(IO_ReadOnly)) { + debug_msg(1, "pbuilder: version.plist: Reading file: %s", version_plist.latin1()); + QTextStream plist(&version_file); + + bool in_dict = FALSE; + QString current_key; + QRegExp keyreg("^<key>(.*)</key>$"), stringreg("^<string>(.*)</string>$"); + while(!plist.eof()) { + QString line = plist.readLine().stripWhiteSpace(); + if(line == "<dict>") + in_dict = TRUE; + else if(line == "</dict>") + in_dict = FALSE; + else if(in_dict) { + if(keyreg.exactMatch(line)) + current_key = keyreg.cap(1); + else if(current_key == "CFBundleShortVersionString" && stringreg.exactMatch(line)) + version = stringreg.cap(1); + } + } + version_file.close(); + } else debug_msg(1, "pbuilder: version.plist: Failure to open %s", version_plist.latin1()); + if(version.startsWith("2.0")) + ret = "38"; + else if(version == "1.1") + ret = "34"; + } else { + ret = project->first("QMAKE_PBUILDER_VERSION"); + } + if(!ret.isEmpty()) { + bool ok; + int int_ret = ret.toInt(&ok); + if(ok) { + debug_msg(1, "pbuilder: version.plist: Got version: %d", int_ret); + return int_ret; + } + } + debug_msg(1, "pbuilder: version.plist: Fallback to default version"); + return 34; //my fallback +} + +QString +ProjectBuilderMakefileGenerator::reftypeForFile(QString where) +{ + if(QDir::isRelativePath(where)) + return "4"; //relative + return "0"; //absolute +} diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h new file mode 100644 index 0000000..ec2e1be --- a/dev/null +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __PBUILDERMAKE_H__ +#define __PBUILDERMAKE_H__ + +#include "unixmake.h" + +class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator +{ + QString pbx_dir; + int pbuilderVersion() const; + bool writeMakeParts(QTextStream &); + bool writeMakefile(QTextStream &); + + QMap<QString, QString> keys; + QString keyFor(QString file); + QString fixEnvs(QString file); + QString fixEnvsList(QString where); + QString reftypeForFile(QString file); + +public: + ProjectBuilderMakefileGenerator(QMakeProject *p); + ~ProjectBuilderMakefileGenerator(); + + virtual bool openOutput(QFile &) const; +protected: + virtual bool doDepends() const { return FALSE; } //never necesary +}; + +inline ProjectBuilderMakefileGenerator::~ProjectBuilderMakefileGenerator() +{ } + + +#endif /* __PBUILDERMAKE_H__ */ diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp new file mode 100644 index 0000000..7df95b2 --- a/dev/null +++ b/qmake/generators/unix/unixmake.cpp @@ -0,0 +1,520 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "unixmake.h" +#include "option.h" +#include <qregexp.h> +#include <qfile.h> +#include <qdict.h> +#include <qdir.h> +#include <time.h> + + +void +UnixMakefileGenerator::init() +{ + if(init_flag) + return; + init_flag = TRUE; + + if(!project->isEmpty("QMAKE_FAILED_REQUIREMENTS")) /* no point */ + return; + + QStringList &configs = project->variables()["CONFIG"]; + /* this should probably not be here, but I'm using it to wrap the .t files */ + if(project->first("TEMPLATE") == "app") + project->variables()["QMAKE_APP_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "lib") + project->variables()["QMAKE_LIB_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "subdirs") { + MakefileGenerator::init(); + if(project->isEmpty("MAKEFILE")) + project->variables()["MAKEFILE"].append("Makefile"); + if(project->isEmpty("QMAKE")) + project->variables()["QMAKE"].append("qmake"); + if(project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].findIndex("qmake_all") == -1) + project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].append("qmake_all"); + return; /* subdirs is done */ + } + + if( project->isEmpty("QMAKE_EXTENSION_SHLIB") ) { + QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); + if ( os == "cygwin" ) { + project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dll" ); + } else { + project->variables()["QMAKE_EXTENSION_SHLIB"].append( "so" ); + } + } + if( project->isEmpty("QMAKE_COPY_FILE") ) + project->variables()["QMAKE_COPY_FILE"].append( "$(COPY) -p" ); + if( project->isEmpty("QMAKE_COPY_DIR") ) + project->variables()["QMAKE_COPY_DIR"].append( "$(COPY) -pR" ); + //If the TARGET looks like a path split it into DESTDIR and the resulting TARGET + if(!project->isEmpty("TARGET")) { + QString targ = project->first("TARGET"); + int slsh = QMAX(targ.findRev('/'), targ.findRev(Option::dir_sep)); + if(slsh != -1) { + if(project->isEmpty("DESTDIR")) + project->values("DESTDIR").append(""); + else if(project->first("DESTDIR").right(1) != Option::dir_sep) + project->variables()["DESTDIR"] = project->first("DESTDIR") + Option::dir_sep; + project->variables()["DESTDIR"] = project->first("DESTDIR") + targ.left(slsh+1); + project->variables()["TARGET"] = targ.mid(slsh+1); + } + } + + project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; + + bool is_qt = (project->first("TARGET") == "qt" || project->first("TARGET") == "qte" || + project->first("TARGET") == "qt-mt" || project->first("TARGET") == "qte-mt"); + bool extern_libs = !project->isEmpty("QMAKE_APP_FLAG") || + (!project->isEmpty("QMAKE_LIB_FLAG") && + project->isActiveConfig("dll")) || is_qt; + if(!project->isActiveConfig("global_init_link_order")) + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + if ( (!project->isEmpty("QMAKE_LIB_FLAG") && !project->isActiveConfig("staticlib") ) || + (project->isActiveConfig("qt") && project->isActiveConfig( "plugin" ) )) { + if(configs.findIndex("dll") == -1) configs.append("dll"); + } else if ( !project->isEmpty("QMAKE_APP_FLAG") || project->isActiveConfig("dll") ) { + configs.remove("staticlib"); + } + if ( project->isActiveConfig("warn_off") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; + } else if ( project->isActiveConfig("warn_on") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; + } + if ( project->isActiveConfig("debug") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; + } + if(!project->isEmpty("QMAKE_INCREMENTAL")) + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_INCREMENTAL"]; + else if(!project->isEmpty("QMAKE_LFLAGS_PREBIND") && + !project->variables()["QMAKE_LIB_FLAG"].isEmpty() && + project->isActiveConfig("dll")) + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_PREBIND"]; + if(!project->isEmpty("QMAKE_INCDIR")) + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; + if(!project->isEmpty("QMAKE_LIBDIR")) { + if ( !project->isEmpty("QMAKE_RPATH") ) + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR", " " + var("QMAKE_RPATH"), + " " + var("QMAKE_RPATH"), ""); + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue( "QMAKE_LIBDIR", "-L", " -L", "" ); + } + if ( extern_libs && (project->isActiveConfig("qt") || project->isActiveConfig("opengl")) ) { + if(configs.findIndex("x11lib") == -1) + configs.append("x11lib"); + if ( project->isActiveConfig("opengl") && configs.findIndex("x11inc") == -1 ) + configs.append("x11inc"); + } + if ( project->isActiveConfig("x11") ) { + if(configs.findIndex("x11lib") == -1) + configs.append("x11lib"); + if(configs.findIndex("x11inc") == -1) + configs.append("x11inc"); + } + if ( project->isActiveConfig("qt") ) { + if ( project->isActiveConfig("accessibility" ) ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); + if ( project->isActiveConfig("tablet") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); + if(configs.findIndex("moc")) configs.append("moc"); + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + if ( !project->isActiveConfig("debug") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); + if ( !is_qt ) { + if ( !project->isEmpty("QMAKE_LIBDIR_QT") ) { + if ( !project->isEmpty("QMAKE_RPATH") ) + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_QT", " " + var("QMAKE_RPATH"), + " " + var("QMAKE_RPATH"), ""); + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_QT", "-L", " -L", ""); + } + if (project->isActiveConfig("thread") && !project->isEmpty("QMAKE_LIBS_QT_THREAD")) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + } + } + if ( project->isActiveConfig("thread") ) { + if(project->isActiveConfig("qt")) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); + if ( !project->isEmpty("QMAKE_CFLAGS_THREAD")) + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_THREAD"]; + if( !project->isEmpty("QMAKE_CXXFLAGS_THREAD")) + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_THREAD"]; + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_THREAD"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_THREAD"]; + if(!project->isEmpty("QMAKE_LFLAGS_THREAD")) + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_THREAD"]; + } + if ( project->isActiveConfig("opengl") ) { + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_OPENGL"]; + if(!project->isEmpty("QMAKE_LIBDIR_OPENGL")) + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_OPENGL", "-L", " -L", ""); + if ( is_qt ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL_QT"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + } + if(project->isActiveConfig("global_init_link_order")) + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + if ( project->isActiveConfig("x11sm") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_X11SM"]; + if ( project->isActiveConfig("dylib") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_DYNLOAD"]; + if ( project->isActiveConfig("x11inc") ) + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_X11"]; + if ( project->isActiveConfig("x11lib") ) { + if(!project->isEmpty("QMAKE_LIBDIR_X11")) + project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_X11", "-L", " -L", ""); + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_X11"]; + } + if ( project->isActiveConfig("moc") ) + setMocAware(TRUE); + if ( project->isEmpty("QMAKE_RUN_CC") ) + project->variables()["QMAKE_RUN_CC"].append("$(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src"); + if ( project->isEmpty("QMAKE_RUN_CC_IMP") ) + project->variables()["QMAKE_RUN_CC_IMP"].append("$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<"); + if ( project->isEmpty("QMAKE_RUN_CXX") ) + project->variables()["QMAKE_RUN_CXX"].append("$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src"); + if ( project->isEmpty("QMAKE_RUN_CXX_IMP") ) + project->variables()["QMAKE_RUN_CXX_IMP"].append("$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<"); + project->variables()["QMAKE_FILETAGS"] += QStringList::split("HEADERS SOURCES TARGET DESTDIR", " "); + if ( !project->isEmpty("PRECOMPH") ) { + initOutPaths(); // Need to fix MOC_DIR since we do this before init() + QString allmoc = fileFixify(project->first("MOC_DIR") + "/allmoc.cpp", QDir::currentDirPath(), Option::output_dir); + project->variables()["SOURCES"].prepend(allmoc); + project->variables()["HEADERS_ORIG"] = project->variables()["HEADERS"]; + project->variables()["HEADERS"].clear(); + } + if( project->isActiveConfig("GNUmake") && !project->isEmpty("QMAKE_CFLAGS_DEPS")) + include_deps = TRUE; //do not generate deps + + MakefileGenerator::init(); + if ( project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + if(!project->isEmpty("QMAKE_APP_FLAG")) { + if(project->isEmpty("DESTDIR")) + project->values("DESTDIR").append(""); + project->variables()["DESTDIR"].first() += project->variables()["TARGET"].first() + + ".app/Contents/MacOS/"; + project->variables()["QMAKE_PKGINFO"].append(project->first("DESTDIR") + "../PkgInfo"); + project->variables()["ALL_DEPS"] += project->first("QMAKE_PKGINFO"); + + QString plist = specdir() + QDir::separator() + "Info.plist." + + project->first("TEMPLATE"); + if(QFile::exists(Option::fixPathToLocalOS(plist))) { + project->variables()["QMAKE_INFO_PLIST"].append(plist); + project->variables()["QMAKE_INFO_PLIST_OUT"].append(project->first("DESTDIR") + + "../Info.plist"); + project->variables()["ALL_DEPS"] += project->first("QMAKE_INFO_PLIST_OUT"); + if(!project->isEmpty("RC_FILE")) + project->variables()["ALL_DEPS"] += project->first("DESTDIR") + + "../Resources/application.icns"; + } + } + } + + if(!project->isEmpty("QMAKE_INTERNAL_INCLUDED_FILES")) + project->variables()["DISTFILES"] += project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"]; + project->variables()["DISTFILES"] += Option::mkfile::project_files; + + init2(); + project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "QMAKE_LIBDIR_FLAGS" << "QMAKE_LIBS"; + if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) { + bool ok; + int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok); + QStringList ar_sublibs, objs = project->variables()["OBJECTS"] + project->variables()["OBJMOC"]; + if(ok && max_files > 5 && max_files < (int)objs.count()) { + int obj_cnt = 0, lib_cnt = 0; + QString lib; + for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { + if((++obj_cnt) >= max_files) { + if(lib_cnt) { + lib.sprintf("lib%s-tmp%d.a", project->first("QMAKE_ORIG_TARGET").latin1(), lib_cnt); + ar_sublibs << lib; + obj_cnt = 0; + } + lib_cnt++; + } + } + } + if(!ar_sublibs.isEmpty()) { + project->variables()["QMAKE_AR_SUBLIBS"] = ar_sublibs; + project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "QMAKE_AR_SUBLIBS"; + } + } +} + +QStringList +UnixMakefileGenerator::uniqueSetLFlags(const QStringList &list1, QStringList &list2) +{ + QStringList ret; + for(QStringList::ConstIterator it = list1.begin(); it != list1.end(); ++it) { + bool unique = TRUE; + if((*it).startsWith("-")) { + if((*it).startsWith("-l") || (*it).startsWith("-L")) { + unique = list2.findIndex((*it)) == -1; + } else if(project->isActiveConfig("macx") && (*it).startsWith("-framework")) { + int as_one = TRUE; + QString framework_in; + if((*it).length() > 11) { + framework_in = (*it).mid(11); + } else { + if(it != list1.end()) { + ++it; + as_one = FALSE; + framework_in = (*it); + } + } + if(!framework_in.isEmpty()) { + for(QStringList::ConstIterator outit = list2.begin(); outit != list2.end(); ++outit) { + if((*outit).startsWith("-framework")) { + QString framework_out; + if((*outit).length() > 11) { + framework_out = (*outit).mid(11); + } else { + if(it != list2.end()) { + ++outit; + framework_out = (*outit); + } + } + if(framework_out == framework_in) { + unique = FALSE; + break; + } + } + } + if(unique) { + unique = FALSE; //because I'm about to just insert it myself + if(as_one) { + ret.append("-framework " + framework_in); + } else { + ret.append("-framework"); + ret.append(framework_in); + } + } + } + } else { + unique = (list2.findIndex((*it)) == -1); + } + } else if(QFile::exists((*it))) { + unique = (list2.findIndex((*it)) == -1); + } + if(unique) + ret.append((*it)); + } + return ret; +} + + +void +UnixMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) +{ + if(var == "QMAKE_PRL_LIBS") + project->variables()["QMAKE_CURRENT_PRL_LIBS"] += uniqueSetLFlags(l, project->variables()["QMAKE_LIBS"]); + else + MakefileGenerator::processPrlVariable(var, l); +} + +void +UnixMakefileGenerator::processPrlFiles() +{ + QDict<void> processed; + QPtrList<MakefileDependDir> libdirs; + libdirs.setAutoDelete(TRUE); + const QString lflags[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null }; + for(int i = 0; !lflags[i].isNull(); i++) { + for(bool ret = FALSE; TRUE; ret = FALSE) { + QStringList l_out; + QStringList &l = project->variables()[lflags[i]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + project->variables()["QMAKE_CURRENT_PRL_LIBS"].clear(); + QString opt = (*it).stripWhiteSpace();; + if(opt.startsWith("-")) { + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + } else if(opt.startsWith("-l") && !processed[opt]) { + QString lib = opt.right(opt.length() - 2), prl; + for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { + prl = mdd->local_dir + Option::dir_sep + "lib" + lib + Option::prl_ext; + if(processPrlFile(prl)) { + if(prl.startsWith(mdd->local_dir)) + prl.replace(0, mdd->local_dir.length(), mdd->real_dir); + QRegExp reg("^.*lib(" + lib + "[^./=]*)\\..*$"); + if(reg.exactMatch(prl)) + prl = "-l" + reg.cap(1); + opt = prl; + processed.insert(opt, (void*)1); + ret = TRUE; + break; + } + } + } else if(project->isActiveConfig("macx") && opt.startsWith("-framework")) { + if(opt.length() > 11) { + opt = opt.mid(11); + } else { + ++it; + opt = (*it); + } + QString prl = "/System/Library/Frameworks/" + opt + + ".framework/" + opt + Option::prl_ext; + if(processPrlFile(prl)) + ret = TRUE; + l_out.append("-framework"); + } + if(!opt.isEmpty()) + l_out.append(opt); + l_out += uniqueSetLFlags(project->variables()["QMAKE_CURRENT_PRL_LIBS"], l_out); + } else { + if(!processed[opt] && processPrlFile(opt)) { + processed.insert(opt, (void*)1); + ret = TRUE; + } + if(!opt.isEmpty()) + l_out.append(opt); + l_out += uniqueSetLFlags(project->variables()["QMAKE_CURRENT_PRL_LIBS"], l_out); + } + } + if(ret && l != l_out) + l = l_out; + else + break; + } + } +} + +QString +UnixMakefileGenerator::defaultInstall(const QString &t) +{ + if(t != "target" || project->first("TEMPLATE") == "subdirs") + return QString(); + + bool resource = FALSE; + QStringList &uninst = project->variables()[t + ".uninstall"]; + QString ret, destdir=fileFixify(project->first("DESTDIR")); + QString targetdir = Option::fixPathToTargetOS(project->first("target.path"), FALSE); + if(!destdir.isEmpty() && destdir.right(1) != Option::dir_sep) + destdir += Option::dir_sep; + targetdir = "$(INSTALL_ROOT)" + Option::fixPathToTargetOS(targetdir, FALSE); + if(targetdir.right(1) != Option::dir_sep) + targetdir += Option::dir_sep; + + QStringList links; + QString target="$(TARGET)"; + if(project->first("TEMPLATE") == "app") { + target = "$(QMAKE_TARGET)"; + if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { + destdir += "../../../"; + target += ".app"; + resource = TRUE; + } + } else if(project->first("TEMPLATE") == "lib") { + if(project->isActiveConfig("create_prl") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) { + QString dst_prl = project->first("QMAKE_INTERNAL_PRL_FILE"); + int slsh = dst_prl.findRev('/'); + if(slsh != -1) + dst_prl = dst_prl.right(dst_prl.length() - slsh - 1); + dst_prl = targetdir + dst_prl; + ret += "-$(COPY) " + project->first("QMAKE_INTERNAL_PRL_FILE") + " " + dst_prl; + if(!uninst.isEmpty()) + uninst.append("\n\t"); + uninst.append("-$(DEL_FILE) \"" + dst_prl + "\""); + } + QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); + if ( os != "cygwin" ) { + if ( !project->isActiveConfig("staticlib") && !project->isActiveConfig("plugin") ) { + if ( os == "hpux" ) { + links << "$(TARGET0)"; + } else { + links << "$(TARGET0)" << "$(TARGET1)" << "$(TARGET2)"; + } + } + } + } + QString src_targ = target; + if(!destdir.isEmpty()) + src_targ = Option::fixPathToTargetOS(destdir + target, FALSE); + QString dst_targ = fileFixify(targetdir + target); + if(!ret.isEmpty()) + ret += "\n\t"; + ret += QString(resource ? "-$(COPY_DIR)" : "-$(COPY)") + " \"" + + src_targ + "\" \"" + dst_targ + "\""; + if(!project->isEmpty("QMAKE_STRIP")) { + ret += "\n\t-" + var("QMAKE_STRIP"); + if(resource) + ret = " \"" + dst_targ + "/Contents/MacOS/$(QMAKE_TARGET)"; + else + ret += " \"" + dst_targ + "\""; + } + if(!uninst.isEmpty()) + uninst.append("\n\t"); + if(resource) + uninst.append("-$(DEL_FILE) -r \"" + dst_targ + "\""); + else + uninst.append("-$(DEL_FILE) \"" + dst_targ + "\""); + if(!links.isEmpty()) { + for(QStringList::Iterator it = links.begin(); it != links.end(); it++) { + if(Option::target_mode == Option::TARG_WIN_MODE || + Option::target_mode == Option::TARG_MAC9_MODE) { + } else if(Option::target_mode == Option::TARG_UNIX_MODE || + Option::target_mode == Option::TARG_MACX_MODE) { + QString link = Option::fixPathToTargetOS(destdir + (*it), FALSE); + int lslash = link.findRev(Option::dir_sep); + if(lslash != -1) + link = link.right(link.length() - (lslash + 1)); + QString dst_link = fileFixify(targetdir + link); + ret += "\n\t-$(SYMLINK) \"$(TARGET)\" \"" + dst_link + "\""; + if(!uninst.isEmpty()) + uninst.append("\n\t"); + uninst.append("-$(DEL_FILE) \"" + dst_link + "\""); + } + } + } + return ret; +} + + diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h new file mode 100644 index 0000000..e889dcc --- a/dev/null +++ b/qmake/generators/unix/unixmake.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __UNIXMAKE_H__ +#define __UNIXMAKE_H__ + +#include "makefile.h" + +class UnixMakefileGenerator : public MakefileGenerator +{ + bool init_flag, include_deps; + bool writeMakefile(QTextStream &); + QStringList uniqueSetLFlags(const QStringList &list1, QStringList &list2); + +public: + UnixMakefileGenerator(QMakeProject *p); + ~UnixMakefileGenerator(); + +protected: + virtual bool doDepends() const { return !include_deps && MakefileGenerator::doDepends(); } + virtual QString defaultInstall(const QString &); + virtual void processPrlVariable(const QString &, const QStringList &); + virtual void processPrlFiles(); + + virtual void init(); + + void writeMakeParts(QTextStream &); + void writeSubdirs(QTextStream &, bool=TRUE); + +private: + void init2(); +}; + +inline UnixMakefileGenerator::~UnixMakefileGenerator() +{ } + + +#endif /* __UNIXMAKE_H__ */ diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp new file mode 100644 index 0000000..1797b98 --- a/dev/null +++ b/qmake/generators/unix/unixmake2.cpp @@ -0,0 +1,1048 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "unixmake.h" +#include "option.h" +#include <qregexp.h> +#include <qfile.h> +#include <qdir.h> +#include <time.h> + + +UnixMakefileGenerator::UnixMakefileGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE), include_deps(FALSE) +{ + +} + +bool +UnixMakefileGenerator::writeMakefile(QTextStream &t) +{ + writeHeader(t); + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + t << "all clean:" << "\n\t" + << "@echo \"Some of the required modules (" + << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" + << "@echo \"Skipped.\"" << endl << endl; + writeMakeQmake(t); + return TRUE; + } + + if (project->variables()["TEMPLATE"].first() == "app" || + project->variables()["TEMPLATE"].first() == "lib") { + writeMakeParts(t); + return MakefileGenerator::writeMakefile(t); + } else if(project->variables()["TEMPLATE"].first() == "subdirs") { + writeSubdirs(t); + return TRUE; + } + return FALSE; +} + +void +UnixMakefileGenerator::writeMakeParts(QTextStream &t) +{ + QString deps = fileFixify(Option::output.name()), prl; + bool do_incremental = (project->isActiveConfig("incremental") && + !project->variables()["QMAKE_INCREMENTAL"].isEmpty() && + (!project->variables()["QMAKE_APP_FLAG"].isEmpty() || + !project->isActiveConfig("staticlib"))), + src_incremental=FALSE, moc_incremental=FALSE; + QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); + + t << "####### Compiler, tools and options" << endl << endl; + t << "CC = "; + if (project->isActiveConfig("thread") && + ! project->variables()["QMAKE_CC_THREAD"].isEmpty()) + t << var("QMAKE_CC_THREAD") << endl; + else + t << var("QMAKE_CC") << endl; + + t << "CXX = "; + if (project->isActiveConfig("thread") && + ! project->variables()["QMAKE_CXX_THREAD"].isEmpty()) + t << var("QMAKE_CXX_THREAD") << endl; + else + t << var("QMAKE_CXX") << endl; + + t << "LEX = " << var("QMAKE_LEX") << endl; + t << "YACC = " << var("QMAKE_YACC") << endl; + t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl; + t << "YACCFLAGS= " << var("QMAKE_YACCFLAGS") << endl; + t << "INCPATH = " << varGlue("INCLUDEPATH","-I", " -I", "") << " -I" << specdir() << endl; + + if(!project->isActiveConfig("staticlib")) { + t << "LINK = "; + if (project->isActiveConfig("thread") && + ! project->variables()["QMAKE_LINK_THREAD"].isEmpty()) + t << var("QMAKE_LINK_THREAD") << endl; + else + t << var("QMAKE_LINK") << endl; + + t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; + t << "LIBS = " << "$(SUBLIBS) " << var("QMAKE_LIBDIR_FLAGS") << " " << var("QMAKE_LIBS") << endl; + } + + t << "AR = " << var("QMAKE_AR") << endl; + t << "RANLIB = " << var("QMAKE_RANLIB") << endl; + t << "MOC = " << var("QMAKE_MOC") << endl; + t << "UIC = " << var("QMAKE_UIC") << endl; + t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "TAR = " << var("QMAKE_TAR") << endl; + t << "GZIP = " << var("QMAKE_GZIP") << endl; + t << "COPY = " << var("QMAKE_COPY") << endl; + t << "COPY_FILE= " << var("QMAKE_COPY_FILE") << endl; + t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; + t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << endl; + + t << "####### Output directory" << endl << endl; + if (! project->variables()["OBJECTS_DIR"].isEmpty()) + t << "OBJECTS_DIR = " << var("OBJECTS_DIR") << endl; + else + t << "OBJECTS_DIR = ./" << endl; + t << endl; + + /* files */ + t << "####### Files" << endl << endl; + t << "HEADERS = " << varList("HEADERS") << endl; + t << "SOURCES = " << varList("SOURCES") << endl; + if(do_incremental) { + QStringList &objs = project->variables()["OBJECTS"], &incrs = project->variables()["QMAKE_INCREMENTAL"], incrs_out; + t << "OBJECTS = "; + for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { + bool increment = FALSE; + for(QStringList::Iterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { + if((*objit).find(QRegExp((*incrit), TRUE, TRUE)) != -1) { + increment = TRUE; + incrs_out.append((*objit)); + break; + } + } + if(!increment) + t << "\\\n\t\t" << (*objit); + } + if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done! + t << incrs_out.join(" \\\n\t\t") << endl; + } else if(!incrs_out.count()) { + t << endl; + } else { + src_incremental = TRUE; + t << endl; + t << "INCREMENTAL_OBJECTS = " << incrs_out.join(" \\\n\t\t") << endl; + } + } else { + t << "OBJECTS = " << varList("OBJECTS") << endl; + } + t << "FORMS = " << varList("FORMS") << endl; + t << "UICDECLS = " << varList("UICDECLS") << endl; + t << "UICIMPLS = " << varList("UICIMPLS") << endl; + QString srcMoc = varList("SRCMOC"), objMoc = varList("OBJMOC"); + t << "SRCMOC = " << srcMoc << endl; + if(do_incremental) { + QStringList &objs = project->variables()["OBJMOC"], + &incrs = project->variables()["QMAKE_INCREMENTAL"], incrs_out; + t << "OBJMOC = "; + for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { + bool increment = FALSE; + for(QStringList::Iterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { + if((*objit).find(QRegExp((*incrit), TRUE, TRUE)) != -1) { + increment = TRUE; + incrs_out.append((*objit)); + break; + } + } + if(!increment) + t << "\\\n\t\t" << (*objit); + } + if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done! + t << incrs_out.join(" \\\n\t\t") << endl; + } else if(!incrs_out.count()) { + t << endl; + } else { + moc_incremental = TRUE; + t << endl; + t << "INCREMENTAL_OBJMOC = " << incrs_out.join(" \\\n\t\t") << endl; + } + } else { + t << "OBJMOC = " << objMoc << endl; + } + if(do_incremental && !moc_incremental && !src_incremental) + do_incremental = FALSE; + t << "DIST = " << varList("DISTFILES") << endl; + t << "QMAKE_TARGET = " << var("QMAKE_ORIG_TARGET") << endl; + t << "DESTDIR = " << var("DESTDIR") << endl; + t << "TARGET = " << var("TARGET") << endl; + if(project->isActiveConfig("plugin") ) { + t << "TARGETD = " << var("TARGET") << endl; + } else if (!project->isActiveConfig("staticlib") && project->variables()["QMAKE_APP_FLAG"].isEmpty()) { + t << "TARGETA = " << var("TARGETA") << endl; + if (os == "hpux") { + t << "TARGETD = " << var("TARGET_x") << endl; + t << "TARGET0 = " << var("TARGET_") << endl; + } + else { + t << "TARGETD = " << var("TARGET_x.y.z") << endl; + t << "TARGET0 = " << var("TARGET_") << endl; + t << "TARGET1 = " << var("TARGET_x") << endl; + t << "TARGET2 = " << var("TARGET_x.y") << endl; + } + } + t << endl; + + // blasted incldues + QStringList &qeui = project->variables()["QMAKE_EXTRA_UNIX_INCLUDES"]; + QStringList::Iterator it; + for( it = qeui.begin(); it != qeui.end(); ++it) + t << "include " << (*it) << endl; + + /* rules */ + t << "first: all" << endl; + t << "####### Implicit rules" << endl << endl; + t << ".SUFFIXES: .c"; + QStringList::Iterator cppit; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << " " << (*cppit); + t << endl << endl; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << (*cppit) << ".o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".c.o:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + + if(include_deps) { + QString cmd=var("QMAKE_CFLAGS_DEPS") + " "; + cmd += varGlue("DEFINES","-D"," -D","") + varGlue("PRL_EXPORT_DEFINES"," -D"," -D",""); + if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) + cmd += " -I" + project->first("QMAKE_ABSOLUTE_SOURCE_PATH") + " "; + cmd += " $(INCPATH) " + varGlue("DEPENDPATH", "-I", " -I", ""); + QString odir; + if(!project->variables()["OBJECTS_DIR"].isEmpty()) + odir = project->first("OBJECTS_DIR"); + t << "###### Dependancies" << endl << endl; + t << odir << ".deps/%.d: %.cpp\n\t" + << "@echo Creating depend for $<" << "\n\t" + << "@test -d $(@D) || mkdir -p $(@D)" << "\n\t" + << "@$(CXX) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@" << endl << endl; + + t << odir << ".deps/%.d: %.c\n\t" + << "@echo Creating depend for $<" << "\n\t" + << "@test -d $(@D) || mkdir -p $(@D)" << "\n\t" + << "@$(CC) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@" << endl << endl; + + + QString src[] = { "SOURCES", "UICIMPLS", "SRCMOC", QString::null }; + for(int x = 0; !src[x].isNull(); x++) { + QStringList &l = project->variables()[src[x]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + if(!(*it).isEmpty()) { + QString d_file; + if((*it).endsWith(".c")) { + d_file = (*it).left((*it).length() - 2); + } else { + for(QStringList::Iterator cppit = Option::cpp_ext.begin(); + cppit != Option::cpp_ext.end(); ++cppit) { + if((*it).endsWith((*cppit))) { + d_file = (*it).left((*it).length() - (*cppit).length()); + break; + } + } + } + if(!d_file.isEmpty()) { + d_file = odir + ".deps/" + d_file + ".d"; + QStringList deps = findDependencies((*it)).grep(QRegExp(Option::moc_ext + "$")); + if(!deps.isEmpty()) + t << d_file << ": " << deps.join(" ") << endl; + t << "-include " << d_file << endl; + } + } + } + } + } + + t << "####### Build rules" << endl << endl; + if(!project->variables()["SUBLIBS"].isEmpty()) { + QString libdir = "tmp/"; + if(!project->isEmpty("SUBLIBS_DIR")) + libdir = project->first("SUBLIBS_DIR"); + t << "SUBLIBS= "; + QStringList &l = project->variables()["SUBLIBS"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) + t << libdir << "lib" << (*it) << ".a "; + t << endl << endl; + } + if(project->isActiveConfig("depend_prl") && !project->isEmpty("QMAKE_PRL_INTERNAL_FILES")) { + QStringList &l = project->variables()["QMAKE_PRL_INTERNAL_FILES"]; + QStringList::Iterator it; + for(it = l.begin(); it != l.end(); ++it) { + QMakeProject proj; + if(proj.read((*it), QDir::currentDirPath()) && !proj.isEmpty("QMAKE_PRL_BUILD_DIR")) { + QString dir; + int slsh = (*it).findRev(Option::dir_sep); + if(slsh != -1) + dir = (*it).left(slsh + 1); + QString targ = dir + proj.first("QMAKE_PRL_TARGET"); + deps += " " + targ; + t << targ << ":" << "\n\t" + << "@echo \"Creating '" << targ << "'\"" << "\n\t" + << "(cd " << proj.first("QMAKE_PRL_BUILD_DIR") << ";" + << "$(MAKE) )" << endl; + } + } + } + if(!project->variables()["QMAKE_APP_FLAG"].isEmpty()) { + QString destdir = project->first("DESTDIR"); + if(do_incremental) { + //incremental target + QString incr_target = var("TARGET") + "_incremental"; + if(incr_target.find(Option::dir_sep) != -1) + incr_target = incr_target.right(incr_target.length() - + (incr_target.findRev(Option::dir_sep) + 1)); + QString incr_deps, incr_objs; + if(project->first("QMAKE_INCREMENTAL_STYLE") == "ld") { + QString incr_target_dir = var("OBJECTS_DIR") + incr_target + Option::obj_ext; + //actual target + t << incr_target_dir << ": $(OBJECTS)" << "\n\t" + << "ld -r -o "<< incr_target_dir << " $(OBJECTS)" << endl; + //communicated below + deps.prepend(incr_target_dir + " "); + incr_deps = "$(UICDECLS) $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC) $(OBJMOC)"; + if(!incr_objs.isEmpty()) + incr_objs += " "; + incr_objs += incr_target_dir; + } else { + //actual target + QString incr_target_dir = var("DESTDIR") + "lib" + incr_target + "." + + project->variables()["QMAKE_EXTENSION_SHLIB"].first(); + QString incr_lflags = var("QMAKE_LFLAGS_SHLIB") + " "; + if(project->isActiveConfig("debug")) + incr_lflags += var("QMAKE_LFLAGS_DEBUG"); + else + incr_lflags += var("QMAKE_LFLAGS_RELEASE"); + t << incr_target_dir << ": $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << "\n\t"; + if(!destdir.isEmpty()) + t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + t << "$(LINK) " << incr_lflags << " -o "<< incr_target_dir << + " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << endl; + //communicated below + if(!destdir.isEmpty()) { + if(!incr_objs.isEmpty()) + incr_objs += " "; + incr_objs += "-L" + destdir; + } else { + if(!incr_objs.isEmpty()) + incr_objs += " "; + incr_objs += "-L" + QDir::currentDirPath(); + } + if(!incr_objs.isEmpty()) + incr_objs += " "; + incr_objs += " -l" + incr_target; + deps.prepend(incr_target_dir + " "); + incr_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; + } + t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" + << endl << endl; + + //real target + t << var("TARGET") << ": " << " " << incr_deps << " " << var("TARGETDEPS") << "\n\t"; + if(!destdir.isEmpty()) + t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + if(!project->isEmpty("QMAKE_PRE_LINK")) + t << var("QMAKE_PRE_LINK") << "\n\t"; + t << "$(LINK) $(LFLAGS) -o $(TARGET) " << incr_deps << " " << incr_objs << " $(LIBS)"; + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK"); + t << endl << endl; + } else { + t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" + << endl << endl; + + t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS") << "\n\t"; + if(!destdir.isEmpty()) + t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + if(!project->isEmpty("QMAKE_PRE_LINK")) + t << var("QMAKE_PRE_LINK") << "\n\t"; + t << "$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)"; + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK"); + t << endl << endl; + } + } else if(!project->isActiveConfig("staticlib")) { + QString destdir = project->first("DESTDIR"), incr_deps; + if(do_incremental) { + QString s_ext = project->variables()["QMAKE_EXTENSION_SHLIB"].first(); + QString incr_target = var("QMAKE_ORIG_TARGET").replace( + QRegExp("\\." + s_ext), "").replace(QRegExp("^lib"), "") + "_incremental"; + if(incr_target.find(Option::dir_sep) != -1) + incr_target = incr_target.right(incr_target.length() - + (incr_target.findRev(Option::dir_sep) + 1)); + + if(project->first("QMAKE_INCREMENTAL_STYLE") == "ld") { + QString incr_target_dir = var("OBJECTS_DIR") + incr_target + Option::obj_ext; + //actual target + const QString link_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; + t << incr_target_dir << ": " << link_deps << "\n\t" + << "ld -r -o " << incr_target_dir << " " << link_deps << endl; + //communicated below + QStringList &cmd = project->variables()["QMAKE_LINK_SHLIB_CMD"]; + cmd.first().replace("$(OBJECTS) $(OBJMOC)", + "$(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"); //ick + cmd.append(incr_target_dir); + deps.prepend(incr_target_dir + " "); + incr_deps = "$(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; + } else { + //actual target + QString incr_target_dir = var("DESTDIR") + "lib" + incr_target + "." + s_ext; + QString incr_lflags = var("QMAKE_LFLAGS_SHLIB") + " "; + if(!project->isEmpty("QMAKE_LFLAGS_INCREMENTAL")) + incr_lflags += var("QMAKE_LFLAGS_INCREMENTAL") + " "; + if(project->isActiveConfig("debug")) + incr_lflags += var("QMAKE_LFLAGS_DEBUG"); + else + incr_lflags += var("QMAKE_LFLAGS_RELEASE"); + t << incr_target_dir << ": $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << "\n\t"; + if(!destdir.isEmpty()) + t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + t << "$(LINK) " << incr_lflags << " -o "<< incr_target_dir << + " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << endl; + //communicated below + QStringList &cmd = project->variables()["QMAKE_LINK_SHLIB_CMD"]; + if(!destdir.isEmpty()) + cmd.append(" -L" + destdir); + cmd.append(" -l" + incr_target); + deps.prepend(incr_target_dir + " "); + incr_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; + } + + t << "all: " << " " << deps << " " << varGlue("ALL_DEPS",""," ","") + << " " << var("DESTDIR_TARGET") << endl << endl; + + //real target + t << var("DESTDIR_TARGET") << ": " << incr_deps << " $(SUBLIBS) " << + var("TARGETDEPS"); + } else { + t << "all: " << deps << " " << varGlue("ALL_DEPS",""," ","") << " " << + var("DESTDIR_TARGET") << endl << endl; + t << var("DESTDIR_TARGET") << ": $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) " << + var("TARGETDEPS"); + } + if(!destdir.isEmpty()) + t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir; + if(!project->isEmpty("QMAKE_PRE_LINK")) + t << "\n\t" << var("QMAKE_PRE_LINK"); + + if(project->isActiveConfig("plugin")) { + t << "\n\t" + << "-$(DEL_FILE) $(TARGET)" << "\n\t" + << var("QMAKE_LINK_SHLIB_CMD"); + if(!destdir.isEmpty()) + t << "\n\t" + << "-$(MOVE) $(TARGET) " << var("DESTDIR"); + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK") << "\n\t"; + t << endl << endl; + } else if ( os == "hpux" ) { + t << "\n\t" + << "-$(DEL_FILE) $(TARGET) $(TARGET0)" << "\n\t" + << var("QMAKE_LINK_SHLIB_CMD") << "\n\t"; + t << varGlue("QMAKE_LN_SHLIB",""," "," $(TARGET) $(TARGET0)"); + if(!destdir.isEmpty()) + t << "\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET0)\n\t" + << "-$(MOVE) $(TARGET) $(TARGET0) " << var("DESTDIR"); + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK"); + t << endl << endl; + } else { + t << "\n\t" + << "-$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2)" << "\n\t" + << var("QMAKE_LINK_SHLIB_CMD") << "\n\t"; + t << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET0)") << "\n\t" + << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET1)") << "\n\t" + << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET2)"); + if(!destdir.isEmpty()) + t << "\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET0)\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET1)\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET2)\n\t" + << "-$(MOVE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) " << var("DESTDIR"); + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\n\t" << var("QMAKE_POST_LINK"); + t << endl << endl; + } + t << endl << endl; + + if (! project->isActiveConfig("plugin")) { + t << "staticlib: $(TARGETA)" << endl << endl; + t << "$(TARGETA): $(UICDECLS) $(OBJECTS) $(OBJMOC)"; + if(do_incremental) + t << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; + t << var("TARGETDEPS") << "\n\t" + << "-$(DEL_FILE) $(TARGETA) " << "\n\t" + << var("QMAKE_AR_CMD"); + if(do_incremental) + t << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; + if(!project->isEmpty("QMAKE_RANLIB")) + t << "\n\t" << "$(RANLIB) $(TARGETA)"; + t << endl << endl; + } + } else { + t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << var("DESTDIR") << "$(TARGET) " + << varGlue("QMAKE_AR_SUBLIBS", var("DESTDIR"), " " + var("DESTDIR"), "") << "\n\n" + << "staticlib: " << var("DESTDIR") << "$(TARGET)" << "\n\n"; + if(project->isEmpty("QMAKE_AR_SUBLIBS")) { + t << var("DESTDIR") << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(TARGETDEPS) " << "\n\t"; + if(!project->isEmpty("DESTDIR")) { + QString destdir = project->first("DESTDIR"); + t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + } + t << "-$(DEL_FILE) $(TARGET)" << "\n\t" + << var("QMAKE_AR_CMD") << "\n"; + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\t" << var("QMAKE_POST_LINK") << "\n"; + if(!project->isEmpty("QMAKE_RANLIB")) + t << "\t" << "$(RANLIB) $(TARGET)" << "\n"; + if(!project->isEmpty("DESTDIR")) + t << "\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)" << "\n" + << "\t" << "-$(MOVE) $(TARGET) " << var("DESTDIR") << "\n"; + } else { + int cnt = 0, max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(); + QStringList objs = project->variables()["OBJECTS"] + project->variables()["OBJMOC"], + libs = project->variables()["QMAKE_AR_SUBLIBS"]; + libs.prepend("$(TARGET)"); + for(QStringList::Iterator libit = libs.begin(), objit = objs.begin(); + libit != libs.end(); ++libit) { + QStringList build; + for(cnt = 0; cnt < max_files && objit != objs.end(); ++objit, cnt++) + build << (*objit); + QString ar; + if((*libit) == "$(TARGET)") { + t << var("DESTDIR") << "$(TARGET): $(UICDECLS) " << " $(TARGETDEPS) " + << valList(build) << "\n\t"; + ar = project->variables()["QMAKE_AR_CMD"].first(); + ar = ar.replace("$(OBJMOC)", "").replace("$(OBJECTS)", + build.join(" ")); + } else { + t << (*libit) << ": " << valList(build) << "\n\t"; + ar = "$(AR) " + (*libit) + " " + build.join(" "); + } + if(!project->isEmpty("DESTDIR")) { + QString destdir = project->first("DESTDIR"); + t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + } + t << "-$(DEL_FILE) " << (*libit) << "\n\t" + << ar << "\n"; + if(!project->isEmpty("QMAKE_POST_LINK")) + t << "\t" << var("QMAKE_POST_LINK") << "\n"; + if(!project->isEmpty("QMAKE_RANLIB")) + t << "\t" << "$(RANLIB) " << (*libit) << "\n"; + if(!project->isEmpty("DESTDIR")) + t << "\t" << "-$(DEL_FILE) " << var("DESTDIR") << (*libit) << "\n" + << "\t" << "-$(MOVE) " << (*libit) << " " << var("DESTDIR") << "\n"; + } + } + t << endl << endl; + } + + t << "mocables: $(SRCMOC)" << endl << endl; + + if(!project->isActiveConfig("no_mocdepend")) { + //this is an implicity depend on moc, so it will be built if necesary, however + //moc itself shouldn't have this dependancy - this is a little kludgy but it is + //better than the alternative for now. + QString moc = project->first("QMAKE_MOC"), target = project->first("TARGET"); + fixEnvVariables(target); + fixEnvVariables(moc); + if(target != moc) + t << "$(MOC): \n\t" + << "( cd $(QTDIR)/src/moc ; $(MAKE) )" << endl << endl; + } + + writeMakeQmake(t); + + if(!project->first("QMAKE_PKGINFO").isEmpty()) { + QString pkginfo = project->first("QMAKE_PKGINFO"); + QString destdir = project->first("DESTDIR"); + t << pkginfo << ": " << "\n\t"; + if(!destdir.isEmpty()) + t << "@test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + t << "@$(DEL_FILE) " << pkginfo << "\n\t" + << "@echo \"APPL????\" >" << pkginfo << endl; + } + if(!project->first("QMAKE_INFO_PLIST").isEmpty()) { + QString info_plist = project->first("QMAKE_INFO_PLIST"), + info_plist_out = project->first("QMAKE_INFO_PLIST_OUT"); + QString destdir = project->first("DESTDIR"); + t << info_plist_out << ": " << "\n\t"; + if(!destdir.isEmpty()) + t << "@test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; + t << "@$(DEL_FILE) " << info_plist_out << "\n\t" + << "@cp \"" << info_plist << "\" \"" << info_plist_out << "\"" << endl; + if(!project->first("RC_FILE").isEmpty()) { + QString dir = destdir + "../Resources/"; + t << dir << "application.icns:" << "\n\t" + << "@test -d " << dir << " || mkdir -p " << dir << "\n\t" + << "@cp " << var("RC_FILE") << " " << dir << "application.icns" << endl; + } + } + + QString ddir = project->isEmpty("QMAKE_DISTDIR") ? project->first("QMAKE_ORIG_TARGET") : + project->first("QMAKE_DISTDIR"); + QString ddir_c = fileFixify((project->isEmpty("OBJECTS_DIR") ? QString(".tmp/") : + project->first("OBJECTS_DIR")) + ddir); + t << "dist: " << "\n\t" + << "@mkdir -p " << ddir_c << " && " + << "$(COPY_FILE) --parents $(SOURCES) $(HEADERS) $(FORMS) $(DIST) " << ddir_c << Option::dir_sep << " && "; + if(!project->isEmpty("TRANSLATIONS")) + t << "$(COPY_FILE) --parents " << var("TRANSLATIONS") << " " << ddir_c << Option::dir_sep << " && "; + if(!project->isEmpty("FORMS")) { + QStringList &forms = project->variables()["FORMS"], ui_headers; + for(QStringList::Iterator formit = forms.begin(); formit != forms.end(); ++formit) { + QString ui_h = fileFixify((*formit) + Option::h_ext.first()); + if(QFile::exists(ui_h) ) + ui_headers << ui_h; + } + if(!ui_headers.isEmpty()) + t << "$(COPY_FILE) --parents " << val(ui_headers) << " " << ddir_c << Option::dir_sep << " && "; + } + t << "( cd `dirname " << ddir_c << "` && " + << "$(TAR) " << var("QMAKE_ORIG_TARGET") << ".tar " << ddir << " && " + << "$(GZIP) " << var("QMAKE_ORIG_TARGET") << ".tar ) && " + << "$(MOVE) `dirname " << ddir_c << "`" << Option::dir_sep << var("QMAKE_ORIG_TARGET") << ".tar.gz . && " + << "$(DEL_DIR) " << ddir_c + << endl << endl; + + QString clean_targets; + if(mocAware()) { + t << "mocclean:" << "\n"; + if(!objMoc.isEmpty() || !srcMoc.isEmpty() || moc_incremental) { + if(!objMoc.isEmpty()) + t << "\t-$(DEL_FILE) $(OBJMOC)" << '\n'; + if(!srcMoc.isEmpty()) + t << "\t-$(DEL_FILE) $(SRCMOC)" << '\n'; + if(moc_incremental) + t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJMOC)" << '\n'; + clean_targets += " mocclean"; + } + t << endl; + } + t << "uiclean:" << "\n"; + if (!var("UICIMPLS").isEmpty() || !var("UICDECLS").isEmpty()) { + t << "\t-$(DEL_FILE) $(UICIMPLS) $(UICDECLS)" << "\n"; + clean_targets += " uiclean"; + } + t << endl; + + if(do_incremental) { + t << "incrclean:" << "\n"; + if(src_incremental) + t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJECTS)" << "\n"; + if(moc_incremental) + t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJMOC)" << '\n'; + t << endl; + } + + t << "clean:" << clean_targets << "\n\t"; + if(!project->isEmpty("OBJECTS")) + t << "-$(DEL_FILE) $(OBJECTS) " << "\n\t"; + if(!project->isEmpty("IMAGES")) + t << varGlue("QMAKE_IMAGE_COLLECTION", "\t-$(DEL_FILE) ", " ", "") << "\n\t"; + if(src_incremental) + t << "-$(DEL_FILE) $(INCREMENTAL_OBJECTS)" << "\n\t"; + t << varGlue("QMAKE_CLEAN","-$(DEL_FILE) "," ","\n\t") + << "-$(DEL_FILE) *~ core *.core" << "\n" + << varGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << endl << endl; + t << "####### Sub-libraries" << endl << endl; + if ( !project->variables()["SUBLIBS"].isEmpty() ) { + QString libdir = "tmp/"; + if(!project->isEmpty("SUBLIBS_DIR")) + libdir = project->first("SUBLIBS_DIR"); + QStringList &l = project->variables()["SUBLIBS"]; + for(it = l.begin(); it != l.end(); ++it) + t << libdir << "lib" << (*it) << ".a" << ":\n\t" + << var(QString("MAKELIB") + (*it)) << endl << endl; + } + + QString destdir = project->first("DESTDIR"); + if(!destdir.isEmpty() && destdir.right(1) != Option::dir_sep) + destdir += Option::dir_sep; + t << "distclean: " << "clean\n\t" + << "-$(DEL_FILE) " << destdir << "$(TARGET)" << " " << "$(TARGET)" << "\n"; + if(!project->isActiveConfig("staticlib") && project->variables()["QMAKE_APP_FLAG"].isEmpty() && + !project->isActiveConfig("plugin")) + t << "\t-$(DEL_FILE) " << destdir << "$(TARGET0) " << destdir << "$(TARGET1) " + << destdir << "$(TARGET2) $(TARGETA)" << "\n"; + t << endl << endl; + + if ( !project->isEmpty("PRECOMPH") ) { + QString outdir = project->first("MOC_DIR"); + QString qt_dot_h = Option::fixPathToLocalOS(project->first("PRECOMPH")); + t << "###### Combined headers" << endl << endl; + //XXX + t << outdir << "allmoc.cpp: " << qt_dot_h << " " + << varList("HEADERS_ORIG") << "\n\t" + << "echo '#include \"" << qt_dot_h << "\"' >" << outdir << "allmoc.cpp" << "\n\t" + << "$(CXX) -E -DQT_MOC_CPP -DQT_NO_STL $(CXXFLAGS) $(INCPATH) >" << outdir << "allmoc.h " + << outdir << "allmoc.cpp" << "\n\t" + << "$(MOC) -o " << outdir << "allmoc.cpp " << outdir << "allmoc.h" << "\n\t" + << "perl -pi -e 's{#include \"allmoc.h\"}{#define QT_H_CPP\\n#include \"" + << qt_dot_h << "\"}' " << outdir << "allmoc.cpp" << "\n\t" + << "$(DEL_FILE) " << outdir << "allmoc.h" << endl << endl; + } + + // blasted user defined targets + QStringList &qut = project->variables()["QMAKE_EXTRA_UNIX_TARGETS"]; + for(it = qut.begin(); it != qut.end(); ++it) { + QString targ = var((*it) + ".target"), + cmd = var((*it) + ".commands"), deps; + if(targ.isEmpty()) + targ = (*it); + QStringList &deplist = project->variables()[(*it) + ".depends"]; + for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { + QString dep = var((*dep_it) + ".target"); + if(dep.isEmpty()) + dep = (*dep_it); + deps += " " + dep; + } + t << targ << ":" << deps << "\n\t" + << cmd << endl << endl; + } + t <<"FORCE:" << endl << endl; +} + +struct SubDir +{ + QString directory, profile, target, makefile; +}; + +void +UnixMakefileGenerator::writeSubdirs(QTextStream &t, bool direct) +{ + QPtrList<SubDir> subdirs; + { + QStringList subdirs_in = project->variables()["SUBDIRS"]; + for(QStringList::Iterator it = subdirs_in.begin(); it != subdirs_in.end(); ++it) { + QString file = (*it); + fileFixify(file); + SubDir *sd = new SubDir; + subdirs.append(sd); + sd->makefile = "$(MAKEFILE)"; + if((*it).right(4) == ".pro") { + int slsh = file.findRev(Option::dir_sep); + if(slsh != -1) { + sd->directory = file.left(slsh+1); + sd->profile = file.mid(slsh+1); + } else { + sd->profile = file; + } + } else { + sd->directory = file; + } + while(sd->directory.right(1) == Option::dir_sep) + sd->directory = sd->directory.left(sd->directory.length() - 1); + if(!sd->profile.isEmpty()) { + QString basename = sd->directory; + int new_slsh = basename.findRev(Option::dir_sep); + if(new_slsh != -1) + basename = basename.mid(new_slsh+1); + if(sd->profile != basename + ".pro") + sd->makefile += "." + sd->profile.left(sd->profile.length() - 4); //no need for the .pro + } + sd->target = "sub-" + (*it); + sd->target.replace('/', '-'); + sd->target.replace('.', '_'); + } + } + QPtrListIterator<SubDir> it(subdirs); + + QString ofile = Option::output.name(); + if(ofile.findRev(Option::dir_sep) != -1) + ofile = ofile.right(ofile.length() - ofile.findRev(Option::dir_sep) -1); + t << "MAKEFILE = " << var("MAKEFILE") << endl; + t << "QMAKE = " << var("QMAKE") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "SUBTARGETS = "; // subdirectory targets are sub-directory + for( it.toFirst(); it.current(); ++it) + t << " \\\n\t\t" << it.current()->target; + t << endl << endl; + t << "first: all\n\nall: " << ofile << " $(SUBTARGETS)" << endl << endl; + + // generate target rules + for( it.toFirst(); it.current(); ++it) { + bool have_dir = !(*it)->directory.isEmpty(); + QString mkfile = (*it)->makefile, out; + if(have_dir) + mkfile.prepend((*it)->directory + Option::dir_sep); + if(direct || (*it)->makefile != "$(MAKEFILE)") + out = " -o " + (*it)->makefile; + //qmake it + t << mkfile << ": " << "\n\t"; + if(have_dir) + t << "cd " << (*it)->directory << " && "; + t << "$(QMAKE) " << (*it)->profile << buildArgs() << out << endl; + //actually compile + t << (*it)->target << ": " << mkfile << " FORCE" << "\n\t"; + if(have_dir) + t << "cd " << (*it)->directory << " && "; + t << "$(MAKE) -f " << (*it)->makefile << endl << endl; + } + + if (project->isActiveConfig("ordered")) { // generate dependencies + for( it.toFirst(); it.current(); ) { + QString tar = it.current()->target; + ++it; + if (it.current()) + t << it.current()->target << ": " << tar << endl; + } + t << endl; + } + + writeMakeQmake(t); + + if(project->isEmpty("SUBDIRS")) { + t << "all qmake_all distclean install uiclean mocclean clean: FORCE" << endl; + } else { + t << "all: $(SUBTARGETS)" << endl; + t << "qmake_all:"; + for( it.toFirst(); it.current(); ++it) { + t << " "; + if(!(*it)->directory.isEmpty()) + t << (*it)->directory << Option::dir_sep; + t << (*it)->makefile; + } + for( it.toFirst(); it.current(); ++it) { + t << "\n\t ( "; + if(!(*it)->directory.isEmpty()) + t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; + t << "grep \"^qmake_all:\" " << (*it)->makefile + << " && $(MAKE) -f " << (*it)->makefile << " qmake_all" << "; ) || true"; + } + t << endl; + t << "clean uninstall install uiclean mocclean: qmake_all FORCE"; + for( it.toFirst(); it.current(); ++it) { + t << "\n\t ( "; + if(!(*it)->directory.isEmpty()) + t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; + t << "$(MAKE) -f " << (*it)->makefile << " $@" << "; ) || true"; + } + t << endl; + t << "distclean: qmake_all FORCE"; + for( it.toFirst(); it.current(); ++it) { + t << "\n\t ( "; + if(!(*it)->directory.isEmpty()) + t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; + t << "$(MAKE) -f " << (*it)->makefile << " $@; $(DEL_FILE) " << (*it)->makefile << "; ) || true"; + } + t << endl << endl; + } + t <<"FORCE:" << endl << endl; +} + +void UnixMakefileGenerator::init2() +{ + //version handling + if(project->variables()["VERSION"].isEmpty()) + project->variables()["VERSION"].append("1.0." + + (project->isEmpty("VER_PAT") ? QString("0") : + project->first("VER_PAT")) ); + QStringList l = QStringList::split('.', project->first("VERSION")); + l << "0" << "0"; //make sure there are three + project->variables()["VER_MAJ"].append(l[0]); + project->variables()["VER_MIN"].append(l[1]); + project->variables()["VER_PAT"].append(l[2]); + + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { +#if 0 + if ( project->isActiveConfig("dll") ) { + project->variables()["TARGET"] += project->variables()["TARGET.so"]; + if(project->variables()["QMAKE_LFLAGS_SHAPP"].isEmpty()) + project->variables()["QMAKE_LFLAGS_SHAPP"] += project->variables()["QMAKE_LFLAGS_SHLIB"]; + if(!project->variables()["QMAKE_LFLAGS_SONAME"].isEmpty()) + project->variables()["QMAKE_LFLAGS_SONAME"].first() += project->first("TARGET"); + } +#endif + project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); + } else if ( project->isActiveConfig("staticlib") ) { + project->variables()["TARGET"].first().prepend("lib"); + project->variables()["TARGET"].first() += ".a"; + if(project->variables()["QMAKE_AR_CMD"].isEmpty()) + project->variables()["QMAKE_AR_CMD"].append("$(AR) $(TARGET) $(OBJECTS) $(OBJMOC)"); + } else { + project->variables()["TARGETA"].append(project->first("DESTDIR") + "lib" + project->first("TARGET") + ".a"); + if ( !project->variables()["QMAKE_AR_CMD"].isEmpty() ) + project->variables()["QMAKE_AR_CMD"].first().replace("(TARGET)","(TARGETA)"); + else + project->variables()["QMAKE_AR_CMD"].append("$(AR) $(TARGETA) $(OBJECTS) $(OBJMOC)"); + QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); + if( project->isActiveConfig("plugin") ) { + project->variables()["TARGET_x.y.z"].append("lib" + + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB")); + if(project->isActiveConfig("lib_version_first")) + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + else + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + + "." + project->first("VER_MAJ")); + + project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; + if(project->isActiveConfig("qt")) + project->variables()["DEFINES"].append("QT_PLUGIN"); + } else if ( os == "hpux" ) { + project->variables()["TARGET_"].append("lib" + project->first("TARGET") + ".sl"); + if(project->isActiveConfig("lib_version_first")) + project->variables()["TARGET_x"].append("lib" + project->first("VER_MAJ") + "." + + project->first("TARGET")); + else + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ")); + project->variables()["TARGET"] = project->variables()["TARGET_x"]; + } else if ( os == "aix" ) { + project->variables()["TARGET_"].append("lib" + project->first("TARGET") + ".a"); + if(project->isActiveConfig("lib_version_first")) { + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + + "." + project->first("VER_MIN") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + "." + + project->first("VER_MIN") + "." + + project->first("VER_PAT") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + } else { + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + + "." + project->first("VER_MAJ")); + project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + + "." + project->first("VER_MAJ") + + "." + project->first("VER_MIN")); + project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + "." + + project->first("VER_MAJ") + "." + + project->first("VER_MIN") + "." + + project->first("VER_PAT")); + } + project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; + } else { + project->variables()["TARGET_"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + if(project->isActiveConfig("lib_version_first")) { + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + + "." + project->first("VER_MIN") + "." + + project->first("QMAKE_EXTENSION_SHLIB")); + project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + + project->first("VER_MAJ") + "." + + project->first("VER_MIN") + "." + + project->first("VER_PAT") + "." + + project->variables()["QMAKE_EXTENSION_SHLIB"].first()); + } else { + project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + + "." + project->first("VER_MAJ")); + project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + + project->first("QMAKE_EXTENSION_SHLIB") + + "." + project->first("VER_MAJ") + + "." + project->first("VER_MIN")); + project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + + "." + + project->variables()[ + "QMAKE_EXTENSION_SHLIB"].first() + "." + + project->first("VER_MAJ") + "." + + project->first("VER_MIN") + "." + + project->first("VER_PAT")); + } + project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; + } + if(project->isEmpty("QMAKE_LN_SHLIB")) + project->variables()["QMAKE_LN_SHLIB"].append("ln -s"); + project->variables()["DESTDIR_TARGET"].append("$(TARGET)"); + if ( !project->variables()["DESTDIR"].isEmpty() ) + project->variables()["DESTDIR_TARGET"].first().prepend(project->first("DESTDIR")); + if ( !project->variables()["QMAKE_LFLAGS_SONAME"].isEmpty() && !project->variables()["TARGET_x"].isEmpty() ) + project->variables()["QMAKE_LFLAGS_SONAME"].first() += project->first("TARGET_x"); + if ( project->variables()["QMAKE_LINK_SHLIB_CMD"].isEmpty() ) + project->variables()["QMAKE_LINK_SHLIB_CMD"].append( + "$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)"); + } + if(project->isEmpty("QMAKE_SYMBOLIC_LINK")) + project->variables()["QMAKE_SYMBOLIC_LINK"].append("ln -sf"); + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SHAPP"]; + } else if ( project->isActiveConfig("dll") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_SHLIB"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_SHLIB"]; + if ( project->isActiveConfig("plugin") ) { + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_PLUGIN"]; + if( !project->isActiveConfig("plugin_no_soname") ) + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SONAME"]; + } else { + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SHLIB"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SONAME"]; + } + QString destdir = project->first("DESTDIR"); + if ( !destdir.isEmpty() && !project->variables()["QMAKE_RPATH"].isEmpty() ) { + QString rpath_destdir = destdir; + if(QDir::isRelativePath(rpath_destdir)) { + QFileInfo fi(Option::fixPathToLocalOS(rpath_destdir)); + if(fi.convertToAbs()) //strange, shouldn't really happen + rpath_destdir = Option::fixPathToTargetOS(rpath_destdir, FALSE); + else + rpath_destdir = fi.filePath(); + } else { + rpath_destdir = Option::fixPathToTargetOS(rpath_destdir, FALSE); + } + project->variables()["QMAKE_LFLAGS"] += project->first("QMAKE_RPATH") + rpath_destdir; + } + } +} diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp new file mode 100644 index 0000000..ae7b47b --- a/dev/null +++ b/qmake/generators/win32/borland_bmake.cpp @@ -0,0 +1,477 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "borland_bmake.h" +#include "option.h" +#include <qdir.h> +#include <qregexp.h> +#include <time.h> +#include <stdlib.h> + + +BorlandMakefileGenerator::BorlandMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) +{ + +} + +bool +BorlandMakefileGenerator::writeMakefile(QTextStream &t) +{ + writeHeader(t); + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + t << "all clean:" << "\n\t" + << "@echo \"Some of the required modules (" + << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" + << "@echo \"Skipped.\"" << endl << endl; + return TRUE; + } + + if(project->first("TEMPLATE") == "app" || + project->first("TEMPLATE") == "lib") { + writeBorlandParts(t); + return MakefileGenerator::writeMakefile(t); + } + else if(project->first("TEMPLATE") == "subdirs") { + writeSubDirs(t); + return TRUE; + } + return FALSE; +} + +void +BorlandMakefileGenerator::writeBorlandParts(QTextStream &t) +{ + t << "!if !$d(BCB)" << endl; + t << "BCB = $(MAKEDIR)\\.." << endl; + t << "!endif" << endl << endl; + t << "####### Compiler, tools and options" << endl << endl; + t << "CC = " << var("QMAKE_CC") << endl; + t << "CXX = " << var("QMAKE_CXX") << endl; + t << "LEX = " << var("QMAKE_LEX") << endl; + t << "YACC = " << var("QMAKE_YACC") << endl; + t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "CXXFLAGS= " << var("QMAKE_CXXFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "LEXFLAGS=" << var("QMAKE_LEXFLAGS") << endl; + t << "YACCFLAGS=" << var("QMAKE_YACCFLAGS") << endl; + + t << "INCPATH = "; + QStringList &incs = project->variables()["INCLUDEPATH"]; + for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { + QString inc = (*incit); + inc.replace(QRegExp("\\\\*$"), ""); + inc.replace("\"", ""); + t << " -I\"" << inc << "\""; + } + t << " -I\"" << specdir() << "\"" + << endl; + + if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { + t << "LINK = " << var("QMAKE_LINK") << endl; + t << "LFLAGS = "; + if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) + t << varGlue("QMAKE_LIBDIR","-L",";","") << " "; + t << var("QMAKE_LFLAGS") << endl; + t << "LIBS = " << var("QMAKE_LIBS") << endl; + } + else { + t << "LIB = " << var("QMAKE_LIB") << endl; + } + t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") : + Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl; + t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") : + Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl; + t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : + Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl; + t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : + Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl; + t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : + Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl; + t << "ZIP = " << var("QMAKE_ZIP") << endl; + t << "DEF_FILE = " << varList("DEF_FILE") << endl; + t << "RES_FILE = " << varList("RES_FILE") << endl; + t << "COPY_FILE = " << var("QMAKE_COPY") << endl; + t << "COPY_DIR = " << var("QMAKE_COPY") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; + t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << endl; + + t << "####### Files" << endl << endl; + t << "HEADERS = " << varList("HEADERS") << endl; + t << "SOURCES = " << varList("SOURCES") << endl; + t << "OBJECTS = " << varList("OBJECTS") << endl; + t << "FORMS = " << varList("FORMS") << endl; + t << "UICDECLS = " << varList("UICDECLS") << endl; + t << "UICIMPLS = " << varList("UICIMPLS") << endl; + t << "SRCMOC = " << varList("SRCMOC") << endl; + t << "OBJMOC = " << varList("OBJMOC") << endl; + t << "DIST = " << varList("DISTFILES") << endl; + t << "TARGET = " + << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT")) + << endl; + t << endl; + + t << "####### Implicit rules" << endl << endl; + t << ".SUFFIXES: .cpp .cxx .cc .c" << endl << endl; + t << ".cpp.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".cxx.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".cc.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".c.obj:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + + t << "####### Build rules" << endl << endl; + t << "all: " << varGlue("ALL_DEPS",""," "," ") << " $(TARGET)" << endl << endl; + t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS"); + if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { + t << "\n\t" << "$(LINK) @&&|" << "\n\t" + << "$(LFLAGS) $(OBJECTS) $(OBJMOC),$(TARGET),,$(LIBS),$(DEF_FILE),$(RES_FILE)"; + } else { + t << "\n\t-del $(TARGET)" + << "\n\t" << "$(LIB) $(TARGET) @&&|" << " \n+" + << project->variables()["OBJECTS"].join(" \\\n+") << " \\\n+" + << project->variables()["OBJMOC"].join(" \\\n+"); + } + t << endl << "|" << endl; + if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) { + QStringList dlldirs = project->variables()["DLLDESTDIR"]; + for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { + t << "\n\t" << "-copy $(TARGET) " << *dlldir; + } + } + QString targetfilename = project->variables()["TARGET"].first(); + if(project->isActiveConfig("activeqt")) { + QString version = project->variables()["VERSION"].first(); + if ( version.isEmpty() ) + version = "1.0"; + + if ( project->isActiveConfig("dll")) { + t << "\n\t" << ("-$(IDC) $(TARGET) /idl tmp\\" + targetfilename + ".idl -version " + version); + t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); + t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); + t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" ); + } else { + t << "\n\t" << ("-$(TARGET) -dumpidl tmp\\" + targetfilename + ".idl -version " + version); + t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); + t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); + t << "\n\t" << ("-$(TARGET) -regserver"); + } + } + t << endl << endl; + + if(!project->variables()["RC_FILE"].isEmpty()) { + t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t" + << var("QMAKE_RC") << " " << var("RC_FILE") << endl << endl; + } + t << "mocables: $(SRCMOC)" << endl << endl; + + writeMakeQmake(t); + + t << "dist:" << "\n\t" + << "$(ZIP) " << var("PROJECT") << ".zip " << var("PROJECT") << ".pro $(SOURCES) $(HEADERS) $(DIST) $(FORMS)" + << endl << endl; + + t << "clean:\n" + << varGlue("OBJECTS","\t-del ","\n\t-del ","") + << varGlue("SRCMOC" ,"\n\t-del ","\n\t-del ","") + << varGlue("OBJMOC" ,"\n\t-del ","\n\t-del ","") + << varGlue("UICDECLS" ,"\n\t-del ","\n\t-del ","") + << varGlue("UICIMPLS" ,"\n\t-del ","\n\t-del ","") + << "\n\t-del $(TARGET)" + << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ","") + << varGlue("CLEAN_FILES","\n\t-del ","\n\t-del ",""); + if ( project->isActiveConfig("activeqt")) { + t << ("\n\t-del tmp\\" + targetfilename + ".*"); + t << "\n\t-del tmp\\dump.*"; + } + if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) + t << "\n\t-del " << var("DLLDESTDIR") << "\\" << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first(); + if(!project->isEmpty("IMAGES")) + t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-del ", "\n\t-del ", ""); + + // blasted user defined targets + QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"]; + for(QStringList::Iterator it = qut.begin(); it != qut.end(); ++it) { + QString targ = var((*it) + ".target"), + cmd = var((*it) + ".commands"), deps; + if(targ.isEmpty()) + targ = (*it); + QStringList &deplist = project->variables()[(*it) + ".depends"]; + for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { + QString dep = var((*dep_it) + ".target"); + if(dep.isEmpty()) + dep = (*dep_it); + deps += " " + dep; + } + t << "\n\n" << targ << ":" << deps << "\n\t" + << cmd; + } + + t << endl << endl; +} + +void +BorlandMakefileGenerator::init() +{ + if(init_flag) + return; + init_flag = TRUE; + + project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; + + /* this should probably not be here, but I'm using it to wrap the .t files */ + if(project->first("TEMPLATE") == "app") + project->variables()["QMAKE_APP_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "lib") + project->variables()["QMAKE_LIB_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "subdirs") { + MakefileGenerator::init(); + if(project->variables()["MAKEFILE"].isEmpty()) + project->variables()["MAKEFILE"].append("Makefile"); + if(project->variables()["QMAKE"].isEmpty()) + project->variables()["QMAKE"].append("qmake"); + return; + } + + bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qtmt"QTDLL_POSTFIX); + QStringList &configs = project->variables()["CONFIG"]; + if (project->isActiveConfig("shared")) + project->variables()["DEFINES"].append("QT_DLL"); + if (project->isActiveConfig("qt_dll")) + if(configs.findIndex("qt") == -1) configs.append("qt"); + if ( project->isActiveConfig("qt") ) { + if ( project->isActiveConfig("plugin") ) { + project->variables()["CONFIG"].append("dll"); + project->variables()["DEFINES"].append("QT_PLUGIN"); + } + if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && + ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || + project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || + (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { + project->variables()["QMAKE_QT_DLL"].append("1"); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) + project->variables()["CONFIG"].append("dll"); + } + } + if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["CONFIG"].remove("staticlib"); + project->variables()["QMAKE_APP_OR_DLL"].append("1"); + } else { + project->variables()["CONFIG"].append("staticlib"); + } + if ( project->isActiveConfig("warn_off") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; + } else if ( project->isActiveConfig("warn_on") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; + } + if(project->isActiveConfig("qt")) { + if ( project->isActiveConfig("thread") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); + if ( project->isActiveConfig("accessibility" ) ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); + if ( project->isActiveConfig("tablet") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); + } + + if ( project->isActiveConfig("debug") ) { + if ( project->isActiveConfig("thread") ) { + if ( project->isActiveConfig("dll") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; + } + } + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; + } else { + if ( project->isActiveConfig("thread") ) { + if ( project->isActiveConfig("dll") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"]; + } + } + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; + } + + if ( !project->variables()["QMAKE_INCDIR"].isEmpty()) { + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; + } + if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) { + project->variables()["CONFIG"].append("windows"); + } + if ( project->isActiveConfig("qt") ) { + project->variables()["CONFIG"].append("moc"); + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; + if ( !project->isActiveConfig("debug") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) { + project->variables()["DEFINES"].append("QT_MAKEDLL"); + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"]; + } + } else { + if(project->isActiveConfig("thread")) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); + if ( hver == -1 ) + hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); + if(hver != -1) { + QString ver; + ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "mt" : ""), hver); + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) + (*libit).replace(QRegExp("qt(mt)?\\.lib"), ver); + } + } + if ( project->isActiveConfig( "activeqt" ) ) { + project->variables().remove("QMAKE_LIBS_QT_ENTRY"); + project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; + if ( project->isActiveConfig( "dll" ) ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + } + } + if ( project->isActiveConfig("opengl") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; + } + if ( project->isActiveConfig("dll") ) { + project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"]; + if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) { + project->variables()["TARGET_EXT"].append( + QStringList::split('.',project->first("VERSION")).join("") + ".dll"); + } else { + project->variables()["TARGET_EXT"].append(".dll"); + } + } else { + project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"]; + project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"]; + project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"]; + project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"]; + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) { + project->variables()["TARGET_EXT"].append(".exe"); + } else { + project->variables()["TARGET_EXT"].append(".lib"); + } + } + if ( project->isActiveConfig("windows") ) { + if ( project->isActiveConfig("console") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; + } else { + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"]; + } + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; + } + if ( project->isActiveConfig("thread") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_RTMT"]; + } else { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_RT"]; + } + if ( project->isActiveConfig("moc") ) { + setMocAware(TRUE); + } + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', + "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); + QStringList &l = project->variables()["QMAKE_FILETAGS"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QStringList &gdmf = project->variables()[(*it)]; + for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) + (*inner) = Option::fixPathToTargetOS((*inner), FALSE); + } + + if ( !project->variables()["RC_FILE"].isEmpty()) { + if ( !project->variables()["RES_FILE"].isEmpty()) { + fprintf(stderr, "Both .rc and .res file specified.\n"); + fprintf(stderr, "Please specify one of them, not both."); + exit(666); + } + project->variables()["RES_FILE"] = project->variables()["RC_FILE"]; + project->variables()["RES_FILE"].first().replace(".rc",".res"); + project->variables()["TARGETDEPS"] += project->variables()["RES_FILE"]; + } + MakefileGenerator::init(); + if ( !project->variables()["VERSION"].isEmpty()) { + QStringList l = QStringList::split('.', project->first("VERSION")); + project->variables()["VER_MAJ"].append(l[0]); + project->variables()["VER_MIN"].append(l[1]); + } + + if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + // bcc does not generate a .tds file for static libs + QString tdsPostfix; + if ( !project->variables()["VERSION"].isEmpty() ) { + tdsPostfix = QStringList::split( '.', project->first("VERSION") ).join("") + + ".tds"; + } else { + tdsPostfix = ".tds"; + } + project->variables()["QMAKE_CLEAN"].append( + project->first("DESTDIR") + project->first("TARGET") + tdsPostfix ); + } +} + diff --git a/qmake/generators/win32/borland_bmake.h b/qmake/generators/win32/borland_bmake.h new file mode 100644 index 0000000..90f8229 --- a/dev/null +++ b/qmake/generators/win32/borland_bmake.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __BORLANDMAKE_H__ +#define __BORLANDMAKE_H__ + +#include "winmakefile.h" + +class BorlandMakefileGenerator : public Win32MakefileGenerator +{ + bool init_flag; + void writeBorlandParts(QTextStream &); + + bool writeMakefile(QTextStream &); + void init(); + +public: + BorlandMakefileGenerator(QMakeProject *p); + ~BorlandMakefileGenerator(); +}; + +inline BorlandMakefileGenerator::~BorlandMakefileGenerator() +{ } + + +#endif /* __BORLANDMAKE_H__ */ diff --git a/qmake/generators/win32/msvc_dsp.cpp b/qmake/generators/win32/msvc_dsp.cpp new file mode 100644 index 0000000..8b08c78 --- a/dev/null +++ b/qmake/generators/win32/msvc_dsp.cpp @@ -0,0 +1,955 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "msvc_dsp.h" +#include "option.h" +#include <qdir.h> +#include <qregexp.h> +#include <stdlib.h> +#include <time.h> + +DspMakefileGenerator::DspMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) +{ + +} + +bool +DspMakefileGenerator::writeMakefile(QTextStream &t) +{ + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + /* for now just dump, I need to generated an empty dsp or something.. */ + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + if(project->first("TEMPLATE") == "vcapp" || + project->first("TEMPLATE") == "vclib") { + return writeDspParts(t); + } + else if(project->first("TEMPLATE") == "subdirs") { + writeHeader(t); + writeSubDirs(t); + return TRUE; + } + return FALSE; +} + +bool +DspMakefileGenerator::writeDspParts(QTextStream &t) +{ + QString dspfile; + if ( !project->variables()["DSP_TEMPLATE"].isEmpty() ) { + dspfile = project->first("DSP_TEMPLATE"); + } else { + dspfile = project->first("MSVCDSP_TEMPLATE"); + } + QString dspfile_loc = findTemplate(dspfile); + + QFile file(dspfile_loc); + if(!file.open(IO_ReadOnly)) { + fprintf(stderr, "Cannot open dsp file: %s\n", dspfile.latin1()); + return FALSE; + } + QTextStream dsp(&file); + + int rep; + QString line; + while ( !dsp.eof() ) { + line = dsp.readLine(); + while((rep = line.find(QRegExp("\\$\\$[a-zA-Z0-9_-]*"))) != -1) { + QString torep = line.mid(rep, line.find(QRegExp("[^\\$a-zA-Z0-9_-]"), rep) - rep); + QString variable = torep.right(torep.length()-2); + + t << line.left(rep); //output the left side + line = line.right(line.length() - (rep + torep.length())); //now past the variable + if(variable == "MSVCDSP_SOURCES") { + if(project->variables()["SOURCES"].isEmpty()) + continue; + + QString mocpath = var( "QMAKE_MOC" ); + mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; + + QStringList list = project->variables()["SOURCES"] + project->variables()["DEF_FILE"]; + if(!project->isActiveConfig("flat")) + list.sort(); + QStringList::Iterator it; + for( it = list.begin(); it != list.end(); ++it) { + beginGroupForFile((*it), t); + t << "# Begin Source File\n\nSOURCE=" << (*it) << endl; + if ( project->isActiveConfig("moc") && (*it).endsWith(Option::moc_ext)) { + QString base = (*it); + base.replace(QRegExp("\\..*$"), "").upper(); + base.replace(QRegExp("[^a-zA-Z]"), "_"); + + QString build = "\n\n# Begin Custom Build - Moc'ing " + findMocSource((*it)) + + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + (*it) + "\"" + " : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n" + "\t" + mocpath + findMocSource((*it)) + " -o " + + (*it) + "\n\n" "# End Custom Build\n\n"; + + t << "USERDEP_" << base << "=\".\\" << findMocSource((*it)) << "\" \"$(QTDIR)\\bin\\moc.exe\"" << endl << endl; + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" + << build << "!ENDIF " << endl << endl; + } + t << "# End Source File" << endl; + } + endGroups(t); + } else if(variable == "MSVCDSP_IMAGES") { + if(project->variables()["IMAGES"].isEmpty()) + continue; + t << "# Begin Source File\n\nSOURCE=" << project->first("QMAKE_IMAGE_COLLECTION") << endl; + t << "# End Source File" << endl; + } else if(variable == "MSVCDSP_HEADERS") { + if(project->variables()["HEADERS"].isEmpty()) + continue; + + QStringList list = project->variables()["HEADERS"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { +// beginGroupForFile((*it), t); + t << "# Begin Source File\n\nSOURCE=" << (*it) << endl << endl; + if ( project->isActiveConfig("moc") && !findMocDestination((*it)).isEmpty()) { + QString base = (*it); + base.replace(QRegExp("\\..*$"), "").upper(); + base.replace(QRegExp("[^a-zA-Z]"), "_"); + + QString mocpath = var( "QMAKE_MOC" ); + mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; + + QString build = "\n\n# Begin Custom Build - Moc'ing " + (*it) + + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + findMocDestination((*it)) + + "\"" " : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n" + "\t" + mocpath + (*it) + " -o " + + findMocDestination((*it)) + "\n\n" "# End Custom Build\n\n"; + + t << "USERDEP_" << base << "=\"$(QTDIR)\\bin\\moc.exe\"" << endl << endl; + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" + << build << "!ENDIF " << endl << endl; + } + t << "# End Source File" << endl; + } +// endGroups(t); + } else if(variable == "MSVCDSP_FORMSOURCES" || variable == "MSVCDSP_FORMHEADERS") { + if(project->variables()["FORMS"].isEmpty()) + continue; + + QString uiSourcesDir; + QString uiHeadersDir; + if(!project->variables()["UI_DIR"].isEmpty()) { + uiSourcesDir = project->first("UI_DIR"); + uiHeadersDir = project->first("UI_DIR"); + } else { + if ( !project->variables()["UI_SOURCES_DIR"].isEmpty() ) + uiSourcesDir = project->first("UI_SOURCES_DIR"); + else + uiSourcesDir = ""; + if ( !project->variables()["UI_HEADERS_DIR"].isEmpty() ) + uiHeadersDir = project->first("UI_HEADERS_DIR"); + else + uiHeadersDir = ""; + } + + QStringList list = project->variables()["FORMS"]; + if(!project->isActiveConfig("flat")) + list.sort(); + QString ext = variable == "MSVCDSP_FORMSOURCES" ? ".cpp" : ".h"; + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString base = (*it); + int dot = base.findRev("."); + base.replace( dot, base.length() - dot, ext ); + QString fname = base; + + int lbs = fname.findRev( "\\" ); + QString fpath; + if ( lbs != -1 ) + fpath = fname.left( lbs + 1 ); + fname = fname.right( fname.length() - lbs - 1 ); + + if ( ext == ".cpp" && !uiSourcesDir.isEmpty() ) + fname.prepend(uiSourcesDir); + else if ( ext == ".h" && !uiHeadersDir.isEmpty() ) + fname.prepend(uiHeadersDir); + else + fname = base; +// beginGroupForFile(fname, t); + t << "# Begin Source File\n\nSOURCE=" << fname + << "\n# End Source File" << endl; + } +// endGroups(t); + } else if(variable == "MSVCDSP_TRANSLATIONS" ) { + if(project->variables()["TRANSLATIONS"].isEmpty()) + continue; + + t << "# Begin Group \"Translations\"\n"; + t << "# Prop Default_Filter \"ts\"\n"; + + QStringList list = project->variables()["TRANSLATIONS"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString sify = *it; + sify.replace('/', '\\' ); + QString base = (*it); + base.replace(QRegExp("\\..*$"), "").upper(); + base.replace(QRegExp("[^a-zA-Z]"), "_"); + +// beginGroupForFile(sify, t); + t << "# Begin Source File\n\nSOURCE=" << sify << endl; + t << "\n# End Source File" << endl; + } +// endGroups(t); + t << "\n# End Group\n"; + } else if (variable == "MSVCDSP_MOCSOURCES" && project->isActiveConfig("moc")) { + if ( project->variables()["SRCMOC"].isEmpty()) + continue; + + QString mocpath = var( "QMAKE_MOC" ); + mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; + + QStringList list = project->variables()["SRCMOC"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { +// beginGroupForFile((*it), t); + t << "# Begin Source File\n\nSOURCE=" << (*it) << endl; + if ( project->isActiveConfig("moc") && (*it).endsWith(Option::moc_ext)) { + QString base = (*it); + base.replace(QRegExp("\\..*$"), "").upper(); + base.replace(QRegExp("[^a-zA-Z]"), "_"); + + QString build = "\n\n# Begin Custom Build - Moc'ing " + findMocSource((*it)) + + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + (*it) + "\"" + " : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n" + "\t" + mocpath + findMocSource((*it)) + " -o " + + (*it) + "\n\n" "# End Custom Build\n\n"; + + t << "USERDEP_" << base << "=\".\\" << findMocSource((*it)) << "\" \"$(QTDIR)\\bin\\moc.exe\"" << endl << endl; + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" + << build << "!ENDIF " << endl << endl; + } + t << "# End Source File" << endl; + } +// endGroups(t); + } else if(variable == "MSVCDSP_PICTURES") { + if(project->variables()["IMAGES"].isEmpty()) + continue; + + t << "# Begin Group \"Images\"\n" + << "# Prop Default_Filter \"png jpeg bmp xpm\"\n"; + + QStringList list = project->variables()["IMAGES"]; + if(!project->isActiveConfig("flat")) + list.sort(); + QStringList::Iterator it; + + // dump the image list to a file UIC can read. + QFile f( "images.tmp" ); + f.open( IO_WriteOnly ); + QTextStream ts( &f ); + for( it = list.begin(); it != list.end(); ++it ) + ts << " " << *it; + f.close(); + + // create an output step for images not more than once + bool imagesBuildDone = FALSE; + for( it = list.begin(); it != list.end(); ++it ) { +// beginGroupForFile((*it), t); + t << "# Begin Source File\n\nSOURCE=" << (*it) << endl; + + QString base = (*it); + QString uicpath = var("QMAKE_UIC"); + uicpath = uicpath.replace(QRegExp("\\..*$"), "") + " "; + + if ( !imagesBuildDone ) { + imagesBuildDone = TRUE; + QString build = "\n\n# Begin Custom Build - Creating image collection...\n" + "InputPath=.\\" + base + "\n\n"; + + build += "\"" + project->first("QMAKE_IMAGE_COLLECTION") + "\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n"; + build += "\t" + uicpath + "-embed " + project->first("QMAKE_ORIG_TARGET") + " -f images.tmp -o " + + project->first("QMAKE_IMAGE_COLLECTION") + "\n\n"; + build.append("# End Custom Build\n\n"); + + t << "USERDEP_" << base << "="; + QStringList::Iterator it2 = list.begin(); + while ( it2 != list.end() ) { + t << "\"" << (*it2) << "\""; + it2++; + if ( it2 != list.end() ) + t << "\\\n"; + } + t << endl << endl; + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build + << "!ENDIF \n\n" << endl; + } + + t << "# End Source File" << endl; + } +// endGroups(t); + t << "\n# End Group\n"; + } else if(variable == "MSVCDSP_FORMS") { + if(project->variables()["FORMS"].isEmpty()) + continue; + + t << "# Begin Group \"Forms\"\n" + << "# Prop Default_Filter \"ui\"\n"; + + QString uicpath = var("QMAKE_UIC"); + uicpath = uicpath.replace(QRegExp("\\..*$"), "") + " "; + QString mocpath = var( "QMAKE_MOC" ); + mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; + + QStringList list = project->variables()["FORMS"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString base = (*it); +// beginGroupForFile(base, t); + t << "# Begin Source File\n\nSOURCE=" << base << endl; + + QString fname = base; + fname.replace(".ui", ""); + int lbs = fname.findRev( "\\" ); + QString fpath; + if ( lbs != -1 ) + fpath = fname.left( lbs + 1 ); + fname = fname.right( fname.length() - lbs - 1 ); + + QString mocFile; + if(!project->variables()["MOC_DIR"].isEmpty()) + mocFile = project->first("MOC_DIR"); + else + mocFile = fpath; + + QString uiSourcesDir; + QString uiHeadersDir; + if(!project->variables()["UI_DIR"].isEmpty()) { + uiSourcesDir = project->first("UI_DIR"); + uiHeadersDir = project->first("UI_DIR"); + } else { + if ( !project->variables()["UI_SOURCES_DIR"].isEmpty() ) + uiSourcesDir = project->first("UI_SOURCES_DIR"); + else + uiSourcesDir = fpath; + if ( !project->variables()["UI_HEADERS_DIR"].isEmpty() ) + uiHeadersDir = project->first("UI_HEADERS_DIR"); + else + uiHeadersDir = fpath; + } + + t << "USERDEP_" << base << "=\"$(QTDIR)\\bin\\moc.exe\" \"$(QTDIR)\\bin\\uic.exe\"" << endl << endl; + + QString build = "\n\n# Begin Custom Build - Uic'ing " + base + "...\n" + "InputPath=.\\" + base + "\n\n" "BuildCmds= \\\n\t" + uicpath + base + + " -o " + uiHeadersDir + fname + ".h \\\n" "\t" + uicpath + base + + " -i " + fname + ".h -o " + uiSourcesDir + fname + ".cpp \\\n" + "\t" + mocpath + uiHeadersDir + fname + ".h -o " + mocFile + "moc_" + fname + ".cpp \\\n"; + + build.append("\n\"" + uiHeadersDir + fname + ".h\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" + "\t$(BuildCmds)\n\n" + "\"" + uiSourcesDir + fname + ".cpp\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" + "\t$(BuildCmds)\n\n" + "\"" + mocFile + "moc_" + fname + ".cpp\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" + "\t$(BuildCmds)\n\n"); + + build.append("# End Custom Build\n\n"); + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build + << "!ENDIF \n\n" << "# End Source File" << endl; + } +// endGroups(t); + t << "\n# End Group\n"; + } else if(variable == "MSVCDSP_LEXSOURCES") { + if(project->variables()["LEXSOURCES"].isEmpty()) + continue; + + t << "# Begin Group \"Lexables\"\n" + << "# Prop Default_Filter \"l\"\n"; + + QString lexpath = var("QMAKE_LEX") + varGlue("QMAKE_LEXFLAGS", " ", " ", "") + " "; + + QStringList list = project->variables()["LEXSOURCES"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString fname = (*it); +// beginGroupForFile(fname, t); + t << "# Begin Source File\n\nSOURCE=" << fname << endl; + fname.replace(".l", Option::lex_mod + Option::cpp_ext.first()); + + QString build = "\n\n# Begin Custom Build - Lex'ing " + (*it) + "...\n" + "InputPath=.\\" + (*it) + "\n\n" + "\"" + fname + "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" + "\t" + lexpath + (*it) + "\\\n" + "\tdel " + fname + "\\\n" + "\tcopy lex.yy.c " + fname + "\n\n" + + "# End Custom Build\n\n"; + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build + << "!ENDIF \n\n" << build + + << "# End Source File" << endl; + } +// endGroups(t); + t << "\n# End Group\n"; + } else if(variable == "MSVCDSP_YACCSOURCES") { + if(project->variables()["YACCSOURCES"].isEmpty()) + continue; + + t << "# Begin Group \"Yaccables\"\n" + << "# Prop Default_Filter \"y\"\n"; + + QString yaccpath = var("QMAKE_YACC") + varGlue("QMAKE_YACCFLAGS", " ", " ", "") + " "; + + QStringList list = project->variables()["YACCSOURCES"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + QString fname = (*it); +// beginGroupForFile(fname, t); + t << "# Begin Source File\n\nSOURCE=" << fname << endl; + fname.replace(".y", Option::yacc_mod); + + QString build = "\n\n# Begin Custom Build - Yacc'ing " + (*it) + "...\n" + "InputPath=.\\" + (*it) + "\n\n" + "\"" + fname + Option::cpp_ext.first() + "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" + "\t" + yaccpath + (*it) + "\\\n" + "\tdel " + fname + Option::h_ext.first() + "\\\n" + "\tmove y.tab.h " + fname + Option::h_ext.first() + "\n\n" + + "\tdel " + fname + Option::cpp_ext.first() + "\\\n" + "\tmove y.tab.c " + fname + Option::cpp_ext.first() + "\n\n" + + "# End Custom Build\n\n"; + + t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build + << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build + << "!ENDIF \n\n" + << "# End Source File" << endl; + } +// endGroups(t); + t << "\n# End Group\n"; + } else if( variable == "MSVCDSP_CONFIGMODE" ) { + if( project->isActiveConfig( "debug" ) ) + t << "Debug"; + else + t << "Release"; + } else if( variable == "MSVCDSP_IDLSOURCES" ) { + QStringList list = project->variables()["MSVCDSP_IDLSOURCES"]; + if(!project->isActiveConfig("flat")) + list.sort(); + for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { + t << "# Begin Source File" << endl << endl; + t << "SOURCE=" << (*it) << endl; + t << "# PROP Exclude_From_Build 1" << endl; + t << "# End Source File" << endl << endl; + } + } + else + t << var(variable); + } + t << line << endl; + } + t << endl; + file.close(); + return TRUE; +} + + + +void +DspMakefileGenerator::init() +{ + if(init_flag) + return; + QStringList::Iterator it; + init_flag = TRUE; + + /* this should probably not be here, but I'm using it to wrap the .t files */ + if(project->first("TEMPLATE") == "vcapp" ) + project->variables()["QMAKE_APP_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "vclib") + project->variables()["QMAKE_LIB_FLAG"].append("1"); + if ( project->variables()["QMAKESPEC"].isEmpty() ) + project->variables()["QMAKESPEC"].append( getenv("QMAKESPEC") ); + + bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX); + project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; + + QStringList &configs = project->variables()["CONFIG"]; + if (project->isActiveConfig("shared")) + project->variables()["DEFINES"].append("QT_DLL"); + if (project->isActiveConfig("qt_dll")) + if(configs.findIndex("qt") == -1) configs.append("qt"); + if ( project->isActiveConfig("qt") ) { + if ( project->isActiveConfig( "plugin" ) ) { + project->variables()["CONFIG"].append("dll"); + project->variables()["DEFINES"].append("QT_PLUGIN"); + } + if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && + ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || + project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || + (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { + project->variables()["QMAKE_QT_DLL"].append("1"); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) + project->variables()["CONFIG"].append("dll"); + } + } + if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["CONFIG"].remove("staticlib"); + project->variables()["QMAKE_APP_OR_DLL"].append("1"); + } else { + project->variables()["CONFIG"].append("staticlib"); + } + + if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) { + project->variables()["CONFIG"].append("windows"); + } + if ( !project->variables()["VERSION"].isEmpty() ) { + QString version = project->variables()["VERSION"][0]; + int firstDot = version.find( "." ); + QString major = version.left( firstDot ); + QString minor = version.right( version.length() - firstDot - 1 ); + minor.replace( ".", "" ); + project->variables()["MSVCDSP_VERSION"].append( "/VERSION:" + major + "." + minor ); + } + + if ( project->isActiveConfig("qt") ) { + project->variables()["CONFIG"].append("moc"); + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; + + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + project->variables()["DEFINES"].append("QT_MAKEDLL"); + project->variables()["QMAKE_LFLAGS"].append("/base:\"0x39D00000\""); + } + } else { + if(project->isActiveConfig("thread")) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); + if ( hver == -1 ) + hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); + if(hver != -1) { + QString ver; + ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) + (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); + } + } + if ( project->isActiveConfig( "activeqt" ) ) { + project->variables().remove("QMAKE_LIBS_QT_ENTRY"); + project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; + if ( project->isActiveConfig( "dll" ) ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { + project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + } + } + + if ( project->isActiveConfig("debug") ) { + if ( !project->first("OBJECTS_DIR").isEmpty() ) + project->variables()["MSVCDSP_OBJECTSDIRDEB"] = project->first("OBJECTS_DIR"); + else + project->variables()["MSVCDSP_OBJECTSDIRDEB"] = "Debug"; + project->variables()["MSVCDSP_OBJECTSDIRREL"] = "Release"; + if ( !project->first("DESTDIR").isEmpty() ) + project->variables()["MSVCDSP_TARGETDIRDEB"] = project->first("DESTDIR"); + else + project->variables()["MSVCDSP_TARGETDIRDEB"] = "Debug"; + project->variables()["MSVCDSP_TARGETDIRREL"] = "Release"; + } else { + if ( !project->first("OBJECTS_DIR").isEmpty() ) + project->variables()["MSVCDSP_OBJECTSDIRREL"] = project->first("OBJECTS_DIR"); + project->variables()["MSVCDSP_OBJECTSDIRDEB"] = "Debug"; + if ( !project->first("DESTDIR").isEmpty() ) + project->variables()["MSVCDSP_TARGETDIRREL"] = project->first("DESTDIR"); + else + project->variables()["MSVCDSP_TARGETDIRREL"] = "Release"; + project->variables()["MSVCDSP_TARGETDIRDEB"] = "Debug"; + } + + if ( project->isActiveConfig("opengl") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; + } + if ( project->isActiveConfig("thread") ) { + if(project->isActiveConfig("qt")) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT" ); + if ( project->isActiveConfig("dll") || project->first("TARGET") == "qtmain" + || !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + project->variables()["MSVCDSP_MTDEFD"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; + project->variables()["MSVCDSP_MTDEF"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; + } else { + // YES we want to use the DLL even in a static build + project->variables()["MSVCDSP_MTDEFD"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; + project->variables()["MSVCDSP_MTDEF"] += project->variables()["QMAKE_CXXFLAGS_MT"]; + } + if ( !project->variables()["DEFINES"].contains("QT_DLL") && is_qt + && project->first("TARGET") != "qtmain" ) + project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:\"libc\""); + } + + if(project->isActiveConfig("qt")) { + if ( project->isActiveConfig("accessibility" ) ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); + if ( project->isActiveConfig("tablet") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); + } + if ( project->isActiveConfig("dll") ) { + if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + QString ver_xyz(project->first("VERSION")); + ver_xyz.replace(".", ""); + project->variables()["TARGET_EXT"].append(ver_xyz + ".dll"); + } else { + project->variables()["TARGET_EXT"].append(".dll"); + } + } else { + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) + project->variables()["TARGET_EXT"].append(".exe"); + else + project->variables()["TARGET_EXT"].append(".lib"); + } + + project->variables()["MSVCDSP_VER"] = "6.00"; + project->variables()["MSVCDSP_DEBUG_OPT"] = "/GZ /ZI"; + + if(!project->isActiveConfig("incremental")) { + project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); + if ( is_qt ) + project->variables()["MSVCDSP_DEBUG_OPT"] = "/GZ /Zi"; + } + + QString msvcdsp_project; + if ( project->variables()["TARGET"].count() ) + msvcdsp_project = project->variables()["TARGET"].first(); + + QString targetfilename = project->variables()["TARGET"].first(); + project->variables()["TARGET"].first() += project->first("TARGET_EXT"); + if ( project->isActiveConfig("moc") ) + setMocAware(TRUE); + + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', + "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); + QStringList &l = project->variables()["QMAKE_FILETAGS"]; + for(it = l.begin(); it != l.end(); ++it) { + QStringList &gdmf = project->variables()[(*it)]; + for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) + (*inner) = Option::fixPathToTargetOS((*inner), FALSE); + } + + MakefileGenerator::init(); + if ( msvcdsp_project.isEmpty() ) + msvcdsp_project = Option::output.name(); + + msvcdsp_project = msvcdsp_project.right( msvcdsp_project.length() - msvcdsp_project.findRev( "\\" ) - 1 ); + msvcdsp_project = msvcdsp_project.left( msvcdsp_project.findRev( "." ) ); + msvcdsp_project.replace("-", ""); + + project->variables()["MSVCDSP_PROJECT"].append(msvcdsp_project); + QStringList &proj = project->variables()["MSVCDSP_PROJECT"]; + + for(it = proj.begin(); it != proj.end(); ++it) + (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); + + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["MSVCDSP_TEMPLATE"].append("win32app" + project->first( "DSP_EXTENSION" ) ); + if ( project->isActiveConfig("console") ) { + project->variables()["MSVCDSP_CONSOLE"].append("Console"); + project->variables()["MSVCDSP_WINCONDEF"].append("_CONSOLE"); + project->variables()["MSVCDSP_DSPTYPE"].append("0x0103"); + project->variables()["MSVCDSP_SUBSYSTEM"].append("console"); + } else { + project->variables()["MSVCDSP_CONSOLE"].clear(); + project->variables()["MSVCDSP_WINCONDEF"].append("_WINDOWS"); + project->variables()["MSVCDSP_DSPTYPE"].append("0x0101"); + project->variables()["MSVCDSP_SUBSYSTEM"].append("windows"); + } + } else { + if ( project->isActiveConfig("dll") ) { + project->variables()["MSVCDSP_TEMPLATE"].append("win32dll" + project->first( "DSP_EXTENSION" ) ); + } else { + project->variables()["MSVCDSP_TEMPLATE"].append("win32lib" + project->first( "DSP_EXTENSION" ) ); + } + } + + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; + + project->variables()["MSVCDSP_LFLAGS" ] += project->variables()["QMAKE_LFLAGS"]; + if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) + project->variables()["MSVCDSP_LFLAGS" ].append(varGlue("QMAKE_LIBDIR","/LIBPATH:\"","\" /LIBPATH:\"","\"")); + project->variables()["MSVCDSP_CXXFLAGS" ] += project->variables()["QMAKE_CXXFLAGS"]; + project->variables()["MSVCDSP_DEFINES"].append(varGlue("DEFINES","/D ","" " /D ","")); + project->variables()["MSVCDSP_DEFINES"].append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ","")); + + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) { + QString lib = (*libit); + lib.replace(QRegExp("\""), ""); + project->variables()["MSVCDSP_LIBS"].append(" \"" + lib + "\""); + } + + QStringList &incs = project->variables()["INCLUDEPATH"]; + for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { + QString inc = (*incit); + inc.replace("\"", ""); + project->variables()["MSVCDSP_INCPATH"].append("/I \"" + inc + "\""); + } + + project->variables()["MSVCDSP_INCPATH"].append("/I \"" + specdir() + "\""); + if ( project->isActiveConfig("qt") ) { + project->variables()["MSVCDSP_RELDEFS"].append("/D \"QT_NO_DEBUG\""); + } else { + project->variables()["MSVCDSP_RELDEFS"].clear(); + } + + QString dest; + if ( !project->variables()["DESTDIR"].isEmpty() ) { + project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); + Option::fixPathToTargetOS(project->first("TARGET")); + dest = project->first("TARGET"); + if ( project->first("TARGET").startsWith("$(QTDIR)") ) + dest.replace( "$(QTDIR)", getenv("QTDIR") ); + project->variables()["MSVCDSP_TARGET"].append( + QString("/out:\"") + dest + "\""); + if ( project->isActiveConfig("dll") ) { + QString imp = dest; + imp.replace(".dll", ".lib"); + project->variables()["MSVCDSP_TARGET"].append(QString(" /implib:\"") + imp + "\""); + } + } + if ( project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty() ) { + QStringList dlldirs = project->variables()["DLLDESTDIR"]; + QString copydll = "# Begin Special Build Tool\n" + "TargetPath=" + dest + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Copy DLL to " + project->first("DLLDESTDIR") + "\n" + "PostBuild_Cmds="; + + for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { + copydll += "copy \"" + dest + "\" \"" + *dlldir + "\"\t"; + } + + copydll += "\n# End Special Build Tool"; + project->variables()["MSVCDSP_COPY_DLL_REL"].append( copydll ); + project->variables()["MSVCDSP_COPY_DLL_DBG"].append( copydll ); + } + if ( project->isActiveConfig("activeqt") ) { + QString idl = project->variables()["QMAKE_IDL"].first(); + QString idc = project->variables()["QMAKE_IDC"].first(); + QString version = project->variables()["VERSION"].first(); + if ( version.isEmpty() ) + version = "1.0"; + + project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".idl" ); + project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".tlb" ); + project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".midl" ); + if ( project->isActiveConfig( "dll" ) ) { + QString regcmd = "# Begin Special Build Tool\n" + "TargetPath=" + targetfilename + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Finalizing ActiveQt server...\n" + "PostBuild_Cmds=" + + idc + " %1 -idl tmp\\" + targetfilename + ".idl -version " + version + + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" + "\t" + idc + " %1 /regserver\n" + "# End Special Build Tool"; + + QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCDSP_COPY_DLL_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + + executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCDSP_COPY_DLL_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + } else { + QString regcmd = "# Begin Special Build Tool\n" + "TargetPath=" + targetfilename + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Finalizing ActiveQt server...\n" + "PostBuild_Cmds=" + "%1 -dumpidl tmp\\" + targetfilename + ".idl -version " + version + + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" + "\t%1 -regserver\n" + "# End Special Build Tool"; + + QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCDSP_REGSVR_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + + executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCDSP_REGSVR_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + } + + } + if ( !project->variables()["SOURCES"].isEmpty() || !project->variables()["RC_FILE"].isEmpty() ) { + project->variables()["SOURCES"] += project->variables()["RC_FILE"]; + } + QStringList &list = project->variables()["FORMS"]; + for( it = list.begin(); it != list.end(); ++it ) { + if ( QFile::exists( *it + ".h" ) ) + project->variables()["SOURCES"].append( *it + ".h" ); + } + project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "MSVCDSP_LIBS"; +} + + +QString +DspMakefileGenerator::findTemplate(QString file) +{ + QString ret; + if(!QFile::exists((ret = file)) && + !QFile::exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) && + !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/win32-msvc/" + file)) && + !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) + return ""; + return ret; +} + + +void +DspMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) +{ + if(var == "QMAKE_PRL_DEFINES") { + QStringList &out = project->variables()["MSVCDSP_DEFINES"]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if(out.findIndex((*it)) == -1) + out.append((" /D \"" + *it + "\"")); + } + } else { + MakefileGenerator::processPrlVariable(var, l); + } +} + + +int +DspMakefileGenerator::beginGroupForFile(QString file, QTextStream &t, + QString filter) +{ + if(project->isActiveConfig("flat")) + return 0; + + fileFixify(file, QDir::currentDirPath(), QDir::currentDirPath(), TRUE); + file = file.section(Option::dir_sep, 0, -2); + if(file.right(Option::dir_sep.length()) != Option::dir_sep) + file += Option::dir_sep; + if(file == currentGroup) + return 0; + + if(file.isEmpty() || !QDir::isRelativePath(file)) { + endGroups(t); + return 0; + } + if(file.startsWith(currentGroup)) + file = file.mid(currentGroup.length()); + else + endGroups(t); + int lvl = file.contains(Option::dir_sep), old_lvl = currentGroup.contains(Option::dir_sep); + if(lvl > old_lvl) { + QStringList dirs = QStringList::split(Option::dir_sep, file); + for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { + t << "# Begin Group \"" << (*dir_it) << "\"\n" + << "# Prop Default_Filter \"" << filter << "\"\n"; + } + } else { + for(int x = old_lvl - lvl; x; x--) + t << "\n# End Group\n"; + } + currentGroup = file; + return lvl - old_lvl; +} + + +int +DspMakefileGenerator::endGroups(QTextStream &t) +{ + if(project->isActiveConfig("flat")) + return 0; + else if(currentGroup.isEmpty()) + return 0; + + QStringList dirs = QStringList::split(Option::dir_sep, currentGroup); + for(QStringList::Iterator dir_it = dirs.end(); dir_it != dirs.begin(); --dir_it) { + t << "\n# End Group\n"; + } + currentGroup = ""; + return dirs.count(); +} + +bool +DspMakefileGenerator::openOutput(QFile &file) const +{ + QString outdir; + if(!file.name().isEmpty()) { + QFileInfo fi(file); + if(fi.isDir()) + outdir = file.name() + QDir::separator(); + } + if(!outdir.isEmpty() || file.name().isEmpty()) + file.setName(outdir + project->first("TARGET") + project->first("DSP_EXTENSION")); + if(QDir::isRelativePath(file.name())) { + QString ofile; + ofile = file.name(); + int slashfind = ofile.findRev('\\'); + if (slashfind == -1) { + ofile = ofile.replace(QRegExp("-"), "_"); + } else { + int hypenfind = ofile.find('-', slashfind); + while (hypenfind != -1 && slashfind < hypenfind) { + ofile = ofile.replace(hypenfind, 1, "_"); + hypenfind = ofile.find('-', hypenfind + 1); + } + } + file.setName(Option::fixPathToLocalOS(QDir::currentDirPath() + Option::dir_sep + ofile)); + } + return Win32MakefileGenerator::openOutput(file); +} diff --git a/qmake/generators/win32/msvc_dsp.h b/qmake/generators/win32/msvc_dsp.h new file mode 100644 index 0000000..a7fc3e7 --- a/dev/null +++ b/qmake/generators/win32/msvc_dsp.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __DSPMAKE_H__ +#define __DSPMAKE_H__ + +#include "winmakefile.h" +#include <qvaluestack.h> + +class DspMakefileGenerator : public Win32MakefileGenerator +{ + QString currentGroup; + int beginGroupForFile(QString file, QTextStream &, const QString filter=""); + int endGroups(QTextStream &); + + bool init_flag; + bool writeDspParts(QTextStream &); + + bool writeMakefile(QTextStream &); + QString findTemplate(QString file); + void init(); + +public: + DspMakefileGenerator(QMakeProject *p); + ~DspMakefileGenerator(); + + bool openOutput(QFile &file) const; + +protected: + virtual void processPrlVariable(const QString &, const QStringList &); + virtual bool findLibraries(); +}; + +inline DspMakefileGenerator::~DspMakefileGenerator() +{ } + +inline bool DspMakefileGenerator::findLibraries() +{ return Win32MakefileGenerator::findLibraries("MSVCDSP_LIBS"); } + +#endif /* __DSPMAKE_H__ */ diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp new file mode 100644 index 0000000..9cc9a69 --- a/dev/null +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -0,0 +1,488 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "msvc_nmake.h" +#include "option.h" +#include <qregexp.h> +#include <qdir.h> +#include <stdlib.h> +#include <time.h> + + +NmakeMakefileGenerator::NmakeMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) +{ + +} + +bool +NmakeMakefileGenerator::writeMakefile(QTextStream &t) +{ + writeHeader(t); + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + t << "all clean:" << "\n\t" + << "@echo \"Some of the required modules (" + << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" + << "@echo \"Skipped.\"" << endl << endl; + writeMakeQmake(t); + return TRUE; + } + + if(project->first("TEMPLATE") == "app" || + project->first("TEMPLATE") == "lib") { + writeNmakeParts(t); + return MakefileGenerator::writeMakefile(t); + } + else if(project->first("TEMPLATE") == "subdirs") { + writeSubDirs(t); + return TRUE; + } + return FALSE; +} + +void +NmakeMakefileGenerator::writeNmakeParts(QTextStream &t) +{ + t << "####### Compiler, tools and options" << endl << endl; + t << "CC = " << var("QMAKE_CC") << endl; + t << "CXX = " << var("QMAKE_CXX") << endl; + t << "LEX = " << var("QMAKE_LEX") << endl; + t << "YACC = " << var("QMAKE_YACC") << endl; + t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " " + << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " + << varGlue("DEFINES","-D"," -D","") << endl; + t << "LEXFLAGS =" << var("QMAKE_LEXFLAGS") << endl; + t << "YACCFLAGS =" << var("QMAKE_YACCFLAGS") << endl; + + t << "INCPATH = "; + QStringList &incs = project->variables()["INCLUDEPATH"]; + for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { + QString inc = (*incit); + inc.replace(QRegExp("\\\\$"), "\\\\"); + inc.replace("\"", ""); + t << " -I\"" << inc << "\""; + } + t << " -I\"" << specdir() << "\"" + << endl; + if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { + t << "LINK = " << var("QMAKE_LINK") << endl; + t << "LFLAGS = " << var("QMAKE_LFLAGS"); + if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) + t << " " << varGlue("QMAKE_LIBDIR","/LIBPATH:\"","\" /LIBPATH:\"","\""); + t << endl; + t << "LIBS = "; + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) { + QString lib = (*libit); + lib.replace(QRegExp("\\\\$"), "\\\\"); + lib.replace(QRegExp("\""), ""); + t << " \"" << lib << "\""; + } + t << endl; + } + else { + t << "LIB = " << var("QMAKE_LIB") << endl; + } + t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") : + Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl; + t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") : + Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl; + t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : + Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl; + t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : + Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl; + t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : + Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl; + t << "ZIP = " << var("QMAKE_ZIP") << endl; + t << "COPY_FILE = " << var("QMAKE_COPY") << endl; + t << "COPY_DIR = " << var("QMAKE_COPY") << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; + t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << endl; + + t << "####### Files" << endl << endl; + t << "HEADERS = " << varList("HEADERS") << endl; + t << "SOURCES = " << varList("SOURCES") << endl; + t << "OBJECTS = " << varList("OBJECTS") << endl; + t << "FORMS = " << varList("FORMS") << endl; + t << "UICDECLS = " << varList("UICDECLS") << endl; + t << "UICIMPLS = " << varList("UICIMPLS") << endl; + t << "SRCMOC = " << varList("SRCMOC") << endl; + t << "OBJMOC = " << varList("OBJMOC") << endl; + t << "DIST = " << varList("DISTFILES") << endl; + t << "TARGET = "; + if( !project->variables()[ "DESTDIR" ].isEmpty() ) + t << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT")); + else + t << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first(); + t << endl; + t << endl; + + t << "####### Implicit rules" << endl << endl; + t << ".SUFFIXES: .cpp .cxx .cc .c" << endl << endl; + t << ".cpp.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".cxx.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".cc.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".c.obj:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + + t << "####### Build rules" << endl << endl; + t << "all: " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" << endl << endl; + t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS"); + if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { + t << "\n\t" << "$(LINK) $(LFLAGS) /OUT:$(TARGET) @<< " << "\n\t " + << "$(OBJECTS) $(OBJMOC) $(LIBS)"; + } else { + t << "\n\t" << "$(LIB) /OUT:$(TARGET) @<<" << "\n\t " + << "$(OBJECTS) $(OBJMOC)"; + } + t << endl << "<<" << endl; + if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) { + QStringList dlldirs = project->variables()["DLLDESTDIR"]; + for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { + t << "\n\t" << "-copy $(TARGET) " << *dlldir; + } + } + QString targetfilename = project->variables()["TARGET"].first(); + if(project->isActiveConfig("activeqt")) { + QString version = project->variables()["VERSION"].first(); + if ( version.isEmpty() ) + version = "1.0"; + + if ( project->isActiveConfig("dll")) { + t << "\n\t" << ("-$(IDC) $(TARGET) /idl tmp\\" + targetfilename + ".idl -version " + version); + t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); + t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); + t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" ); + } else { + t << "\n\t" << ("-$(TARGET) -dumpidl tmp\\" + targetfilename + ".idl -version " + version); + t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); + t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); + t << "\n\t" << "-$(TARGET) -regserver"; + } + } + t << endl << endl; + + if(!project->variables()["RC_FILE"].isEmpty()) { + t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t" + << var("QMAKE_RC") << " " << var("RC_FILE") << endl << endl; + } + + t << "mocables: $(SRCMOC)" << endl << endl; + + writeMakeQmake(t); + + t << "dist:" << "\n\t" + << "$(ZIP) " << var("PROJECT") << ".zip " + << var("PROJECT") << ".pro $(SOURCES) $(HEADERS) $(DIST) $(FORMS)" << endl << endl; + + t << "clean:" + << varGlue("OBJECTS","\n\t-del ","\n\t-del ","") + << varGlue("SRCMOC" ,"\n\t-del ","\n\t-del ","") + << varGlue("OBJMOC" ,"\n\t-del ","\n\t-del ","") + << varGlue("UICDECLS" ,"\n\t-del ","\n\t-del ","") + << varGlue("UICIMPLS" ,"\n\t-del ","\n\t-del ","") + << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ","") + << varGlue("CLEAN_FILES","\n\t-del ","\n\t-del ",""); + if ( project->isActiveConfig("activeqt")) { + t << ("\n\t-del tmp\\" + targetfilename + ".*"); + t << "\n\t-del tmp\\dump.*"; + } + if(!project->isEmpty("IMAGES")) + t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-del ", "\n\t-del ", ""); + + // blasted user defined targets + QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"]; + for(QStringList::Iterator it = qut.begin(); it != qut.end(); ++it) { + QString targ = var((*it) + ".target"), + cmd = var((*it) + ".commands"), deps; + if(targ.isEmpty()) + targ = (*it); + QStringList &deplist = project->variables()[(*it) + ".depends"]; + for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { + QString dep = var((*dep_it) + ".target"); + if(dep.isEmpty()) + dep = (*dep_it); + deps += " " + dep; + } + t << "\n\n" << targ << ":" << deps << "\n\t" + << cmd; + } + + t << endl << endl; +} + + +void +NmakeMakefileGenerator::init() +{ + if(init_flag) + return; + init_flag = TRUE; + + /* this should probably not be here, but I'm using it to wrap the .t files */ + if(project->first("TEMPLATE") == "app") + project->variables()["QMAKE_APP_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "lib") + project->variables()["QMAKE_LIB_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "subdirs") { + MakefileGenerator::init(); + if(project->variables()["MAKEFILE"].isEmpty()) + project->variables()["MAKEFILE"].append("Makefile"); + if(project->variables()["QMAKE"].isEmpty()) + project->variables()["QMAKE"].append("qmake"); + return; + } + + bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX); + project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; + + QString targetfilename = project->variables()["TARGET"].first(); + QStringList &configs = project->variables()["CONFIG"]; + if (project->isActiveConfig("qt") && project->isActiveConfig("shared")) + project->variables()["DEFINES"].append("QT_DLL"); + if (project->isActiveConfig("qt_dll")) + if(configs.findIndex("qt") == -1) configs.append("qt"); + if ( project->isActiveConfig("qt") ) { + if ( project->isActiveConfig( "plugin" ) ) { + project->variables()["CONFIG"].append("dll"); + if(project->isActiveConfig("qt")) + project->variables()["DEFINES"].append("QT_PLUGIN"); + } + if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && + ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || + project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || + (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { + project->variables()["QMAKE_QT_DLL"].append("1"); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) + project->variables()["CONFIG"].append("dll"); + } + if ( project->isActiveConfig("thread") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); + if ( project->isActiveConfig("accessibility" ) ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); + if ( project->isActiveConfig("tablet") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); + } + if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["CONFIG"].remove("staticlib"); + project->variables()["QMAKE_APP_OR_DLL"].append("1"); + } else { + project->variables()["CONFIG"].append("staticlib"); + } + if ( project->isActiveConfig("warn_off") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; + } else if ( project->isActiveConfig("warn_on") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; + } + if ( project->isActiveConfig("debug") ) { + if ( project->isActiveConfig("thread") ) { + // use the DLL RT even here + if ( project->variables()["DEFINES"].contains("QT_DLL") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; + } + } + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; + } else { + if ( project->isActiveConfig("thread") ) { + if ( project->variables()["DEFINES"].contains("QT_DLL") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"]; + } + } + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; + } + if ( project->isActiveConfig("thread") && !project->variables()["DEFINES"].contains("QT_DLL") + && !is_qt && project->first("TARGET") != "qtmain") { + project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:\"libc\""); + } + + if ( !project->variables()["QMAKE_INCDIR"].isEmpty()) + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; + if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) + project->variables()["CONFIG"].append("windows"); + if ( project->isActiveConfig("qt") ) { + project->variables()["CONFIG"].append("moc"); + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; + if ( !project->isActiveConfig("debug") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) { + project->variables()["DEFINES"].append("QT_MAKEDLL"); + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"]; + } + } else { + if(project->isActiveConfig("thread")) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); + if ( hver == -1 ) + hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); + if(hver != -1) { + QString ver; + ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) + (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); + } + } + if ( project->isActiveConfig( "activeqt" ) ) { + project->variables().remove("QMAKE_LIBS_QT_ENTRY"); + project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; + if ( project->isActiveConfig( "dll" ) ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { + project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + } + } + if ( project->isActiveConfig("opengl") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; + } + if ( project->isActiveConfig("dll") ) { + project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"]; + project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"]; + if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) { + project->variables()["TARGET_EXT"].append( + QStringList::split('.',project->first("VERSION")).join("") + ".dll"); + } else { + project->variables()["TARGET_EXT"].append(".dll"); + } + } else { + project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"]; + project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"]; + project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"]; + project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"]; + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) { + project->variables()["TARGET_EXT"].append(".exe"); + } else { + project->variables()["TARGET_EXT"].append(".lib"); + } + } + if ( project->isActiveConfig("windows") ) { + if ( project->isActiveConfig("console") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; + } else { + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"]; + } + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; + } + + if ( project->isActiveConfig("moc") ) + setMocAware(TRUE); + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', + "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); + QStringList &l = project->variables()["QMAKE_FILETAGS"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QStringList &gdmf = project->variables()[(*it)]; + for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) + (*inner) = Option::fixPathToTargetOS((*inner), FALSE); + } + + if ( !project->variables()["DEF_FILE"].isEmpty() ) + project->variables()["QMAKE_LFLAGS"].append(QString("/DEF:") + project->first("DEF_FILE")); + if(!project->isActiveConfig("incremental")) + project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); + + if ( !project->variables()["VERSION"].isEmpty() ) { + QString version = project->variables()["VERSION"][0]; + int firstDot = version.find( "." ); + QString major = version.left( firstDot ); + QString minor = version.right( version.length() - firstDot - 1 ); + minor.replace( ".", "" ); + project->variables()["QMAKE_LFLAGS"].append( "/VERSION:" + major + "." + minor ); + } + if ( !project->variables()["RC_FILE"].isEmpty()) { + if ( !project->variables()["RES_FILE"].isEmpty()) { + fprintf(stderr, "Both .rc and .res file specified.\n"); + fprintf(stderr, "Please specify one of them, not both."); + exit(666); + } + project->variables()["RES_FILE"] = project->variables()["RC_FILE"]; + project->variables()["RES_FILE"].first().replace(".rc",".res"); + project->variables()["TARGETDEPS"] += project->variables()["RES_FILE"]; + } + if ( !project->variables()["RES_FILE"].isEmpty()) + project->variables()["QMAKE_LIBS"] += project->variables()["RES_FILE"]; + + MakefileGenerator::init(); + if ( !project->variables()["VERSION"].isEmpty()) { + QStringList l = QStringList::split('.', project->first("VERSION")); + project->variables()["VER_MAJ"].append(l[0]); + project->variables()["VER_MIN"].append(l[1]); + } + if(project->isActiveConfig("dll")) { + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".lib"); + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".exp"); + } + if(project->isActiveConfig("debug")) { + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".pdb"); + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".ilk"); + project->variables()["QMAKE_CLEAN"].append("vc*.pdb"); + } +} diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h new file mode 100644 index 0000000..d3e170f --- a/dev/null +++ b/qmake/generators/win32/msvc_nmake.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __NMAKEMAKE_H__ +#define __NMAKEMAKE_H__ + +#include "winmakefile.h" + +class NmakeMakefileGenerator : public Win32MakefileGenerator +{ + bool init_flag; + void writeNmakeParts(QTextStream &); + + bool writeMakefile(QTextStream &); + void init(); + +public: + NmakeMakefileGenerator(QMakeProject *p); + ~NmakeMakefileGenerator(); + +}; + +inline NmakeMakefileGenerator::~NmakeMakefileGenerator() +{ } + +#endif /* __NMAKEMAKE_H__ */ diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp new file mode 100644 index 0000000..c2b9e30 --- a/dev/null +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -0,0 +1,1955 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Copyright (C) 2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "msvc_objectmodel.h" +#include "msvc_vcproj.h" +#include <qtextstream.h> +#include <qstringlist.h> +#include <quuid.h> + +#if defined(Q_OS_WIN32) +#include <objbase.h> +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + ulong Data1; + ushort Data2; + ushort Data3; + uchar Data4[8]; +} GUID; +#endif +#endif + +// XML Tags --------------------------------------------------------- +const char* _xmlInit = "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>"; +const char* _begConfiguration = "\n\t\t<Configuration"; +const char* _begConfigurations = "\n\t<Configurations>"; +const char* _begFile = "\n\t\t\t<File"; +const char* _begFileConfiguration = "\n\t\t\t\t<FileConfiguration"; +const char* _begFiles = "\n\t<Files>"; +const char* _begFilter = "\n\t\t<Filter"; +const char* _begGlobals = "\n\t<Globals>"; +const char* _begPlatform = "\n\t\t<Platform"; +const char* _begPlatforms = "\n\t<Platforms>"; +const char* _begTool3 = "\n\t\t\t<Tool"; +const char* _begTool5 = "\n\t\t\t\t\t<Tool"; +const char* _begVisualStudioProject = "\n<VisualStudioProject"; +const char* _endConfiguration = "\n\t\t</Configuration>"; +const char* _endConfigurations = "\n\t</Configurations>"; +const char* _endFile = "\n\t\t\t</File>"; +const char* _endFileConfiguration = "\n\t\t\t\t</FileConfiguration>"; +const char* _endFiles = "\n\t</Files>"; +const char* _endFilter = "\n\t\t</Filter>"; +const char* _endGlobals = "\n\t</Globals>"; +const char* _endPlatforms = "\n\t</Platforms>"; +const char* _endVisualStudioProject = "\n</VisualStudioProject>"; + +// XML Properties --------------------------------------------------- +const char* _AddModuleNamesToAssembly = "\n\t\t\t\tAddModuleNamesToAssembly=\""; +const char* _AdditionalDependencies4 = "\n\t\t\t\tAdditionalDependencies=\""; +const char* _AdditionalDependencies6 = "\n\t\t\t\t\t\tAdditionalDependencies=\""; +const char* _AdditionalIncludeDirectories = "\n\t\t\t\tAdditionalIncludeDirectories=\""; +const char* _AdditionalLibraryDirectories = "\n\t\t\t\tAdditionalLibraryDirectories=\""; +const char* _AdditionalOptions = "\n\t\t\t\tAdditionalOptions=\""; +const char* _AdditionalUsingDirectories = "\n\t\t\t\tAdditionalUsingDirectories=\""; +const char* _AssemblerListingLocation = "\n\t\t\t\tAssemblerListingLocation=\""; +const char* _AssemblerOutput = "\n\t\t\t\tAssemblerOutput=\""; +const char* _ATLMinimizesCRunTimeLibraryUsage = "\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\""; +const char* _BaseAddress = "\n\t\t\t\tBaseAddress=\""; +const char* _BasicRuntimeChecks = "\n\t\t\t\tBasicRuntimeChecks=\""; +const char* _BrowseInformation = "\n\t\t\t\tBrowseInformation=\""; +const char* _BrowseInformationFile = "\n\t\t\t\tBrowseInformationFile=\""; +const char* _BufferSecurityCheck = "\n\t\t\t\tBufferSecurityCheck=\""; +const char* _BuildBrowserInformation = "\n\t\t\tBuildBrowserInformation=\""; +const char* _CPreprocessOptions = "\n\t\t\t\tCPreprocessOptions=\""; +const char* _CallingConvention = "\n\t\t\t\tCallingConvention=\""; +const char* _CharacterSet = "\n\t\t\tCharacterSet=\""; +const char* _CommandLine4 = "\n\t\t\t\tCommandLine=\""; +const char* _CommandLine6 = "\n\t\t\t\t\t\tCommandLine=\""; +const char* _CompileAs = "\n\t\t\t\tCompileAs=\""; +const char* _CompileAsManaged = "\n\t\t\t\tCompileAsManaged=\""; +const char* _CompileOnly = "\n\t\t\t\tCompileOnly=\""; +const char* _ConfigurationType = "\n\t\t\tConfigurationType=\""; +const char* _Culture = "\n\t\t\t\tCulture=\""; +const char* _DLLDataFileName = "\n\t\t\t\tDLLDataFileName=\""; +const char* _DebugInformationFormat = "\n\t\t\t\tDebugInformationFormat=\""; +const char* _DefaultCharIsUnsigned = "\n\t\t\t\tDefaultCharIsUnsigned=\""; +const char* _DefaultCharType = "\n\t\t\t\tDefaultCharType=\""; +const char* _DelayLoadDLLs = "\n\t\t\t\tDelayLoadDLLs=\""; +const char* _DeleteExtensionsOnClean = "\n\t\t\tDeleteExtensionsOnClean=\""; +const char* _Description4 = "\n\t\t\t\tDescription=\""; +const char* _Description6 = "\n\t\t\t\t\t\tDescription=\""; +const char* _Detect64BitPortabilityProblems = "\n\t\t\t\tDetect64BitPortabilityProblems=\""; +const char* _DisableLanguageExtensions = "\n\t\t\t\tDisableLanguageExtensions=\""; +const char* _DisableSpecificWarnings = "\n\t\t\t\tDisableSpecificWarnings=\""; +const char* _EnableCOMDATFolding = "\n\t\t\t\tEnableCOMDATFolding=\""; +const char* _EnableErrorChecks = "\n\t\t\t\tEnableErrorChecks=\""; +const char* _EnableFiberSafeOptimizations = "\n\t\t\t\tEnableFiberSafeOptimizations=\""; +const char* _EnableFunctionLevelLinking = "\n\t\t\t\tEnableFunctionLevelLinking=\""; +const char* _EnableIntrinsicFunctions = "\n\t\t\t\tEnableIntrinsicFunctions=\""; +const char* _EntryPointSymbol = "\n\t\t\t\tEntryPointSymbol=\""; +const char* _ErrorCheckAllocations = "\n\t\t\t\tErrorCheckAllocations=\""; +const char* _ErrorCheckBounds = "\n\t\t\t\tErrorCheckBounds=\""; +const char* _ErrorCheckEnumRange = "\n\t\t\t\tErrorCheckEnumRange=\""; +const char* _ErrorCheckRefPointers = "\n\t\t\t\tErrorCheckRefPointers=\""; +const char* _ErrorCheckStubData = "\n\t\t\t\tErrorCheckStubData=\""; +const char* _ExceptionHandling = "\n\t\t\t\tExceptionHandling=\""; +const char* _ExcludedFromBuild = "\n\t\t\t\tExcludedFromBuild=\""; +const char* _ExpandAttributedSource = "\n\t\t\t\tExpandAttributedSource=\""; +const char* _ExportNamedFunctions = "\n\t\t\t\tExportNamedFunctions=\""; +const char* _FavorSizeOrSpeed = "\n\t\t\t\tFavorSizeOrSpeed=\""; +const char* _Filter = "\n\t\t\tFilter=\""; +const char* _ForceConformanceInForLoopScope = "\n\t\t\t\tForceConformanceInForLoopScope=\""; +const char* _ForceSymbolReferences = "\n\t\t\t\tForceSymbolReferences=\""; +const char* _ForcedIncludeFiles = "\n\t\t\t\tForcedIncludeFiles=\""; +const char* _ForcedUsingFiles = "\n\t\t\t\tForcedUsingFiles=\""; +const char* _FullIncludePath = "\n\t\t\t\tFullIncludePath=\""; +const char* _FunctionOrder = "\n\t\t\t\tFunctionOrder=\""; +const char* _GenerateDebugInformation = "\n\t\t\t\tGenerateDebugInformation=\""; +const char* _GenerateMapFile = "\n\t\t\t\tGenerateMapFile=\""; +const char* _GeneratePreprocessedFile = "\n\t\t\t\tGeneratePreprocessedFile=\""; +const char* _GenerateStublessProxies = "\n\t\t\t\tGenerateStublessProxies=\""; +const char* _GenerateTypeLibrary = "\n\t\t\t\tGenerateTypeLibrary=\""; +const char* _GlobalOptimizations = "\n\t\t\t\tGlobalOptimizations=\""; +const char* _HeaderFileName = "\n\t\t\t\tHeaderFileName=\""; +const char* _HeapCommitSize = "\n\t\t\t\tHeapCommitSize=\""; +const char* _HeapReserveSize = "\n\t\t\t\tHeapReserveSize=\""; +const char* _IgnoreAllDefaultLibraries = "\n\t\t\t\tIgnoreAllDefaultLibraries=\""; +const char* _IgnoreDefaultLibraryNames = "\n\t\t\t\tIgnoreDefaultLibraryNames=\""; +const char* _IgnoreEmbeddedIDL = "\n\t\t\t\tIgnoreEmbeddedIDL=\""; +const char* _IgnoreImportLibrary = "\n\t\t\t\tIgnoreImportLibrary=\""; +const char* _IgnoreStandardIncludePath = "\n\t\t\t\tIgnoreStandardIncludePath=\""; +const char* _ImportLibrary = "\n\t\t\t\tImportLibrary=\""; +const char* _ImproveFloatingPointConsistency = "\n\t\t\t\tImproveFloatingPointConsistency=\""; +const char* _InlineFunctionExpansion = "\n\t\t\t\tInlineFunctionExpansion=\""; +const char* _InterfaceIdentifierFileName = "\n\t\t\t\tInterfaceIdentifierFileName=\""; +const char* _IntermediateDirectory = "\n\t\t\tIntermediateDirectory=\""; +const char* _KeepComments = "\n\t\t\t\tKeepComments=\""; +const char* _LargeAddressAware = "\n\t\t\t\tLargeAddressAware=\""; +const char* _LinkDLL = "\n\t\t\t\tLinkDLL=\""; +const char* _LinkIncremental = "\n\t\t\t\tLinkIncremental=\""; +const char* _LinkTimeCodeGeneration = "\n\t\t\t\tLinkTimeCodeGeneration=\""; +const char* _LinkToManagedResourceFile = "\n\t\t\t\tLinkToManagedResourceFile=\""; +const char* _MapExports = "\n\t\t\t\tMapExports=\""; +const char* _MapFileName = "\n\t\t\t\tMapFileName=\""; +const char* _MapLines = "\n\t\t\t\tMapLines =\""; +const char* _MergeSections = "\n\t\t\t\tMergeSections=\""; +const char* _MergedIDLBaseFileName = "\n\t\t\t\tMergedIDLBaseFileName=\""; +const char* _MidlCommandFile = "\n\t\t\t\tMidlCommandFile=\""; +const char* _MinimalRebuild = "\n\t\t\t\tMinimalRebuild=\""; +const char* _MkTypLibCompatible = "\n\t\t\t\tMkTypLibCompatible=\""; +const char* _ModuleDefinitionFile = "\n\t\t\t\tModuleDefinitionFile=\""; +const char* _Name1 = "\n\tName=\""; +const char* _Name2 = "\n\t\tName=\""; +const char* _Name3 = "\n\t\t\tName=\""; +const char* _Name4 = "\n\t\t\t\tName=\""; +const char* _Name5 = "\n\t\t\t\t\tName=\""; +const char* _ObjectFile = "\n\t\t\t\tObjectFile=\""; +const char* _OmitFramePointers = "\n\t\t\t\tOmitFramePointers=\""; +const char* _Optimization = "\n\t\t\t\tOptimization =\""; +const char* _OptimizeForProcessor = "\n\t\t\t\tOptimizeForProcessor=\""; +const char* _OptimizeForWindows98 = "\n\t\t\t\tOptimizeForWindows98=\""; +const char* _OptimizeForWindowsApplication = "\n\t\t\t\tOptimizeForWindowsApplication=\""; +const char* _OptimizeReferences = "\n\t\t\t\tOptimizeReferences=\""; +const char* _OutputDirectory3 = "\n\t\t\tOutputDirectory=\""; +const char* _OutputDirectory4 = "\n\t\t\t\tOutputDirectory=\""; +const char* _OutputFile = "\n\t\t\t\tOutputFile=\""; +const char* _Outputs4 = "\n\t\t\t\tOutputs=\""; +const char* _Outputs6 = "\n\t\t\t\t\t\tOutputs=\""; +const char* _ParseFiles = "\n\t\t\tParseFiles=\""; +const char* _PrecompiledHeaderFile = "\n\t\t\t\tPrecompiledHeaderFile=\""; +const char* _PrecompiledHeaderThrough = "\n\t\t\t\tPrecompiledHeaderThrough=\""; +const char* _PreprocessorDefinitions = "\n\t\t\t\tPreprocessorDefinitions=\""; +const char* _PrimaryOutput = "\n\t\t\tPrimaryOutput=\""; +const char* _ProjectGUID = "\n\tProjectGUID=\""; +const char* _ProjectType = "\n\tProjectType=\"Visual C++\""; +const char* _ProgramDatabase = "\n\t\t\tProgramDatabase=\""; +const char* _ProgramDataBaseFileName = "\n\t\t\t\tProgramDataBaseFileName=\""; +const char* _ProgramDatabaseFile = "\n\t\t\t\tProgramDatabaseFile=\""; +const char* _ProxyFileName = "\n\t\t\t\tProxyFileName=\""; +const char* _RedirectOutputAndErrors = "\n\t\t\t\tRedirectOutputAndErrors=\""; +const char* _RegisterOutput = "\n\t\t\t\tRegisterOutput=\""; +const char* _RelativePath = "\n\t\t\t\tRelativePath=\""; +const char* _ResourceOnlyDLL = "\n\t\t\t\tResourceOnlyDLL=\""; +const char* _ResourceOutputFileName = "\n\t\t\t\tResourceOutputFileName=\""; +const char* _RuntimeLibrary = "\n\t\t\t\tRuntimeLibrary=\""; +const char* _RuntimeTypeInfo = "\n\t\t\t\tRuntimeTypeInfo=\""; +const char* _SccProjectName = "\n\tSccProjectName=\""; +const char* _SccLocalPath = "\n\tSccLocalPath=\""; +const char* _SetChecksum = "\n\t\t\t\tSetChecksum=\""; +const char* _ShowIncludes = "\n\t\t\t\tShowIncludes=\""; +const char* _ShowProgress = "\n\t\t\t\tShowProgress=\""; +const char* _SmallerTypeCheck = "\n\t\t\t\tSmallerTypeCheck=\""; +const char* _StackCommitSize = "\n\t\t\t\tStackCommitSize=\""; +const char* _StackReserveSize = "\n\t\t\t\tStackReserveSize=\""; +const char* _StringPooling = "\n\t\t\t\tStringPooling=\""; +const char* _StripPrivateSymbols = "\n\t\t\t\tStripPrivateSymbols=\""; +const char* _StructMemberAlignment = "\n\t\t\t\tStructMemberAlignment=\""; +const char* _SubSystem = "\n\t\t\t\tSubSystem=\""; +const char* _SupportUnloadOfDelayLoadedDLL = "\n\t\t\t\tSupportUnloadOfDelayLoadedDLL=\""; +const char* _SuppressStartupBanner = "\n\t\t\t\tSuppressStartupBanner=\""; +const char* _SwapRunFromCD = "\n\t\t\t\tSwapRunFromCD=\""; +const char* _SwapRunFromNet = "\n\t\t\t\tSwapRunFromNet=\""; +const char* _TargetEnvironment = "\n\t\t\t\tTargetEnvironment=\""; +const char* _TargetMachine = "\n\t\t\t\tTargetMachine=\""; +const char* _TerminalServerAware = "\n\t\t\t\tTerminalServerAware=\""; +const char* _ToolName = "\n\t\t\t\tName=\""; +const char* _ToolPath = "\n\t\t\t\tPath=\""; +const char* _TreatWChar_tAsBuiltInType = "\n\t\t\t\tTreatWChar_tAsBuiltInType=\""; +const char* _TurnOffAssemblyGeneration = "\n\t\t\t\tTurnOffAssemblyGeneration=\""; +const char* _TypeLibraryFile = "\n\t\t\t\tTypeLibraryFile=\""; +const char* _TypeLibraryName = "\n\t\t\t\tTypeLibraryName=\""; +const char* _TypeLibraryResourceID = "\n\t\t\t\tTypeLibraryResourceID=\""; +const char* _UndefineAllPreprocessorDefinitions = "\n\t\t\t\tUndefineAllPreprocessorDefinitions=\""; +const char* _UndefinePreprocessorDefinitions = "\n\t\t\t\tUndefinePreprocessorDefinitions=\""; +const char* _UseOfATL = "\n\t\t\tUseOfATL=\""; +const char* _UseOfMfc = "\n\t\t\tUseOfMfc=\""; +const char* _UsePrecompiledHeader = "\n\t\t\t\tUsePrecompiledHeader=\""; +const char* _ValidateParameters = "\n\t\t\t\tValidateParameters=\""; +const char* _VCCLCompilerToolName = "\n\t\t\t\tName=\"VCCLCompilerTool\""; +const char* _VCCustomBuildTool = "\n\t\t\t\t\t\tName=\"VCCustomBuildTool\""; +const char* _VCLinkerToolName = "\n\t\t\t\tName=\"VCLinkerTool\""; +const char* _VCResourceCompilerToolName = "\n\t\t\t\tName=\"VCResourceCompilerTool\""; +const char* _VCMIDLToolName = "\n\t\t\t\tName=\"VCMIDLTool\""; +const char* _Version1 = "\n\tVersion=\""; +const char* _Version4 = "\n\t\t\t\tVersion=\""; +const char* _WarnAsError = "\n\t\t\t\tWarnAsError=\""; +const char* _WarnLevel = "\n\t\t\t\tWarnLevel=\""; +const char* _WarningLevel = "\n\t\t\t\tWarningLevel=\""; +const char* _WholeProgramOptimization = "\n\t\t\t\tWholeProgramOptimization=\""; + +// Property name and value as Pairs --------------------------------- +struct TPair { + TPair( const char* n, const triState v ) : name(n), value(v) {}; + const char* name; + const triState value; +}; +struct EPair { + EPair( const char* n, const int v ) : name(n), value(v) {}; + const char* name; + const int value; +}; +struct LPair { + LPair( const char* n, const long v ) : name(n), value(v) {}; + const char* name; + const long value; +}; +struct SPair { + SPair( const char* n, const QString& v ) : name(n), value(v) {}; + const char* name; + const QString& value; +}; +struct XPair { + XPair( const char* n, const QStringList& v, const char* s = "," ) : name(n), value(v), sep(s) {}; + const char* name; + const QStringList& value; + const char* sep; +}; + +// void streamSPair( QTextStream &strm, const char *n, const QString &s ) + + +// Streaming operators for property Pairs --------------------------- +QTextStream &operator<<( QTextStream &strm, const TPair &prop ) +{ + switch( prop.value ) { + case _False: + strm << prop.name << "FALSE\""; + break; + case _True: + strm << prop.name << "TRUE\""; + break; + case unset: + default: + break; + } + return strm; +} + +/* Be sure to check that each enum is not set to + default before streaming it out. Defaults seem + to not be in the XML file. +*/ +QTextStream &operator<<( QTextStream &strm, const EPair &prop ) +{ + strm << prop.name << prop.value << "\""; + return strm; +} + +QTextStream &operator<<( QTextStream &strm, const LPair &prop ) +{ + strm << prop.name << prop.value << "\""; + return strm; +} + +QTextStream &operator<<( QTextStream &strm, const SPair &prop ) +{ + if ( !prop.value.isEmpty() ) + strm << prop.name << prop.value.latin1() << "\""; + return strm; +} + +QTextStream &operator<<( QTextStream &strm, const XPair &prop ) +{ + if ( !prop.value.isEmpty() ) + strm << prop.name << prop.value.join(prop.sep).latin1() << "\""; + return strm; +} + +// VCCLCompilerTool ------------------------------------------------- +VCCLCompilerTool::VCCLCompilerTool() + : AssemblerOutput( asmListingNone ), + BasicRuntimeChecks( runtimeBasicCheckNone ), + BrowseInformation( brInfoNone ), + BufferSecurityCheck( unset ), + CallingConvention( callConventionDefault ), + CompileAs( compileAsDefault ), + CompileAsManaged( managedDefault ), + CompileOnly( unset ), + DebugInformationFormat( debugDisabled ), + DefaultCharIsUnsigned( unset ), + Detect64BitPortabilityProblems( unset ), + DisableLanguageExtensions( unset ), + EnableFiberSafeOptimizations( unset ), + EnableFunctionLevelLinking( unset ), + EnableIntrinsicFunctions( unset ), + ExceptionHandling( unset ), + ExpandAttributedSource( unset ), + FavorSizeOrSpeed( favorNone ), + ForceConformanceInForLoopScope( unset ), + GeneratePreprocessedFile( preprocessNo ), + GlobalOptimizations( unset ), + IgnoreStandardIncludePath( unset ), + ImproveFloatingPointConsistency( unset ), + InlineFunctionExpansion( expandOnlyInline ), + KeepComments( unset ), + MinimalRebuild( unset ), + OmitFramePointers( unset ), + Optimization( optimizeDisabled ), + OptimizeForProcessor( procOptimizeBlended ), + OptimizeForWindowsApplication( unset ), + RuntimeLibrary( rtMultiThreaded ), + RuntimeTypeInfo( unset ), + ShowIncludes( unset ), + SmallerTypeCheck( unset ), + StringPooling( unset ), + StructMemberAlignment( alignNotSet ), + SuppressStartupBanner( unset ), + TreatWChar_tAsBuiltInType( unset ), + TurnOffAssemblyGeneration( unset ), + UndefineAllPreprocessorDefinitions( unset ), + UsePrecompiledHeader( pchGenerateAuto ), + WarnAsError( unset ), + WarningLevel( warningLevel_0 ), + WholeProgramOptimization( unset ) +{ +} + +QTextStream &operator<<( QTextStream &strm, const VCCLCompilerTool &tool ) +{ + strm << _begTool3; + strm << _VCCLCompilerToolName; + strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalUsingDirectories, tool.AdditionalUsingDirectories ); + strm << SPair( _AssemblerListingLocation, tool.AssemblerListingLocation ); + if ( tool.AssemblerOutput != asmListingNone ) strm << EPair( _AssemblerOutput, tool.AssemblerOutput ); + if ( tool.BasicRuntimeChecks != runtimeBasicCheckNone ) strm << EPair( _BasicRuntimeChecks, tool.BasicRuntimeChecks ); + if ( tool.BrowseInformation != brInfoNone ) strm << EPair( _BrowseInformation, tool.BrowseInformation ); + strm << SPair( _BrowseInformationFile, tool.BrowseInformationFile ); + strm << TPair( _BufferSecurityCheck, tool.BufferSecurityCheck ); + if ( tool.CallingConvention != callConventionDefault ) strm << EPair( _CallingConvention, tool.CallingConvention ); + if ( tool.CompileAs != compileAsDefault ) strm << EPair( _CompileAs, tool.CompileAs ); + if ( tool.CompileAsManaged != managedDefault ) strm << EPair( _CompileAsManaged, tool.CompileAsManaged ); + strm << TPair( _CompileOnly, tool.CompileOnly ); + strm << EPair( _DebugInformationFormat, tool.DebugInformationFormat ); + strm << TPair( _DefaultCharIsUnsigned, tool.DefaultCharIsUnsigned ); + strm << TPair( _Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems ); + strm << TPair( _DisableLanguageExtensions, tool.DisableLanguageExtensions ); + strm << XPair( _DisableSpecificWarnings, tool.DisableSpecificWarnings ); + strm << TPair( _EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations ); + strm << TPair( _EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking ); + strm << TPair( _EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions ); + strm << TPair( _ExceptionHandling, tool.ExceptionHandling ); + strm << TPair( _ExpandAttributedSource, tool.ExpandAttributedSource ); + if ( tool.FavorSizeOrSpeed != favorNone ) strm << EPair( _FavorSizeOrSpeed, tool.FavorSizeOrSpeed ); + strm << TPair( _ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope ); + strm << XPair( _ForcedIncludeFiles, tool.ForcedIncludeFiles ); + strm << XPair( _ForcedUsingFiles, tool.ForcedUsingFiles ); + strm << EPair( _GeneratePreprocessedFile, tool.GeneratePreprocessedFile ); + strm << TPair( _GlobalOptimizations, tool.GlobalOptimizations ); + strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); + strm << TPair( _ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency ); + strm << EPair( _InlineFunctionExpansion, tool.InlineFunctionExpansion ); + strm << TPair( _KeepComments, tool.KeepComments ); + strm << TPair( _MinimalRebuild, tool.MinimalRebuild ); + strm << SPair( _ObjectFile, tool.ObjectFile ); + strm << TPair( _OmitFramePointers, tool.OmitFramePointers ); + strm << EPair( _Optimization, tool.Optimization ); + if ( tool.OptimizeForProcessor != procOptimizeBlended ) strm << EPair( _OptimizeForProcessor, tool.OptimizeForProcessor ); + strm << TPair( _OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication ); + strm << SPair( _OutputFile, tool.OutputFile ); + strm << SPair( _PrecompiledHeaderFile, tool.PrecompiledHeaderFile ); + strm << SPair( _PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough ); + strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); + strm << SPair( _ProgramDataBaseFileName, tool.ProgramDataBaseFileName ); + strm << EPair( _RuntimeLibrary, tool.RuntimeLibrary ); + strm << TPair( _RuntimeTypeInfo, tool.RuntimeTypeInfo ); + strm << TPair( _ShowIncludes, tool.ShowIncludes ); + strm << TPair( _SmallerTypeCheck, tool.SmallerTypeCheck ); + strm << TPair( _StringPooling, tool.StringPooling ); + if ( tool.StructMemberAlignment != alignNotSet ) strm << EPair( _StructMemberAlignment, tool.StructMemberAlignment ); + strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); + strm << TPair( _TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType ); + strm << TPair( _TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration ); + strm << TPair( _UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions ); + strm << XPair( _UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions ); + if ( !tool.PrecompiledHeaderFile.isEmpty() || + !tool.PrecompiledHeaderThrough.isEmpty() ) + strm << EPair( _UsePrecompiledHeader, tool.UsePrecompiledHeader ); + strm << TPair( _WarnAsError, tool.WarnAsError ); + strm << EPair( _WarningLevel, tool.WarningLevel ); + strm << TPair( _WholeProgramOptimization, tool.WholeProgramOptimization ); + strm << "/>"; +return strm; +} + +bool VCCLCompilerTool::parseOption( const char* option ) +{ + // skip index 0 ('/' or '-') + char first = option[1]; + char second = option[2]; + char third = option[3]; + char fourth = option[4]; + + switch ( first ) { + case '?': + case 'h': + qWarning( "Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info" ); + return FALSE; + case '@': + qWarning( "Generator: Option '/@': MSVC.NET projects do not support the use of a response file" ); + return FALSE; + case 'l': + qWarning( "Generator: Option '/link': qmake generator does not support passing link options through the compiler tool" ); + return FALSE; + + case 'A': + if ( second != 'I' ) + return FALSE; + AdditionalUsingDirectories += option+2; + break; + case 'C': + KeepComments = _True; + break; + case 'D': + PreprocessorDefinitions += option+1; + break; + case 'E': + if ( second == 'H' ) { + if ( third == 'a' || third == 'c' || third == 's' ) { + // ExceptionHandling must be false, or it will override + // with an /EHsc option + ExceptionHandling = _False; + AdditionalOptions += option; + break; + } + return FALSE; + } + GeneratePreprocessedFile = preprocessYes; + break; + case 'F': + if ( second <= '9' && second >= '0' ) { + AdditionalOptions += option; + break; + } else { + switch ( second ) { + case 'A': + if ( third == 'c' ) { + AssemblerOutput = asmListingAsmMachine; + if ( fourth == 's' ) + AssemblerOutput = asmListingAsmMachineSrc; + } else if ( third == 's' ) { + AssemblerOutput = asmListingAsmSrc; + } else { + AssemblerOutput = asmListingAssemblyOnly; + } + break; + case 'a': + AssemblerListingLocation = option+3; + break; + case 'I': + ForcedIncludeFiles += option+3; + break; + case 'R': + BrowseInformation = brAllInfo; + BrowseInformationFile = option+3; + break; + case 'r': + BrowseInformation = brNoLocalSymbols; + BrowseInformationFile = option+3; + break; + case 'U': + ForcedUsingFiles += option+3; + break; + case 'd': + ProgramDataBaseFileName = option+3; + break; + case 'e': + OutputFile = option+3; + break; + case 'm': + AdditionalOptions += option; + break; + case 'o': + ObjectFile = option+3; + break; + case 'p': + PrecompiledHeaderFile = option+3; + break; + case 'x': + ExpandAttributedSource = _True; + break; + default: + return FALSE; + } + } + break; + case 'G': + switch ( second ) { + case '3': + case '4': + qWarning( "Option '/G3' and '/G4' were phased out in Visual C++ 5.0" ); + return FALSE; + case '5': + OptimizeForProcessor = procOptimizePentium; + break; + case '6': + case 'B': + OptimizeForProcessor = procOptimizePentiumProAndAbove; + break; + case 'A': + OptimizeForWindowsApplication = _True; + break; + case 'F': + StringPooling = _True; + break; + case 'H': + AdditionalOptions += option; + break; + case 'L': + WholeProgramOptimization = _True; + if ( third == '-' ) + WholeProgramOptimization = _False; + break; + case 'R': + RuntimeTypeInfo = _True; + if ( third == '-' ) + RuntimeTypeInfo = _False; + break; + case 'S': + BufferSecurityCheck = _True; + break; + case 'T': + EnableFiberSafeOptimizations = _True; + break; + case 'X': + case 'Z': + case 'e': + case 'h': + AdditionalOptions += option; + break; + case 'd': + CallingConvention = callConventionCDecl; + break; + case 'f': + StringPooling = _True; + AdditionalOptions += option; + break; + case 'm': + MinimalRebuild = _True; + if ( third == '-' ) + MinimalRebuild = _False; + break; + case 'r': + CallingConvention = callConventionFastCall; + break; + case 's': + // Warning: following [num] is not used, + // were should we put it? + BufferSecurityCheck = _True; + break; + case 'y': + EnableFunctionLevelLinking = _True; + break; + case 'z': + CallingConvention = callConventionStdCall; + break; + default: + return FALSE; + } + break; + case 'H': + AdditionalOptions += option; + break; + case 'I': + AdditionalIncludeDirectories += option+2; + break; + case 'L': + if ( second == 'D' ) { + AdditionalOptions += option; + break; + } + return FALSE; + case 'M': + if ( second == 'D' ) { + RuntimeLibrary = rtMultiThreadedDLL; + if ( third == 'd' ) + RuntimeLibrary = rtMultiThreadedDebugDLL; + break; + } else if ( second == 'L' ) { + RuntimeLibrary = rtSingleThreaded; + if ( third == 'd' ) + RuntimeLibrary = rtSingleThreadedDebug; + break; + } else if ( second == 'T' ) { + RuntimeLibrary = rtMultiThreaded; + if ( third == 'd' ) + RuntimeLibrary = rtMultiThreadedDebug; + break; + } + return FALSE; + case 'O': + switch ( second ) { + case '1': + Optimization = optimizeMinSpace; + break; + case '2': + Optimization = optimizeMaxSpeed; + break; + case 'a': + AdditionalOptions += option; + break; + case 'b': + if ( third == '0' ) + InlineFunctionExpansion = expandDisable; + else if ( third == '1' ) + InlineFunctionExpansion = expandOnlyInline; + else if ( third == '2' ) + InlineFunctionExpansion = expandAnySuitable; + else + return FALSE; + break; + case 'd': + Optimization = optimizeDisabled; + break; + case 'g': + GlobalOptimizations = _True; + break; + case 'i': + EnableIntrinsicFunctions = _True; + break; + case 'p': + ImproveFloatingPointConsistency = _True; + if ( third == '-' ) + ImproveFloatingPointConsistency = _False; + break; + case 's': + FavorSizeOrSpeed = favorSize; + break; + case 't': + FavorSizeOrSpeed = favorSpeed; + break; + case 'w': + AdditionalOptions += option; + break; + case 'x': + Optimization = optimizeFull; + break; + case 'y': + OmitFramePointers = _True; + if ( third == '-' ) + OmitFramePointers = _False; + break; + default: + return FALSE; + } + break; + case 'P': + GeneratePreprocessedFile = preprocessYes; + break; + case 'Q': + if ( second == 'I' ) { + AdditionalOptions += option; + break; + } + return FALSE; + case 'R': + if ( second == 'T' && third == 'C' ) { + if ( fourth == '1' ) + BasicRuntimeChecks = runtimeBasicCheckAll; + else if ( fourth == 'c' ) + SmallerTypeCheck = _True; + else if ( fourth == 's' ) + BasicRuntimeChecks = runtimeCheckStackFrame; + else if ( fourth == 'u' ) + BasicRuntimeChecks = runtimeCheckUninitVariables; + else + return FALSE; + } + break; + case 'T': + if ( second == 'C' ) { + CompileAs = compileAsC; + } else if ( second == 'P' ) { + CompileAs = compileAsCPlusPlus; + } else { + qWarning( "Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake" ); + return FALSE; + } + break; + case 'U': + UndefinePreprocessorDefinitions += option+2; + break; + case 'V': + AdditionalOptions += option; + break; + case 'W': + switch ( second ) { + case 'a': + case '4': + WarningLevel = warningLevel_4; + break; + case '3': + WarningLevel = warningLevel_3; + break; + case '2': + WarningLevel = warningLevel_2; + break; + case '1': + WarningLevel = warningLevel_1; + break; + case '0': + WarningLevel = warningLevel_0; + break; + case 'L': + AdditionalOptions += option; + break; + case 'X': + WarnAsError = _True; + break; + case 'p': + if ( third == '6' && fourth == '4' ) { + Detect64BitPortabilityProblems = _True; + break; + } + // Fallthrough + default: + return FALSE; + } + break; + case 'X': + IgnoreStandardIncludePath = _True; + break; + case 'Y': + switch ( second ) { + case '\0': + case '-': + AdditionalOptions += option; + break; + case 'X': + UsePrecompiledHeader = pchGenerateAuto; + PrecompiledHeaderFile = option+3; + break; + case 'c': + UsePrecompiledHeader = pchCreateUsingSpecific; + PrecompiledHeaderFile = option+3; + break; + case 'd': + case 'l': + AdditionalOptions =+ option; + break; + case 'u': + UsePrecompiledHeader = pchUseUsingSpecific; + PrecompiledHeaderFile = option+3; + break; + default: + return FALSE; + } + break; + case 'Z': + switch ( second ) { + case '7': + DebugInformationFormat = debugOldStyleInfo; + break; + case 'I': + DebugInformationFormat = debugEditAndContinue; + break; + case 'd': + DebugInformationFormat = debugLineInfoOnly; + break; + case 'i': + DebugInformationFormat = debugEnabled; + break; + case 'l': + DebugInformationFormat = debugEditAndContinue; + break; + case 'a': + DisableLanguageExtensions = _True; + break; + case 'e': + DisableLanguageExtensions = _False; + break; + case 'c': + if ( third == ':' ) { + if ( fourth == 'f' ) + ForceConformanceInForLoopScope = _True; + else if ( fourth == 'w' ) + TreatWChar_tAsBuiltInType = _True; + else + return FALSE; + } else { + return FALSE; + } + break; + case 'g': + case 'm': + case 's': + AdditionalOptions += option; + break; + case 'p': + switch ( third ) + { + case '\0': + case '1': + StructMemberAlignment = alignSingleByte; + if ( fourth == '6' ) + StructMemberAlignment = alignSixteenBytes; + break; + case '2': + StructMemberAlignment = alignTwoBytes; + break; + case '4': + StructMemberAlignment = alignFourBytes; + break; + case '8': + StructMemberAlignment = alignEightBytes; + break; + default: + return FALSE; + } + break; + default: + return FALSE; + } + break; + case 'c': + if ( second == '\0' ) { + CompileOnly = _True; + } else if ( second == 'l' ) { + if ( *(option+5) == 'n' ) { + CompileAsManaged = managedAssembly; + TurnOffAssemblyGeneration = _True; + } else { + CompileAsManaged = managedAssembly; + } + } else { + return FALSE; + } + break; + case 'd': + if ( second != 'r' ) + return FALSE; + CompileAsManaged = managedAssembly; + break; + case 'n': + if ( second == 'o' && third == 'B' && fourth == 'o' ) { + AdditionalOptions += "/noBool"; + break; + } + if ( second == 'o' && third == 'l' && fourth == 'o' ) { + SuppressStartupBanner = _True; + break; + } + return FALSE; + case 's': + if ( second == 'h' && third == 'o' && fourth == 'w' ) { + ShowIncludes = _True; + break; + } + return FALSE; + case 'u': + UndefineAllPreprocessorDefinitions = _True; + break; + case 'v': + if ( second == 'd' || second == 'm' ) { + AdditionalOptions += option; + break; + } + return FALSE; + case 'w': + switch ( second ) { + case '\0': + WarningLevel = warningLevel_0; + break; + case 'd': + DisableSpecificWarnings += option+3; + break; + default: + AdditionalOptions += option; + } + break; + default: + return FALSE; + } + return TRUE; +} + +// VCLinkerTool ----------------------------------------------------- +VCLinkerTool::VCLinkerTool() + : EnableCOMDATFolding( optFoldingDefault ), + GenerateDebugInformation( unset ), + GenerateMapFile( unset ), + HeapCommitSize( -1 ), + HeapReserveSize( -1 ), + IgnoreAllDefaultLibraries( unset ), + IgnoreEmbeddedIDL( unset ), + IgnoreImportLibrary( unset ), + LargeAddressAware( addrAwareDefault ), + LinkDLL( unset ), + LinkIncremental( linkIncrementalYes ), + LinkTimeCodeGeneration( unset ), + MapExports( unset ), + MapLines( unset ), + OptimizeForWindows98( optWin98Default ), + OptimizeReferences( optReferencesDefault ), + RegisterOutput( unset ), + ResourceOnlyDLL( unset ), + SetChecksum( unset ), + ShowProgress( linkProgressNotSet ), + StackCommitSize( -1 ), + StackReserveSize( -1 ), + SubSystem( subSystemNotSet ), + SupportUnloadOfDelayLoadedDLL( unset ), + SuppressStartupBanner( unset ), + SwapRunFromCD( unset ), + SwapRunFromNet( unset ), + TargetMachine( machineNotSet ), + TerminalServerAware( termSvrAwareDefault ), + TurnOffAssemblyGeneration( unset ), + TypeLibraryResourceID( 0 ) +{ +} + +QTextStream &operator<<( QTextStream &strm, const VCLinkerTool &tool ) +{ + strm << _begTool3; + strm << _VCLinkerToolName; + strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies, " " ); + strm << XPair( _AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly ); + strm << SPair( _BaseAddress, tool.BaseAddress ); + strm << XPair( _DelayLoadDLLs, tool.DelayLoadDLLs ); + if ( tool.EnableCOMDATFolding != optFoldingDefault ) strm << EPair( _EnableCOMDATFolding, tool.EnableCOMDATFolding ); + strm << SPair( _EntryPointSymbol, tool.EntryPointSymbol ); + strm << XPair( _ForceSymbolReferences, tool.ForceSymbolReferences ); + strm << SPair( _FunctionOrder, tool.FunctionOrder ); + strm << TPair( _GenerateDebugInformation, tool.GenerateDebugInformation ); + strm << TPair( _GenerateMapFile, tool.GenerateMapFile ); + if ( tool.HeapCommitSize != -1 ) strm << LPair( _HeapCommitSize, tool.HeapCommitSize ); + if ( tool.HeapReserveSize != -1 ) strm << LPair( _HeapReserveSize, tool.HeapReserveSize ); + strm << TPair( _IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries ); + strm << XPair( _IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames ); + strm << TPair( _IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL ); + strm << TPair( _IgnoreImportLibrary, tool.IgnoreImportLibrary ); + strm << SPair( _ImportLibrary, tool.ImportLibrary ); + if ( tool.LargeAddressAware != addrAwareDefault ) strm << EPair( _LargeAddressAware, tool.LargeAddressAware ); + strm << TPair( _LinkDLL, tool.LinkDLL ); + if ( tool.LinkIncremental != linkIncrementalDefault ) strm << EPair( _LinkIncremental, tool.LinkIncremental ); + strm << TPair( _LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration ); + strm << SPair( _LinkToManagedResourceFile, tool.LinkToManagedResourceFile ); + strm << TPair( _MapExports, tool.MapExports ); + strm << SPair( _MapFileName, tool.MapFileName ); + strm << TPair( _MapLines, tool.MapLines ); + strm << SPair( _MergedIDLBaseFileName, tool.MergedIDLBaseFileName ); + strm << SPair( _MergeSections, tool.MergeSections ); + strm << SPair( _MidlCommandFile, tool.MidlCommandFile ); + strm << SPair( _ModuleDefinitionFile, tool.ModuleDefinitionFile ); + if ( tool.OptimizeForWindows98 != optWin98Default ) strm << EPair( _OptimizeForWindows98, tool.OptimizeForWindows98 ); + if ( tool.OptimizeReferences != optReferencesDefault ) strm << EPair( _OptimizeReferences, tool.OptimizeReferences ); + strm << SPair( _OutputFile, tool.OutputFile ); + strm << SPair( _ProgramDatabaseFile, tool.ProgramDatabaseFile ); + strm << TPair( _RegisterOutput, tool.RegisterOutput ); + strm << TPair( _ResourceOnlyDLL, tool.ResourceOnlyDLL ); + strm << TPair( _SetChecksum, tool.SetChecksum ); + if ( tool.ShowProgress != linkProgressNotSet ) strm << EPair( _ShowProgress, tool.ShowProgress ); + if ( tool.StackCommitSize != -1 ) strm << LPair( _StackCommitSize, tool.StackCommitSize ); + if ( tool.StackReserveSize != -1 ) strm << LPair( _StackReserveSize, tool.StackReserveSize ); + strm << SPair( _StripPrivateSymbols, tool.StripPrivateSymbols ); + strm << EPair( _SubSystem, tool.SubSystem ); + strm << TPair( _SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL ); + strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); + strm << TPair( _SwapRunFromCD, tool.SwapRunFromCD ); + strm << TPair( _SwapRunFromNet, tool.SwapRunFromNet ); + if ( tool.TargetMachine != machineNotSet ) strm << EPair( _TargetMachine, tool.TargetMachine ); + if ( tool.TerminalServerAware != termSvrAwareDefault ) strm << EPair( _TerminalServerAware, tool.TerminalServerAware ); + strm << TPair( _TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration ); + strm << SPair( _TypeLibraryFile, tool.TypeLibraryFile ); + if ( tool.TypeLibraryResourceID != rcUseDefault ) strm << LPair( _TypeLibraryResourceID, tool.TypeLibraryResourceID ); + strm << SPair( _Version4, tool.Version ); + strm << "/>"; + return strm; +} + +// Hashing routine to do fast option lookups ---- +// Slightly rewritten to stop on ':' ',' and '\0' +// Original routine in qtranslator.cpp ---------- +static uint elfHash( const char* name ) +{ + const uchar *k; + uint h = 0; + uint g; + + if ( name ) { + k = (const uchar *) name; + while ( (*k) && + (*k)!= ':' && + (*k)!=',' && + (*k)!=' ' ) { + h = ( h << 4 ) + *k++; + if ( (g = (h & 0xf0000000)) != 0 ) + h ^= g >> 24; + h &= ~g; + } + } + if ( !h ) + h = 1; + return h; +} +static void displayHash( const char* str ) +{ + printf( "case 0x%07x: // %s\n break;\n", elfHash(str), str ); +} + +bool VCLinkerTool::parseOption( const char* option ) +{ +#if 0 + // Main options + displayHash( "/ALIGN" ); displayHash( "/ALLOWBIND" ); displayHash( "/ASSEMBLYMODULE" ); + displayHash( "/ASSEMBLYRESOURCE" ); displayHash( "/BASE" ); displayHash( "/DEBUG" ); + displayHash( "/DEF" ); displayHash( "/DEFAULTLIB" ); displayHash( "/DELAY" ); + displayHash( "/DELAYLOAD" ); displayHash( "/DLL" ); displayHash( "/DRIVER" ); + displayHash( "/ENTRY" ); displayHash( "/EXETYPE" ); displayHash( "/EXPORT" ); + displayHash( "/FIXED" ); displayHash( "/FORCE" ); displayHash( "/HEAP" ); + displayHash( "/IDLOUT" ); displayHash( "/IGNOREIDL" ); displayHash( "/IMPLIB" ); + displayHash( "/INCLUDE" ); displayHash( "/INCREMENTAL" ); displayHash( "/LARGEADDRESSAWARE" ); + displayHash( "/LIBPATH" ); displayHash( "/LTCG" ); displayHash( "/MACHINE" ); + displayHash( "/MAP" ); displayHash( "/MAPINFO" ); displayHash( "/MERGE" ); + displayHash( "/MIDL" ); displayHash( "/NOASSEMBLY" ); displayHash( "/NODEFAULTLIB" ); + displayHash( "/NOENTRY" ); displayHash( "/NOLOGO" ); displayHash( "/OPT" ); + displayHash( "/ORDER" ); displayHash( "/OUT" ); displayHash( "/PDB" ); + displayHash( "/PDBSTRIPPED" ); displayHash( "/RELEASE" ); displayHash( "/SECTION" ); + displayHash( "/STACK" ); displayHash( "/STUB" ); displayHash( "/SUBSYSTEM" ); + displayHash( "/SWAPRUN" ); displayHash( "/TLBID" ); displayHash( "/TLBOUT" ); + displayHash( "/TSAWARE" ); displayHash( "/VERBOSE" ); displayHash( "/VERSION" ); + displayHash( "/VXD" ); displayHash( "/WS " ); +#endif +#if 0 + // Sub options + displayHash( "UNLOAD" ); displayHash( "NOBIND" ); displayHash( "no" ); displayHash( "NOSTATUS" ); displayHash( "STATUS" ); + displayHash( "AM33" ); displayHash( "ARM" ); displayHash( "CEE" ); displayHash( "IA64" ); displayHash( "X86" ); displayHash( "M32R" ); + displayHash( "MIPS" ); displayHash( "MIPS16" ); displayHash( "MIPSFPU" ); displayHash( "MIPSFPU16" ); displayHash( "MIPSR41XX" ); displayHash( "PPC" ); + displayHash( "SH3" ); displayHash( "SH4" ); displayHash( "SH5" ); displayHash( "THUMB" ); displayHash( "TRICORE" ); displayHash( "EXPORTS" ); + displayHash( "LINES" ); displayHash( "REF" ); displayHash( "NOREF" ); displayHash( "ICF" ); displayHash( "WIN98" ); displayHash( "NOWIN98" ); + displayHash( "CONSOLE" ); displayHash( "EFI_APPLICATION" ); displayHash( "EFI_BOOT_SERVICE_DRIVER" ); displayHash( "EFI_ROM" ); displayHash( "EFI_RUNTIME_DRIVER" ); displayHash( "NATIVE" ); + displayHash( "POSIX" ); displayHash( "WINDOWS" ); displayHash( "WINDOWSCE" ); displayHash( "NET" ); displayHash( "CD" ); displayHash( "NO" ); +#endif + + switch ( elfHash(option) ) { + case 0x3360dbe: // /ALIGN[:number] + case 0x1485c34: // /ALLOWBIND[:NO] + case 0x6b21972: // /DEFAULTLIB:library + case 0x396ea92: // /DRIVER[:UPONLY | :WDM] + case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] + case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] + case 0x33aec94: // /FIXED[:NO] + case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] + case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] + case 0x0348992: // /STUB:filename + case 0x0034bc4: // /VXD + case 0x0034c50: // /WS + AdditionalOptions += option; + break; + case 0x679c075: // /ASSEMBLYMODULE:filename + AddModuleNamesToAssembly += option+15; + break; + case 0x062d065: // /ASSEMBLYRESOURCE:filename + LinkToManagedResourceFile = option+18; + break; + case 0x0336675: // /BASE:{address | @filename,key} + // Do we need to do a manual lookup when '@filename,key'? + // Seems BaseAddress only can contain the location... + // We don't use it in Qt, so keep it simple for now + BaseAddress = option+6; + break; + case 0x3389797: // /DEBUG + GenerateDebugInformation = _True; + break; + case 0x0033896: // /DEF:filename + ModuleDefinitionFile = option+5; + break; + case 0x338a069: // /DELAY:{UNLOAD | NOBIND} + // MS documentation does not specify what to do with + // this option, so we'll put it in AdditionalOptions + AdditionalOptions += option; + break; + case 0x06f4bf4: // /DELAYLOAD:dllname + DelayLoadDLLs += option+11; + break; + // case 0x003390c: // /DLL + // This option is not used for vcproj files + // break; + case 0x33a3979: // /ENTRY:function + EntryPointSymbol = option+7; + break; + case 0x033c960: // /HEAP:reserve[,commit] + { + QStringList both = QStringList::split( ",", option+6 ); + HeapReserveSize = both[0].toLong(); + if ( both.count() == 2 ) + HeapCommitSize = both[1].toLong(); + } + break; + case 0x3d91494: // /IDLOUT:[path\]filename + MergedIDLBaseFileName = option+8; + break; + case 0x345a04c: // /IGNOREIDL + IgnoreEmbeddedIDL = _True; + break; + case 0x3e250e2: // /IMPLIB:filename + ImportLibrary = option+8; + break; + case 0xe281ab5: // /INCLUDE:symbol + ForceSymbolReferences += option+9; + break; + case 0xb28103c: // /INCREMENTAL[:no] + if ( *(option+12) == ':' && + *(option+13) == 'n' ) + LinkIncremental = linkIncrementalNo; + else + LinkIncremental = linkIncrementalYes; + break; + case 0x26e4675: // /LARGEADDRESSAWARE[:no] + if ( *(option+18) == ':' && + *(option+19) == 'n' ) + LargeAddressAware = addrAwareNoLarge; + else + LargeAddressAware = addrAwareLarge; + break; + case 0x0d745c8: // /LIBPATH:dir + AdditionalLibraryDirectories += option+9; + break; + case 0x0341877: // /LTCG[:NOSTATUS|:STATUS] + config->WholeProgramOptimization = _True; + LinkTimeCodeGeneration = _True; + if ( *(option+5) == ':' && + *(option+6) == 'S' ) + ShowProgress = linkProgressAll; + break; + case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE} + switch ( elfHash(option+9) ) { + // Very limited documentation on all options but X86, + // so we put the others in AdditionalOptions... + case 0x0046063: // AM33 + case 0x000466d: // ARM + case 0x0004795: // CEE + case 0x004d494: // IA64 + case 0x0050672: // M32R + case 0x0051e53: // MIPS + case 0x51e5646: // MIPS16 + case 0x1e57b05: // MIPSFPU + case 0x57b09a6: // MIPSFPU16 + case 0x5852738: // MIPSR41XX + case 0x0005543: // PPC + case 0x00057b3: // SH3 + case 0x00057b4: // SH4 + case 0x00057b5: // SH5 + case 0x058da12: // THUMB + case 0x96d8435: // TRICORE + AdditionalOptions += option; + break; + case 0x0005bb6: // X86 + TargetMachine = machineX86; + break; + default: + return FALSE; + } + break; + case 0x0034160: // /MAP[:filename] + GenerateMapFile = _True; + MapFileName = option+5; + break; + case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES} + if ( *(option+9) == 'E' ) + MapExports = _True; + else if ( *(option+9) == 'L' ) + MapLines = _True; + break; + case 0x341a6b5: // /MERGE:from=to + MergeSections = option+7; + break; + case 0x0341d8c: // /MIDL:@file + MidlCommandFile = option+7; + break; + case 0x84e2679: // /NOASSEMBLY + TurnOffAssemblyGeneration = _True; + break; + case 0x2b21942: // /NODEFAULTLIB[:library] + if ( *(option+13) == '\0' ) + IgnoreAllDefaultLibraries = _True; + else + IgnoreDefaultLibraryNames += option+14; + break; + case 0x33a3a39: // /NOENTRY + ResourceOnlyDLL = _True; + break; + case 0x434138f: // /NOLOGO + SuppressStartupBanner = _True; + break; + case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} + { + char third = *(option+7); + switch ( third ) { + case 'F': // REF + if ( *(option+5) == 'R' ) { + OptimizeReferences = optReferences; + } else { // ICF[=iterations] + EnableCOMDATFolding = optFolding; + // [=iterations] case is not documented + } + break; + case 'R': // NOREF + OptimizeReferences = optNoReferences; + break; + case 'I': // NOICF + EnableCOMDATFolding = optNoFolding; + break; + case 'N': // WIN98 + OptimizeForWindows98 = optWin98Yes; + break; + case 'W': // NOWIN98 + OptimizeForWindows98 = optWin98No; + break; + default: + return FALSE; + } + } + break; + case 0x34468a2: // /ORDER:@filename + FunctionOrder = option+8; + break; + case 0x00344a4: // /OUT:filename + OutputFile = option+5; + break; + case 0x0034482: // /PDB:filename + ProgramDatabaseFile = option+5; + break; + case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name + StripPrivateSymbols = option+13; + break; + case 0x6a09535: // /RELEASE + SetChecksum = _True; + break; + case 0x348857b: // /STACK:reserve[,commit] + { + QStringList both = QStringList::split( ",", option+7 ); + StackReserveSize = both[0].toLong(); + if ( both.count() == 2 ) + StackCommitSize = both[1].toLong(); + } + break; + case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]] + { + // Split up in subsystem, and version number + QStringList both = QStringList::split( ",", option+11 ); + switch ( elfHash(both[0].latin1()) ) { + case 0x8438445: // CONSOLE + SubSystem = subSystemConsole; + break; + case 0xbe29493: // WINDOWS + SubSystem = subSystemWindows; + break; + // The following are undocumented, so add them to AdditionalOptions + case 0x240949e: // EFI_APPLICATION + case 0xe617652: // EFI_BOOT_SERVICE_DRIVER + case 0x9af477d: // EFI_ROM + case 0xd34df42: // EFI_RUNTIME_DRIVER + case 0x5268ea5: // NATIVE + case 0x05547e8: // POSIX + case 0x2949c95: // WINDOWSCE + AdditionalOptions += option; + break; + default: + return FALSE; + } + } + break; + case 0x8b654de: // /SWAPRUN:{NET | CD} + if ( *(option+9) == 'N' ) + SwapRunFromNet = _True; + else if ( *(option+9) == 'C' ) + SwapRunFromCD = _True; + else + return FALSE; + break; + case 0x34906d4: // /TLBID:id + TypeLibraryResourceID = QString( option+7 ).toLong(); + break; + case 0x4907494: // /TLBOUT:[path\]filename + TypeLibraryFile = option+8; + break; + case 0x976b525: // /TSAWARE[:NO] + if ( *(option+8) == ':' ) + TerminalServerAware = termSvrAwareNo; + else + TerminalServerAware = termSvrAwareYes; + break; + case 0xaa67735: // /VERBOSE[:lib] + if ( *(option+9) == ':' ) { + ShowProgress = linkProgressLibs; + AdditionalOptions += option; + } else { + ShowProgress = linkProgressAll; + } + break; + case 0xaa77f7e: // /VERSION:major[.minor] + Version = option+9; + break; + default: + return FALSE; + } + return TRUE; +} + +// VCMIDLTool ------------------------------------------------------- +VCMIDLTool::VCMIDLTool() + : DefaultCharType( midlCharUnsigned ), + EnableErrorChecks( midlDisableAll ), + ErrorCheckAllocations( unset ), + ErrorCheckBounds( unset ), + ErrorCheckEnumRange( unset ), + ErrorCheckRefPointers( unset ), + ErrorCheckStubData( unset ), + GenerateStublessProxies( unset ), + GenerateTypeLibrary( unset ), + IgnoreStandardIncludePath( unset ), + MkTypLibCompatible( unset ), + StructMemberAlignment( midlAlignNotSet ), + SuppressStartupBanner( unset ), + TargetEnvironment( midlTargetNotSet ), + ValidateParameters( unset ), + WarnAsError( unset ), + WarningLevel( midlWarningLevel_0 ) +{ +} + +QTextStream &operator<<( QTextStream &strm, const VCMIDLTool &tool ) +{ + strm << _begTool3; + strm << _VCMIDLToolName; + strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _CPreprocessOptions, tool.CPreprocessOptions ); + strm << EPair( _DefaultCharType, tool.DefaultCharType ); + strm << SPair( _DLLDataFileName, tool.DLLDataFileName ); + strm << EPair( _EnableErrorChecks, tool.EnableErrorChecks ); + strm << TPair( _ErrorCheckAllocations, tool.ErrorCheckAllocations ); + strm << TPair( _ErrorCheckBounds, tool.ErrorCheckBounds ); + strm << TPair( _ErrorCheckEnumRange, tool.ErrorCheckEnumRange ); + strm << TPair( _ErrorCheckRefPointers, tool.ErrorCheckRefPointers ); + strm << TPair( _ErrorCheckStubData, tool.ErrorCheckStubData ); + strm << XPair( _FullIncludePath, tool.FullIncludePath ); + strm << TPair( _GenerateStublessProxies, tool.GenerateStublessProxies ); + strm << TPair( _GenerateTypeLibrary, tool.GenerateTypeLibrary ); + strm << SPair( _HeaderFileName, tool.HeaderFileName ); + strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); + strm << SPair( _InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName ); + strm << TPair( _MkTypLibCompatible, tool.MkTypLibCompatible ); + strm << SPair( _OutputDirectory4, tool.OutputDirectory ); + strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); + strm << SPair( _ProxyFileName, tool.ProxyFileName ); + strm << SPair( _RedirectOutputAndErrors, tool.RedirectOutputAndErrors ); + if ( tool.StructMemberAlignment != midlAlignNotSet) strm << EPair( _StructMemberAlignment, tool.StructMemberAlignment ); + strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); + if ( tool.TargetEnvironment != midlTargetNotSet ) strm << EPair( _TargetEnvironment, tool.TargetEnvironment ); + strm << SPair( _TypeLibraryName, tool.TypeLibraryName ); + strm << XPair( _UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions ); + strm << TPair( _ValidateParameters, tool.ValidateParameters ); + strm << TPair( _WarnAsError, tool.WarnAsError ); + strm << EPair( _WarningLevel, tool.WarningLevel ); + strm << "/>"; + return strm; +} + +bool VCMIDLTool::parseOption( const char* option ) +{ +#if 0 + displayHash( "/D name[=def]" ); displayHash( "/I directory-list" ); displayHash( "/Oi" ); + displayHash( "/Oic" ); displayHash( "/Oicf" ); displayHash( "/Oif" ); displayHash( "/Os" ); + displayHash( "/U name" ); displayHash( "/WX" ); displayHash( "/W{0|1|2|3|4}" ); + displayHash( "/Zp {N}" ); displayHash( "/Zs" ); displayHash( "/acf filename" ); + displayHash( "/align {N}" ); displayHash( "/app_config" ); displayHash( "/c_ext" ); + displayHash( "/char ascii7" ); displayHash( "/char signed" ); displayHash( "/char unsigned" ); + displayHash( "/client none" ); displayHash( "/client stub" ); displayHash( "/confirm" ); + displayHash( "/cpp_cmd cmd_line" ); displayHash( "/cpp_opt options" ); + displayHash( "/cstub filename" ); displayHash( "/dlldata filename" ); displayHash( "/env win32" ); + displayHash( "/env win64" ); displayHash( "/error all" ); displayHash( "/error allocation" ); + displayHash( "/error bounds_check" ); displayHash( "/error enum" ); displayHash( "/error none" ); + displayHash( "/error ref" ); displayHash( "/error stub_data" ); displayHash( "/h filename" ); + displayHash( "/header filename" ); displayHash( "/iid filename" ); displayHash( "/lcid" ); + displayHash( "/mktyplib203" ); displayHash( "/ms_ext" ); displayHash( "/ms_union" ); + displayHash( "/msc_ver <nnnn>" ); displayHash( "/newtlb" ); displayHash( "/no_cpp" ); + displayHash( "/no_def_idir" ); displayHash( "/no_default_epv" ); displayHash( "/no_format_opt" ); + displayHash( "/no_warn" ); displayHash( "/nocpp" ); displayHash( "/nologo" ); displayHash( "/notlb" ); + displayHash( "/o filename" ); displayHash( "/oldnames" ); displayHash( "/oldtlb" ); + displayHash( "/osf" ); displayHash( "/out directory" ); displayHash( "/pack {N}" ); + displayHash( "/prefix all" ); displayHash( "/prefix client" ); displayHash( "/prefix server" ); + displayHash( "/prefix switch" ); displayHash( "/protocol all" ); displayHash( "/protocol dce" ); + displayHash( "/protocol ndr64" ); displayHash( "/proxy filename" ); displayHash( "/robust" ); + displayHash( "/rpcss" ); displayHash( "/savePP" ); displayHash( "/server none" ); + displayHash( "/server stub" ); displayHash( "/sstub filename" ); displayHash( "/syntax_check" ); + displayHash( "/target {system}" ); displayHash( "/tlb filename" ); displayHash( "/use_epv" ); + displayHash( "/win32" ); displayHash( "/win64" ); +#endif + int offset = 0; + switch( elfHash(option) ) { + case 0x0000334: // /D name[=def] + PreprocessorDefinitions += option+3; + break; + case 0x0000339: // /I directory-list + AdditionalIncludeDirectories += option+3; + break; + case 0x0345f96: // /Oicf + case 0x00345f6: // /Oif + GenerateStublessProxies = _True; + break; + case 0x0000345: // /U name + UndefinePreprocessorDefinitions += option+3; + break; + case 0x00034c8: // /WX + WarnAsError = _True; + break; + case 0x3582fde: // /align {N} + offset = 3; // Fallthrough + case 0x0003510: // /Zp {N} + switch ( *(option+offset+4) ) { + case '1': + StructMemberAlignment = ( *(option+offset+5) == '\0' ) ? midlAlignSingleByte : midlAlignSixteenBytes; + break; + case '2': + StructMemberAlignment = midlAlignTwoBytes; + break; + case '4': + StructMemberAlignment = midlAlignFourBytes; + break; + case '8': + StructMemberAlignment = midlAlignEightBytes; + break; + default: + return FALSE; + } + break; + case 0x0359e82: // /char {ascii7|signed|unsigned} + switch( *(option+6) ) { + case 'a': + DefaultCharType = midlCharAscii7; + break; + case 's': + DefaultCharType = midlCharSigned; + break; + case 'u': + DefaultCharType = midlCharUnsigned; + break; + default: + return FALSE; + } + break; + case 0xa766524: // /cpp_opt options + CPreprocessOptions += option+9; + break; + case 0xb32abf1: // /dlldata filename + DLLDataFileName = option + 9; + break; + case 0x0035c56: // /env {win32|win64} + TargetEnvironment = ( *(option+8) == '6' ) ? midlTargetWin64 : midlTargetWin32; + break; + case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data} + EnableErrorChecks = midlEnableCustom; + switch ( *(option+7) ) { + case 'a': + if ( *(option+10) == '\0' ) + EnableErrorChecks = midlEnableAll; + else + ErrorCheckAllocations = _True; + break; + case 'b': + ErrorCheckBounds = _True; + break; + case 'e': + ErrorCheckEnumRange = _True; + break; + case 'n': + EnableErrorChecks = midlDisableAll; + break; + case 'r': + break; + ErrorCheckRefPointers = _True; + case 's': + break; + ErrorCheckStubData = _True; + default: + return FALSE; + } + break; + case 0x5eb7af2: // /header filename + offset = 5; + case 0x0000358: // /h filename + HeaderFileName = option + offset + 3; + break; + case 0x0035ff4: // /iid filename + InterfaceIdentifierFileName = option+5; + break; + case 0x64b7933: // /mktyplib203 + MkTypLibCompatible = _True; + break; + case 0x8e0b0a2: // /no_def_idir + IgnoreStandardIncludePath = _True; + break; + case 0x65635ef: // /nologo + SuppressStartupBanner = _True; + break; + case 0x3656b22: // /notlb + GenerateTypeLibrary = _True; + break; + case 0x000035f: // /o filename + RedirectOutputAndErrors = option+3; + break; + case 0x00366c4: // /out directory + OutputDirectory = option+5; + break; + case 0x36796f9: // /proxy filename + ProxyFileName = option+7; + break; + case 0x6959c94: // /robust + ValidateParameters = _True; + break; + case 0x6a88df4: // /target {system} + if ( *(option+11) == '6' ) + TargetEnvironment = midlTargetWin64; + else + TargetEnvironment = midlTargetWin32; + break; + case 0x0036b22: // /tlb filename + TypeLibraryName = option+5; + break; + case 0x36e0162: // /win32 + TargetEnvironment = midlTargetWin32; + break; + case 0x36e0194: // /win64 + TargetEnvironment = midlTargetWin64; + break; + case 0x0003459: // /Oi + case 0x00345f3: // /Oic + case 0x0003463: // /Os + case 0x0003513: // /Zs + case 0x0035796: // /acf filename + case 0x5b1cb97: // /app_config + case 0x3595cf4: // /c_ext + case 0x5a2fc64: // /client {none|stub} + case 0xa64d3dd: // /confirm + case 0xa765b64: // /cpp_cmd cmd_line + case 0x35aabb2: // /cstub filename + case 0x03629f4: // /lcid + case 0x6495cc4: // /ms_ext + case 0x96c7a1e: // /ms_union + case 0x4996fa2: // /msc_ver <nnnn> + case 0x64ceb12: // /newtlb + case 0x6555a40: // /no_cpp + case 0xf64d6a6: // /no_default_epv + case 0x6dd9384: // /no_format_opt + case 0x556dbee: // /no_warn + case 0x3655a70: // /nocpp + case 0x2b455a3: // /oldnames + case 0x662bb12: // /oldtlb + case 0x0036696: // /osf + case 0x036679b: // /pack {N} + case 0x678bd38: // /prefix {all|client|server|switch} + case 0x96b702c: // /protocol {all|dce|ndr64} + case 0x3696aa3: // /rpcss + case 0x698ca60: // /savePP + case 0x69c9cf2: // /server {none|stub} + case 0x36aabb2: // /sstub filename + case 0xce9b12b: // /syntax_check + case 0xc9b5f16: // /use_epv + AdditionalOptions += option; + break; + default: + // /W{0|1|2|3|4} case + if ( *(option+1) == 'W' ) { + switch ( *(option+2) ) { + case '0': + WarningLevel = midlWarningLevel_0; + break; + case '1': + WarningLevel = midlWarningLevel_1; + break; + case '2': + WarningLevel = midlWarningLevel_2; + break; + case '3': + WarningLevel = midlWarningLevel_3; + break; + case '4': + WarningLevel = midlWarningLevel_4; + break; + default: + return FALSE; + } + } + break; + } + return TRUE; +} + +// VCLibrarianTool -------------------------------------------------- +VCLibrarianTool::VCLibrarianTool() + : IgnoreAllDefaultLibraries( unset ), + SuppressStartupBanner( _True ) +{ +} + +QTextStream &operator<<( QTextStream &strm, const VCLibrarianTool &tool ) +{ + strm << _begTool3; + strm << SPair( _ToolName, QString( "VCLibrarianTool" ) ); + strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies ); + strm << XPair( _AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _ExportNamedFunctions, tool.ExportNamedFunctions ); + strm << XPair( _ForceSymbolReferences, tool.ForceSymbolReferences ); + strm << TPair( _IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries ); + strm << XPair( _IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames ); + strm << SPair( _ModuleDefinitionFile, tool.ModuleDefinitionFile ); + strm << SPair( _OutputFile, tool.OutputFile ); + strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); + strm << "/>"; + return strm; +} + +// VCCustomBuildTool ------------------------------------------------ +VCCustomBuildTool::VCCustomBuildTool() +{ + ToolName = "VCCustomBuildTool"; +} + +QTextStream &operator<<( QTextStream &strm, const VCCustomBuildTool &tool ) +{ + strm << _begTool3; + strm << SPair( _ToolName, tool.ToolName ); + strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies, ";" ); + strm << SPair( _CommandLine4, tool.CommandLine ); + strm << SPair( _Description4, tool.Description ); + strm << SPair( _Outputs4, tool.Outputs ); + strm << SPair( _ToolPath, tool.ToolPath ); + strm << "/>"; + return strm; +} + +// VCResourceCompilerTool ------------------------------------------- +VCResourceCompilerTool::VCResourceCompilerTool() + : Culture( rcUseDefault ), + IgnoreStandardIncludePath( unset ), + ShowProgress( linkProgressNotSet ) +{ + PreprocessorDefinitions = "NDEBUG"; +} + +QTextStream &operator<<( QTextStream &strm, const VCResourceCompilerTool &tool ) +{ + strm << _begTool3; + strm << _VCResourceCompilerToolName; + strm << SPair( _ToolPath, tool.ToolPath ); + strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + if ( tool.Culture != rcUseDefault ) strm << EPair( _Culture, tool.Culture ); + strm << XPair( _FullIncludePath, tool.FullIncludePath ); + strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); + strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); + strm << SPair( _ResourceOutputFileName, tool.ResourceOutputFileName ); + if ( tool.ShowProgress != linkProgressNotSet ) strm << EPair( _ShowProgress, tool.ShowProgress ); + strm << "/>"; + return strm; +} + +// VCEventTool ------------------------------------------------- +QTextStream &operator<<( QTextStream &strm, const VCEventTool &tool ) +{ + strm << _begTool3; + strm << SPair( _ToolName, tool.ToolName ); + strm << SPair( _ToolPath, tool.ToolPath ); + strm << SPair( _CommandLine4, tool.CommandLine ); + strm << SPair( _Description4, tool.Description ); + strm << TPair( _ExcludedFromBuild, tool.ExcludedFromBuild ); + strm << "/>"; + return strm; +} + +// VCPostBuildEventTool --------------------------------------------- +VCPostBuildEventTool::VCPostBuildEventTool() +{ + ToolName = "VCPostBuildEventTool"; +} + +// VCPreBuildEventTool ---------------------------------------------- +VCPreBuildEventTool::VCPreBuildEventTool() +{ + ToolName = "VCPreBuildEventTool"; +} + +// VCPreLinkEventTool ----------------------------------------------- +VCPreLinkEventTool::VCPreLinkEventTool() +{ + ToolName = "VCPreLinkEventTool"; +} + +// VCConfiguration -------------------------------------------------- + +VCConfiguration::VCConfiguration() + : ATLMinimizesCRunTimeLibraryUsage( unset ), + BuildBrowserInformation( unset ), + CharacterSet( charSetNotSet ), + ConfigurationType( typeApplication ), + RegisterOutput( unset ), + UseOfATL( useATLNotSet ), + UseOfMfc( useMfcStdWin ), + WholeProgramOptimization( unset ) +{ + compiler.config = this; + linker.config = this; + idl.config = this; +} + +QTextStream &operator<<( QTextStream &strm, const VCConfiguration &tool ) +{ + strm << _begConfiguration; + strm << SPair( _Name3, tool.Name ); + strm << SPair( _OutputDirectory3, tool.OutputDirectory ); + strm << TPair( _ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage ); + strm << TPair( _BuildBrowserInformation, tool.BuildBrowserInformation ); + if ( tool.CharacterSet != charSetNotSet) strm << EPair( _CharacterSet, tool.CharacterSet ); + strm << EPair( _ConfigurationType, tool.ConfigurationType ); + strm << SPair( _DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean ); + strm << SPair( _ImportLibrary, tool.ImportLibrary ); + strm << SPair( _IntermediateDirectory, tool.IntermediateDirectory ); + strm << SPair( _PrimaryOutput, tool.PrimaryOutput ); + strm << SPair( _ProgramDatabase, tool.ProgramDatabase ); + strm << TPair( _RegisterOutput, tool.RegisterOutput ); + if ( tool.UseOfATL != useATLNotSet) strm << EPair( _UseOfATL, tool.UseOfATL ); + strm << EPair( _UseOfMfc, tool.UseOfMfc ); + strm << TPair( _WholeProgramOptimization, tool.WholeProgramOptimization ); + strm << ">"; + strm << tool.compiler; + strm << tool.custom; + if ( tool.ConfigurationType == typeStaticLibrary ) + strm << tool.librarian; + else + strm << tool.linker; + strm << tool.idl; + strm << tool.postBuild; + strm << tool.preBuild; + strm << tool.preLink; + strm << tool.resource; + strm << _endConfiguration; + return strm; +} +// VCFilter --------------------------------------------------------- +VCFilter::VCFilter() + : ParseFiles( unset ) +{ +} + +void VCFilter::generateMOC( QTextStream &strm, QString str ) const +{ + QString mocOutput = Project->findMocDestination( str ); + QString mocApp = Project->var( "QMAKE_MOC" ); + + if( mocOutput.isEmpty() ) { + // In specialcases we DO moc .cpp files + // when the result is an .moc file + if ( !str.endsWith(".moc") ) + return; + mocOutput = str; + str = Project->findMocSource( mocOutput ); + } + + strm << _begFileConfiguration; + strm << _Name5; + strm << Config->Name; + strm << "\">"; + strm << _begTool5; + strm << _VCCustomBuildTool; + strm << _Description6; + strm << "Moc'ing " << str << "...\""; + strm << _CommandLine6; + strm << mocApp; + strm << " " << str << " -o " << mocOutput << "\""; + strm << _AdditionalDependencies6; + strm << mocApp << "\""; + strm << _Outputs6; + strm << mocOutput << "\""; + strm << "/>"; + strm << _endFileConfiguration; +} + +void VCFilter::generateUIC( QTextStream &strm, const QString& str ) const +{ + QString uicApp = Project->var("QMAKE_UIC"); + QString mocApp = Project->var( "QMAKE_MOC" ); + QString fname = str.section( '\\', -1 ); + QString mocDir = Project->var( "MOC_DIR" ); + int dot = fname.findRev( '.' ); + if( dot != -1 ) + fname.truncate( dot ); + + int slash = str.findRev( '\\' ); + QString pname = ( slash != -1 ) ? str.left( slash+1 ) : QString(".\\"); + + strm << _begFileConfiguration; + strm << _Name5; + strm << Config->Name; + strm << "\">"; + strm << _begTool5; + strm << _VCCustomBuildTool; + strm << _Description6; + strm << "Uic'ing " << str << "...\""; + strm << _CommandLine6; + strm << uicApp << " " << str << " -o " << pname << fname << ".h && "; // Create .h from .ui file + strm << uicApp << " " << str << " -i " << fname << ".h -o " << pname << fname << ".cpp && "; // Create .cpp from .ui file + strm << mocApp << " " << pname << fname << ".h -o " << mocDir << "moc_" << fname << ".cpp\""; + strm << _AdditionalDependencies6; + strm << mocApp << ";" << uicApp << "\""; + strm << _Outputs6; + strm << pname << fname << ".h;" << pname << fname << ".cpp;" << mocDir << "moc_" << fname << ".cpp\""; + strm << "/>"; + strm << _endFileConfiguration; +} + +QTextStream &operator<<( QTextStream &strm, const VCFilter &tool ) +{ + if ( tool.Files.count() == 0 ) + return strm; + + strm << _begFilter; + strm << SPair( _Name3, tool.Name ); + strm << TPair( _ParseFiles, tool.ParseFiles ); + strm << SPair( _Filter, tool.Filter ); + strm << ">"; + for ( QStringList::ConstIterator it = tool.Files.begin(); it != tool.Files.end(); ++it ) { + strm << _begFile; + strm << SPair( _RelativePath, *it ); + strm << ">"; + if ( tool.CustomBuild == moc ) + tool.generateMOC( strm, *it ); + else if ( tool.CustomBuild == uic ) + tool.generateUIC( strm, *it ); + strm << _endFile; + } + + strm << _endFilter; + return strm; +} + +// VCProject -------------------------------------------------------- +VCProject::VCProject() +{ + QUuid uniqueId; +#if defined(Q_WS_WIN32) + GUID guid; + HRESULT h = CoCreateGuid( &guid ); + if ( h == S_OK ) + uniqueId = QUuid( guid ); + ProjectGUID = uniqueId.toString(); +#else + // Qt doesn't support GUID on other platforms yet + ProjectGUID = ""; +#endif +} + +QTextStream &operator<<( QTextStream &strm, const VCProject &tool ) +{ + strm << _xmlInit; + strm << _begVisualStudioProject; + strm << _ProjectType; + strm << SPair( _Version1, tool.Version ); + strm << SPair( _Name1, tool.Name ); + strm << SPair( _ProjectGUID, tool.ProjectGUID ); + strm << SPair( _SccProjectName, tool.SccProjectName ); + strm << SPair( _SccLocalPath, tool.SccLocalPath ); + strm << ">"; + strm << _begPlatforms; + strm << _begPlatform; + strm << SPair( _Name3, tool.PlatformName ); + strm << "/>"; + strm << _endPlatforms; + strm << _begConfigurations; + strm << tool.Configuration; + strm << _endConfigurations; + strm << _begFiles; + strm << tool.SourceFiles; + strm << tool.HeaderFiles; + strm << tool.MOCFiles; + strm << tool.UICFiles; + strm << tool.FormFiles; + strm << tool.TranslationFiles; + strm << tool.LexYaccFiles; + strm << tool.ResourceFiles; + strm << _endFiles; + strm << _begGlobals; + strm << _endGlobals; + strm << _endVisualStudioProject; + return strm; +} diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h new file mode 100644 index 0000000..2d09280 --- a/dev/null +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -0,0 +1,775 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Copyright (C) 2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __MSVC_OBJECTMODEL_H__ +#define __MSVC_OBJECTMODEL_H__ + +#include "project.h" +#include <qstring.h> +#include <qstringlist.h> + +/* + This Object model is of course VERY simplyfied, + and does not actually follow the original MSVC + object model. However, it fulfilles the basic + needs for qmake +*/ + +/* + If a triState value is 'unset' then the + corresponding property is not in the output, + forcing the tool to utilize default values. + False/True values will be in the output... +*/ +enum customBuildCheck { + none, + moc, + uic, + lexyacc +}; +enum triState { + unset = -1, + _False = 0, + _True = 1 +}; +enum addressAwarenessType { + addrAwareDefault, + addrAwareNoLarge, + addrAwareLarge +}; +enum asmListingOption { + asmListingNone, + asmListingAssemblyOnly, + asmListingAsmMachineSrc, + asmListingAsmMachine, + asmListingAsmSrc +}; +enum basicRuntimeCheckOption { + runtimeBasicCheckNone, + runtimeCheckStackFrame, + runtimeCheckUninitVariables, + runtimeBasicCheckAll +}; +enum browseInfoOption { + brInfoNone, + brAllInfo, + brNoLocalSymbols +}; +enum callingConventionOption { + callConventionDefault = -1, + callConventionCDecl, + callConventionFastCall, + callConventionStdCall +}; +enum charSet { + charSetNotSet, + charSetUnicode, + charSetMBCS +}; +enum compileAsManagedOptions { + managedDefault = -1, + managedAssembly = 2 +}; +enum CompileAsOptions{ + compileAsDefault, + compileAsC, + compileAsCPlusPlus +}; +enum ConfigurationTypes { + typeUnknown = 0, + typeApplication = 1, + typeDynamicLibrary = 2, + typeStaticLibrary = 4, + typeGeneric = 10 +}; +enum debugOption { + debugDisabled, + debugOldStyleInfo, + debugLineInfoOnly, + debugEnabled, + debugEditAndContinue +}; +enum eAppProtectionOption { + eAppProtectUnchanged, + eAppProtectLow, + eAppProtectMedium, + eAppProtectHigh +}; +enum enumResourceLangID { + rcUseDefault = 0, + rcAfrikaans = 1078, + rcAlbanian = 1052, + rcArabicAlgeria = 5121, + rcArabicBahrain = 15361, + rcArabicEgypt = 3073, + rcArabicIraq = 2049, + rcArabicJordan = 11265, + rcArabicKuwait = 13313, + rcArabicLebanon = 12289, + rcArabicLibya = 4097, + rcArabicMorocco = 6145, + rcArabicOman = 8193, + rcArabicQatar = 16385, + rcArabicSaudi = 1025, + rcArabicSyria = 10241, + rcArabicTunisia = 7169, + rcArabicUnitedArabEmirates = 14337, + rcArabicYemen = 9217, + rcBasque = 1069, + rcBulgarian = 1026, + rcByelorussian = 1059, + rcCatalan = 1027, + rcChineseHongKong = 3076, + rcChinesePRC = 2052, + rcChineseSingapore = 4100, + rcChineseTaiwan = 1028, + rcCroatian = 1050, + rcCzech = 1029, + rcDanish = 1030, + rcDutchBelgium = 2067, + rcDutchStandard = 1043, + rcEnglishAustralia = 3081, + rcEnglishBritain = 2057, + rcEnglishCanada = 4105, + RcEnglishCaribbean = 9225, + rcEnglishIreland = 6153, + rcEnglishJamaica = 8201, + rcEnglishNewZealand = 5129, + rcEnglishSouthAfrica = 7177, + rcEnglishUS = 1033, + rcEstonian = 1061, + rcFarsi = 1065, + rcFinnish = 1035, + rcFrenchBelgium = 2060, + rcFrenchCanada = 3084, + rcFrenchLuxembourg = 5132, + rcFrenchStandard = 1036, + rcFrenchSwitzerland = 4108, + rcGermanAustria = 3079, + rcGermanLichtenstein = 5127, + rcGermanLuxembourg = 4103, + rcGermanStandard = 1031, + rcGermanSwitzerland = 2055, + rcGreek = 1032, + rcHebrew = 1037, + rcHungarian = 1038, + rcIcelandic = 1039, + rcIndonesian = 1057, + rcItalianStandard = 1040, + rcItalianSwitzerland = 2064, + rcJapanese = 1041, + rcKorean = 1042, + rcKoreanJohab = 2066, + rcLatvian = 1062, + rcLithuanian = 1063, + rcNorwegianBokmal = 1044, + rcNorwegianNynorsk = 2068, + rcPolish = 1045, + rcPortugueseBrazilian = 1046, + rcPortugueseStandard = 2070, + rcRomanian = 1048, + rcRussian = 1049, + rcSerbian = 2074, + rcSlovak = 1051, + rcSpanishArgentina = 11274, + rcSpanishBolivia = 16394, + rcSpanishChile = 13322, + rcSpanishColombia = 9226, + rcSpanishCostaRica = 5130, + rcSpanishDominicanRepublic = 7178, + rcSpanishEcuador = 12298, + rcSpanishGuatemala = 4106, + rcSpanishMexico = 2058, + rcSpanishModern = 3082, + rcSpanishPanama = 6154, + rcSpanishParaguay = 15370, + rcSpanishPeru = 10250, + rcSpanishTraditional = 1034, + rcSpanishUruguay = 14346, + rcSpanishVenezuela = 8202, + rcSwedish = 1053, + rcThai = 1054, + rcTurkish = 1055, + rcUkrainian = 1058, + rcUrdu = 1056 +}; +enum enumSccEvent { + eProjectInScc, + ePreDirtyNotification +}; +enum favorSizeOrSpeedOption { + favorNone, + favorSpeed, + favorSize +}; +enum genProxyLanguage { + genProxyNative, + genProxyManaged +}; +enum inlineExpansionOption { + expandDisable, + expandOnlyInline, + expandAnySuitable +}; +enum linkIncrementalType { + linkIncrementalDefault, + linkIncrementalNo, + linkIncrementalYes +}; +enum linkProgressOption { + linkProgressNotSet, + linkProgressAll, + linkProgressLibs +}; +enum machineTypeOption { + machineNotSet, + machineX86 +}; +enum midlCharOption { + midlCharUnsigned, + midlCharSigned, + midlCharAscii7 +}; +enum midlErrorCheckOption { + midlEnableCustom, + midlDisableAll, + midlEnableAll +}; +enum midlStructMemberAlignOption { + midlAlignNotSet, + midlAlignSingleByte, + midlAlignTwoBytes, + midlAlignFourBytes, + midlAlignEightBytes, + midlAlignSixteenBytes +}; +enum midlTargetEnvironment { + midlTargetNotSet, + midlTargetWin32, + midlTargetWin64 +}; +enum midlWarningLevelOption { + midlWarningLevel_0, + midlWarningLevel_1, + midlWarningLevel_2, + midlWarningLevel_3, + midlWarningLevel_4 +}; +enum optFoldingType { + optFoldingDefault, + optNoFolding, + optFolding +}; +enum optimizeOption { + optimizeDisabled, + optimizeMinSpace, + optimizeMaxSpeed, + optimizeFull, + optimizeCustom +}; +enum optRefType { + optReferencesDefault, + optNoReferences, + optReferences +}; +enum optWin98Type { + optWin98Default, + optWin98No, + optWin98Yes +}; +enum pchOption { + pchNone, + pchCreateUsingSpecific, + pchGenerateAuto, + pchUseUsingSpecific +}; +enum preprocessOption { + preprocessNo, + preprocessYes, + preprocessNoLineNumbers +}; +enum ProcessorOptimizeOption { + procOptimizeBlended, + procOptimizePentium, + procOptimizePentiumProAndAbove +}; +enum RemoteDebuggerType { + DbgLocal, + DbgRemote, + DbgRemoteTCPIP +}; +enum runtimeLibraryOption { + rtMultiThreaded, + rtMultiThreadedDebug, + rtMultiThreadedDLL, + rtMultiThreadedDebugDLL, + rtSingleThreaded, + rtSingleThreadedDebug +}; +enum structMemberAlignOption { + alignNotSet, + alignSingleByte, + alignTwoBytes, + alignFourBytes, + alignEightBytes, + alignSixteenBytes +}; +enum subSystemOption { + subSystemNotSet, + subSystemConsole, + subSystemWindows +}; +enum termSvrAwarenessType { + termSvrAwareDefault, + termSvrAwareNo, + termSvrAwareYes +}; +enum toolSetType { + toolSetUtility, + toolSetMakefile, + toolSetLinker, + toolSetLibrarian, + toolSetAll +}; +enum TypeOfDebugger { + DbgNativeOnly, + DbgManagedOnly, + DbgMixed, + DbgAuto +}; +enum useOfATL { + useATLNotSet, + useATLStatic, + useATLDynamic +}; +enum useOfMfc { + useMfcStdWin, + useMfcStatic, + useMfcDynamic +}; +enum warningLevelOption { + warningLevel_0, + warningLevel_1, + warningLevel_2, + warningLevel_3, + warningLevel_4 +}; + +class VCToolBase { +protected: + // Functions + VCToolBase(){}; + ~VCToolBase(){}; + virtual bool parseOption( const char* option ) = 0; +public: + bool parseOptions( QStringList& options ) { + bool result = TRUE; + for ( QStringList::ConstIterator it=options.begin(); (it!=options.end()) && result; it++ ) + result = parseOption( (*it).latin1() ); + return result; + } +}; + +class VCConfiguration; +class VCProject; + +class VCCLCompilerTool : public VCToolBase +{ +public: + // Functions + VCCLCompilerTool(); + ~VCCLCompilerTool(){}; + virtual bool parseOption( const char* option ); + + // Variables + QStringList AdditionalIncludeDirectories; + QStringList AdditionalOptions; + QStringList AdditionalUsingDirectories; + QString AssemblerListingLocation; + asmListingOption AssemblerOutput; + basicRuntimeCheckOption BasicRuntimeChecks; + browseInfoOption BrowseInformation; + QString BrowseInformationFile; + triState BufferSecurityCheck; + callingConventionOption CallingConvention; + CompileAsOptions CompileAs; + compileAsManagedOptions CompileAsManaged; + triState CompileOnly; + debugOption DebugInformationFormat; + triState DefaultCharIsUnsigned; + triState Detect64BitPortabilityProblems; + triState DisableLanguageExtensions; + QStringList DisableSpecificWarnings; + triState EnableFiberSafeOptimizations; + triState EnableFunctionLevelLinking; + triState EnableIntrinsicFunctions; + triState ExceptionHandling; + triState ExpandAttributedSource; + favorSizeOrSpeedOption FavorSizeOrSpeed; + triState ForceConformanceInForLoopScope; + QStringList ForcedIncludeFiles; + QStringList ForcedUsingFiles; + preprocessOption GeneratePreprocessedFile; + triState GlobalOptimizations; + triState IgnoreStandardIncludePath; + triState ImproveFloatingPointConsistency; + inlineExpansionOption InlineFunctionExpansion; + triState KeepComments; + triState MinimalRebuild; + QString ObjectFile; + triState OmitFramePointers; + optimizeOption Optimization; + ProcessorOptimizeOption OptimizeForProcessor; + triState OptimizeForWindowsApplication; + QString OutputFile; + QString PrecompiledHeaderFile; + QString PrecompiledHeaderThrough; + QStringList PreprocessorDefinitions; + QString ProgramDataBaseFileName; + runtimeLibraryOption RuntimeLibrary; + triState RuntimeTypeInfo; + triState ShowIncludes; + triState SmallerTypeCheck; + triState StringPooling; + structMemberAlignOption StructMemberAlignment; + triState SuppressStartupBanner; + triState TreatWChar_tAsBuiltInType; + triState TurnOffAssemblyGeneration; + triState UndefineAllPreprocessorDefinitions; + QStringList UndefinePreprocessorDefinitions; + pchOption UsePrecompiledHeader; + triState WarnAsError; + warningLevelOption WarningLevel; + triState WholeProgramOptimization; + VCConfiguration* config; +}; + +class VCLinkerTool : public VCToolBase +{ +public: + // Functions + VCLinkerTool(); + ~VCLinkerTool(){}; + virtual bool parseOption( const char* option ); + + // Variables + QStringList AdditionalDependencies; + QStringList AdditionalLibraryDirectories; + QStringList AdditionalOptions; + QStringList AddModuleNamesToAssembly; + QString BaseAddress; + QStringList DelayLoadDLLs; + optFoldingType EnableCOMDATFolding; + QString EntryPointSymbol; + QStringList ForceSymbolReferences; + QString FunctionOrder; + triState GenerateDebugInformation; + triState GenerateMapFile; + long HeapCommitSize; + long HeapReserveSize; + triState IgnoreAllDefaultLibraries; + QStringList IgnoreDefaultLibraryNames; + triState IgnoreEmbeddedIDL; + triState IgnoreImportLibrary; + QString ImportLibrary; + addressAwarenessType LargeAddressAware; + triState LinkDLL; + linkIncrementalType LinkIncremental; + triState LinkTimeCodeGeneration; + QString LinkToManagedResourceFile; + triState MapExports; + QString MapFileName; + triState MapLines; + QString MergedIDLBaseFileName; + QString MergeSections; // Should be list? + QString MidlCommandFile; + QString ModuleDefinitionFile; // Should be list? + optWin98Type OptimizeForWindows98; + optRefType OptimizeReferences; + QString OutputFile; + QString ProgramDatabaseFile; + triState RegisterOutput; + triState ResourceOnlyDLL; + triState SetChecksum; + linkProgressOption ShowProgress; + long StackCommitSize; + long StackReserveSize; + QString StripPrivateSymbols; // Should be list? + subSystemOption SubSystem; + triState SupportUnloadOfDelayLoadedDLL; + triState SuppressStartupBanner; + triState SwapRunFromCD; + triState SwapRunFromNet; + machineTypeOption TargetMachine; + termSvrAwarenessType TerminalServerAware; + triState TurnOffAssemblyGeneration; + QString TypeLibraryFile; + long TypeLibraryResourceID; + QString Version; + VCConfiguration* config; +}; + +class VCMIDLTool : public VCToolBase +{ +public: + // Functions + VCMIDLTool(); + ~VCMIDLTool(){}; + virtual bool parseOption( const char* option ); + + // Variables + QStringList AdditionalIncludeDirectories; + QStringList AdditionalOptions; + QStringList CPreprocessOptions; + midlCharOption DefaultCharType; + QString DLLDataFileName; // Should be list? + midlErrorCheckOption EnableErrorChecks; + triState ErrorCheckAllocations; + triState ErrorCheckBounds; + triState ErrorCheckEnumRange; + triState ErrorCheckRefPointers; + triState ErrorCheckStubData; + QStringList FullIncludePath; + triState GenerateStublessProxies; + triState GenerateTypeLibrary; + QString HeaderFileName; + triState IgnoreStandardIncludePath; + QString InterfaceIdentifierFileName; + triState MkTypLibCompatible; + QString OutputDirectory; + QStringList PreprocessorDefinitions; + QString ProxyFileName; + QString RedirectOutputAndErrors; + midlStructMemberAlignOption StructMemberAlignment; + triState SuppressStartupBanner; + midlTargetEnvironment TargetEnvironment; + QString TypeLibraryName; + QStringList UndefinePreprocessorDefinitions; + triState ValidateParameters; + triState WarnAsError; + midlWarningLevelOption WarningLevel; + VCConfiguration* config; +}; + +class VCLibrarianTool : public VCToolBase +{ +public: + // Functions + VCLibrarianTool(); + ~VCLibrarianTool(){}; + virtual bool parseOption( const char* option ){ return FALSE; }; + + // Variables + QStringList AdditionalDependencies; + QStringList AdditionalLibraryDirectories; + QStringList AdditionalOptions; + QStringList ExportNamedFunctions; + QStringList ForceSymbolReferences; + triState IgnoreAllDefaultLibraries; + QStringList IgnoreDefaultLibraryNames; + QString ModuleDefinitionFile; + QString OutputFile; + triState SuppressStartupBanner; +}; + +class VCCustomBuildTool : public VCToolBase +{ +public: + // Functions + VCCustomBuildTool(); + ~VCCustomBuildTool(){}; + virtual bool parseOption( const char* option ){ return FALSE; }; + + // Variables + QStringList AdditionalDependencies; + QString CommandLine; + QString Description; + QString Outputs; + QString ToolName; + QString ToolPath; +}; + +class VCResourceCompilerTool : public VCToolBase +{ +public: + // Functions + VCResourceCompilerTool(); + ~VCResourceCompilerTool(){}; + virtual bool parseOption( const char* option ){ return FALSE; }; + + // Variables + QStringList AdditionalIncludeDirectories; + QStringList AdditionalOptions; + enumResourceLangID Culture; + QStringList FullIncludePath; + triState IgnoreStandardIncludePath; + QStringList PreprocessorDefinitions; + QString ResourceOutputFileName; + linkProgressOption ShowProgress; + QString ToolPath; +}; + +class VCEventTool : public VCToolBase +{ +protected: + // Functions + VCEventTool() : ExcludedFromBuild( unset ){}; + ~VCEventTool(){}; + virtual bool parseOption( const char* option ){ return FALSE; }; + +public: + // Variables + QString CommandLine; + QString Description; + triState ExcludedFromBuild; + QString ToolName; + QString ToolPath; +}; + +class VCPostBuildEventTool : public VCEventTool +{ +public: + VCPostBuildEventTool(); + ~VCPostBuildEventTool(){}; +}; + +class VCPreBuildEventTool : public VCEventTool +{ +public: + VCPreBuildEventTool(); + ~VCPreBuildEventTool(){}; +}; + +class VCPreLinkEventTool : public VCEventTool +{ +public: + VCPreLinkEventTool(); + ~VCPreLinkEventTool(){}; +}; + +class VCConfiguration +{ +public: + // Functions + VCConfiguration(); + ~VCConfiguration(){}; + + // Variables + triState ATLMinimizesCRunTimeLibraryUsage; + triState BuildBrowserInformation; + charSet CharacterSet; + ConfigurationTypes ConfigurationType; + QString DeleteExtensionsOnClean; + QString ImportLibrary; + QString IntermediateDirectory; + QString Name; + QString OutputDirectory; + QString PrimaryOutput; + QString ProgramDatabase; + triState RegisterOutput; + useOfATL UseOfATL; + useOfMfc UseOfMfc; + triState WholeProgramOptimization; + + // XML sub-parts + VCCLCompilerTool compiler; + VCLinkerTool linker; + VCLibrarianTool librarian; + VCCustomBuildTool custom; + VCMIDLTool idl; + VCPostBuildEventTool postBuild; + VCPreBuildEventTool preBuild; + VCPreLinkEventTool preLink; + VCResourceCompilerTool resource; +}; + +class VcprojGenerator; +class VCFilter +{ +public: + // Functions + VCFilter(); + ~VCFilter(){}; + void generateMOC( QTextStream &strm, QString str ) const; + void generateUIC( QTextStream &strm, const QString& str ) const; + + // Variables + QString Name; + QString Filter; + triState ParseFiles; + QStringList Files; + VcprojGenerator* Project; + VCConfiguration* Config; + customBuildCheck CustomBuild; +}; + +class VCProject +{ +public: + // Functions + VCProject(); + ~VCProject(){}; + + // Variables + QString Name; + QString Version; + QString ProjectGUID; + QString SccProjectName; + QString SccLocalPath; + QString PlatformName; + + // XML sub-parts + VCConfiguration Configuration; + VCFilter SourceFiles; + VCFilter HeaderFiles; + VCFilter MOCFiles; + VCFilter UICFiles; + VCFilter FormFiles; + VCFilter TranslationFiles; + VCFilter LexYaccFiles; + VCFilter ResourceFiles; +}; + +QTextStream &operator<<( QTextStream &, const VCCLCompilerTool & ); +QTextStream &operator<<( QTextStream &, const VCLinkerTool & ); +QTextStream &operator<<( QTextStream &, const VCMIDLTool & ); +QTextStream &operator<<( QTextStream &, const VCCustomBuildTool & ); +QTextStream &operator<<( QTextStream &, const VCLibrarianTool & ); +QTextStream &operator<<( QTextStream &, const VCResourceCompilerTool & ); +QTextStream &operator<<( QTextStream &, const VCEventTool & ); +QTextStream &operator<<( QTextStream &, const VCConfiguration & ); +QTextStream &operator<<( QTextStream &, const VCFilter & ); +QTextStream &operator<<( QTextStream &, const VCProject & ); + +#endif //__MSVC_OBJECTMODEL_H__ diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp new file mode 100644 index 0000000..a2bb6e9 --- a/dev/null +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -0,0 +1,1050 @@ +/**************************************************************************** +** $Id$ +** +** Definition of VcprojGenerator class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "msvc_vcproj.h" +#include "option.h" +#include <qdir.h> +#include <stdlib.h> +#include <qregexp.h> + +#if defined(Q_OS_WIN32) +#include <objbase.h> +#endif + +VcprojGenerator::VcprojGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) +{ +} + +/* \internal + Generates a project file for the given profile. + Options are either a Visual Studio projectfiles, or + recursive projectfiles.. Maybe we can make .sln files + someday? +*/ +bool VcprojGenerator::writeMakefile(QTextStream &t) +{ + // Check if all requirements are fullfilled + if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { + fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", + var("QMAKE_FAILED_REQUIREMENTS").latin1()); + return TRUE; + } + + // Generate full project file + if(project->first("TEMPLATE") == "vcapp" || + project->first("TEMPLATE") == "vclib") { + debug_msg(1, "Generator: MSVC.NET: Writing project file" ); + t << vcProject; + return TRUE; + } else if(project->first("TEMPLATE") == "vcsubdirs") { // Generate recursive project + debug_msg(1, "Generator: MSVC.NET: Writing solution file" ); + writeSubDirs(t); + return TRUE; + } + return FALSE; + +} + +struct VcsolutionDepend { + QString vcprojFile, orig_target, target; + QStringList dependencies; +}; + +void VcprojGenerator::writeSubDirs(QTextStream &t) +{ + if(project->first("TEMPLATE") == "subdirs") { + writeHeader(t); + Win32MakefileGenerator::writeSubDirs(t); + return; + } + + QPtrList<VcsolutionDepend> solution_depends; + solution_depends.setAutoDelete(TRUE); + QStringList subdirs = project->variables()["SUBDIRS"]; + QString oldpwd = QDir::currentDirPath(); + for(QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it) { + QFileInfo fi(Option::fixPathToLocalOS((*it), TRUE)); + if(fi.exists()) { + if(fi.isDir()) { + QString profile = (*it); + if(!profile.endsWith(Option::dir_sep)) + profile += Option::dir_sep; + profile += fi.baseName() + ".pro"; + subdirs.append(profile); + } else { + QMakeProject tmp_proj; + QString dir = fi.dirPath(), fn = fi.fileName(); + if(!dir.isEmpty()) { + if(!QDir::setCurrent(dir)) + fprintf(stderr, "Cannot find directory: %s\n", dir.latin1()); + } + if(tmp_proj.read(fn, oldpwd)) { + if(tmp_proj.first("TEMPLATE") == "vcsubdirs") { + QStringList tmp_subdirs = fileFixify(tmp_proj.variables()["SUBDIRS"]); + subdirs += tmp_subdirs; + } else if(tmp_proj.first("TEMPLATE") == "vcapp" || + tmp_proj.first("TEMPLATE") == "vclib") { + QString vcproj = fi.baseName() + project->first("VCPROJ_EXTENSION"); + if(QFile::exists(vcproj) || 1) { + VcprojGenerator tmp_dsp(&tmp_proj); + tmp_dsp.setNoIO(TRUE); + tmp_dsp.init(); + if(Option::debug_level) { + QMap<QString, QStringList> &vars = tmp_proj.variables(); + for(QMap<QString, QStringList>::Iterator it = vars.begin(); + it != vars.end(); ++it) { + if(it.key().left(1) != "." && !it.data().isEmpty()) + debug_msg(1, "%s: %s === %s", fn.latin1(), it.key().latin1(), + it.data().join(" :: ").latin1()); + } + } + VcsolutionDepend *newDep = new VcsolutionDepend; + newDep->vcprojFile = fileFixify(vcproj); + newDep->orig_target = tmp_proj.first("QMAKE_ORIG_TARGET"); + newDep->target = tmp_proj.first("TARGET").section(Option::dir_sep, -1); + if(newDep->target.endsWith(".dll")) + newDep->target = newDep->target.left(newDep->target.length()-3) + "lib"; + if(!tmp_proj.isEmpty("FORMS")) + newDep->dependencies << "uic.exe"; + { + QStringList where("QMAKE_LIBS"); + if(!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS")) + where = tmp_proj.variables()["QMAKE_INTERNAL_PRL_LIBS"]; + for(QStringList::iterator wit = where.begin(); + wit != where.end(); ++wit) { + QStringList &l = tmp_proj.variables()[(*wit)]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString opt = (*it); + if(!opt.startsWith("/")) //Not a switch + newDep->dependencies << opt.section(Option::dir_sep, -1); + } + } + } + solution_depends.append(newDep); + } + } + } + QDir::setCurrent(oldpwd); + } + } + } + + VcsolutionDepend *vc; + QMap<QString, int> uuids; + QRegExp libVersion("[0-9]{3,3}\\.lib$"); + for(vc = solution_depends.first(); vc; vc = solution_depends.next()) { + static int uuid = 666; + uuids.insert(vc->target, uuid); + if(libVersion.match(vc->target) != -1) + uuids.insert(vc->target.left(vc->target.length() - libVersion.matchedLength()) + ".lib", + uuid); + t << "\"" << vc->orig_target << "\" \"" << vc->vcprojFile << "\" { " << uuid << " }" << endl; + uuid++; + } + for(vc = solution_depends.first(); vc; vc = solution_depends.next()) { + int uuid = uuids[vc->target], cnt = 0; + for(QStringList::iterator dit = vc->dependencies.begin(); dit != vc->dependencies.end(); ++dit) { + if(uuids.contains((*dit))) + t << uuid << "." << cnt++ << " = " << uuids[(*dit)] << endl; + } + } +} + +// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ + +void VcprojGenerator::init() +{ + if( init_flag ) + return; + if(project->first("TEMPLATE") == "vcsubdirs") { //too much work for subdirs + init_flag = TRUE; + return; + } + + debug_msg(1, "Generator: MSVC.NET: Initializing variables" ); + +/* + // Once to be nice and clean code... + // Wouldn't life be great? + + // Are we building Qt? + bool is_qt = + ( project->first("TARGET") == "qt"QTDLL_POSTFIX || + project->first("TARGET") == "qt-mt"QTDLL_POSTFIX ); + + // Are we using Qt? + bool isQtActive = project->isActiveConfig("qt"); + + if ( isQtActive ) { + project->variables()["CONFIG"] += "moc"; + project->variables()["CONFIG"] += "windows"; + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; + + if( projectTarget == SharedLib ) + project->variables()["DEFINES"] += "QT_DLL"; + + if( project->isActiveConfig("accessibility" ) ) + project->variables()["DEFINES"] += "QT_ACCESSIBILITY_SUPPORT"; + + if ( project->isActiveConfig("plugin")) { + project->variables()["DEFINES"] += "QT_PLUGIN"; + project->variables()["CONFIG"] += "dll"; + } + + if( project->isActiveConfig("thread") ) { + project->variables()["DEFINES"] += "QT_THREAD_SUPPORT"; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + } else { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + } + } + + if ( project->isActiveConfig("opengl") ) { + project->variables()["CONFIG"] += "windows"; // <-- Also in 'qt' above + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; + + } +*/ + initOld(); // Currently calling old DSP code to set variables. CLEAN UP! + + // Figure out what we're trying to build + if ( project->first("TEMPLATE") == "vcapp" ) { + projectTarget = Application; + } else if ( project->first("TEMPLATE") == "vclib") { + if ( project->isActiveConfig( "staticlib" ) ) + projectTarget = StaticLib; + else + projectTarget = SharedLib; + } + initProject(); // Fills the whole project with proper data +} + +void VcprojGenerator::initProject() +{ + // Initialize XML sub elements + // - Do this first since project elements may need + // - to know of certain configuration options + initConfiguration(); + initSourceFiles(); + initHeaderFiles(); + initMOCFiles(); + initUICFiles(); + initFormsFiles(); + initTranslationFiles(); + initLexYaccFiles(); + initResourceFiles(); + + // Own elements ----------------------------- + vcProject.Name = project->first("QMAKE_ORIG_TARGET"); + vcProject.Version = "7.00"; + vcProject.PlatformName = ( vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32" ); + // These are not used by Qt, but may be used by customers + vcProject.SccProjectName = project->first("SCCPROJECTNAME"); + vcProject.SccLocalPath = project->first("SCCLOCALPATH"); +} + +void VcprojGenerator::initConfiguration() +{ + // Initialize XML sub elements + // - Do this first since main configuration elements may need + // - to know of certain compiler/linker options + initCompilerTool(); + if ( projectTarget == StaticLib ) + initLibrarianTool(); + else + initLinkerTool(); + initIDLTool(); + + // Own elements ----------------------------- + QString temp = project->first("BuildBrowserInformation"); + switch ( projectTarget ) { + case SharedLib: + vcProject.Configuration.ConfigurationType = typeDynamicLibrary; + break; + case StaticLib: + vcProject.Configuration.ConfigurationType = typeStaticLibrary; + break; + case Application: + default: + vcProject.Configuration.ConfigurationType = typeApplication; + break; + } + vcProject.Configuration.Name = ( project->isActiveConfig( "release" ) ? "Release|" : "Debug|" ); + vcProject.Configuration.Name += ( vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32" ); + vcProject.Configuration.ATLMinimizesCRunTimeLibraryUsage = ( project->first("ATLMinimizesCRunTimeLibraryUsage").isEmpty() ? _False : _True ); + vcProject.Configuration.BuildBrowserInformation = triState( temp.isEmpty() ? unset : temp.toShort() ); + temp = project->first("CharacterSet"); + vcProject.Configuration.CharacterSet = charSet( temp.isEmpty() ? charSetNotSet : temp.toShort() ); + vcProject.Configuration.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean"); + vcProject.Configuration.ImportLibrary = vcProject.Configuration.linker.ImportLibrary; + vcProject.Configuration.IntermediateDirectory = project->first("OBJECTS_DIR"); +// temp = (projectTarget == StaticLib) ? project->first("DESTDIR"):project->first("DLLDESTDIR"); + vcProject.Configuration.OutputDirectory = "."; //( temp.isEmpty() ? QString(".") : temp ); + vcProject.Configuration.PrimaryOutput = project->first("PrimaryOutput"); + vcProject.Configuration.WholeProgramOptimization = vcProject.Configuration.compiler.WholeProgramOptimization; + temp = project->first("UseOfATL"); + if ( !temp.isEmpty() ) + vcProject.Configuration.UseOfATL = useOfATL( temp.toShort() ); + temp = project->first("UseOfMfc"); + if ( !temp.isEmpty() ) + vcProject.Configuration.UseOfMfc = useOfMfc( temp.toShort() ); + + // Configuration does not need parameters from + // these sub XML items; + initCustomBuildTool(); + initPreBuildEventTools(); + initPostBuildEventTools(); + initPreLinkEventTools(); +} + +void VcprojGenerator::initCompilerTool() +{ + QString placement = project->first("OBJECTS_DIR"); + if ( placement.isEmpty() ) + placement = project->isActiveConfig( "release" )? ".\\Release\\":".\\Debug\\"; + + vcProject.Configuration.compiler.AssemblerListingLocation = placement ; + vcProject.Configuration.compiler.ProgramDataBaseFileName = placement ; + vcProject.Configuration.compiler.ObjectFile = placement ; + vcProject.Configuration.compiler.PrecompiledHeaderFile = placement + project->first("QMAKE_ORIG_TARGET") + ".pch"; + + if ( project->isActiveConfig("debug") ){ + // Debug version + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS"] ); + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_DEBUG"] ); + if ( project->isActiveConfig("thread") ) { + if ( (projectTarget == Application) || (projectTarget == StaticLib) ) + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DBG"] ); + else + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"] ); + } else { + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_ST_DBG"] ); + } + } else { + // Release version + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS"] ); + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_RELEASE"] ); + vcProject.Configuration.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; + if ( project->isActiveConfig("thread") ) { + if ( (projectTarget == Application) || (projectTarget == StaticLib) ) + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT"] ); + else + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DLL"] ); + } else { + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_ST"] ); + } + } + + // Common for both release and debug + if ( project->isActiveConfig("warn_off") ) + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_WARN_OFF"] ); + else + vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_WARN_ON"] ); + if ( project->isActiveConfig("windows") ) + vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["MSVCPROJ_WINCONDEF"]; + + // Can this be set for ALL configs? + // If so, use qmake.conf! + if ( projectTarget == SharedLib ) + vcProject.Configuration.compiler.PreprocessorDefinitions += "_WINDOWS"; + + vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["DEFINES"]; + vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["PRL_EXPORT_DEFINES"]; + vcProject.Configuration.compiler.parseOptions( project->variables()["MSVCPROJ_INCPATH"] ); +} + +void VcprojGenerator::initLibrarianTool() +{ + vcProject.Configuration.librarian.OutputFile = project->first( "DESTDIR" ); + if( vcProject.Configuration.librarian.OutputFile.isEmpty() ) + vcProject.Configuration.librarian.OutputFile = ".\\"; + + if( !vcProject.Configuration.librarian.OutputFile.endsWith("\\") ) + vcProject.Configuration.librarian.OutputFile += '\\'; + + vcProject.Configuration.librarian.OutputFile += project->first("MSVCPROJ_TARGET"); +} + +void VcprojGenerator::initLinkerTool() +{ + vcProject.Configuration.linker.parseOptions( project->variables()["MSVCPROJ_LFLAGS"] ); + vcProject.Configuration.linker.AdditionalDependencies += project->variables()["MSVCPROJ_LIBS"]; + + switch ( projectTarget ) { + case Application: + vcProject.Configuration.linker.OutputFile = project->first( "DESTDIR" ); + break; + case SharedLib: + vcProject.Configuration.linker.parseOptions( project->variables()["MSVCPROJ_LIBOPTIONS"] ); + vcProject.Configuration.linker.OutputFile = project->first( "DLLDESTDIR" ); + break; + } + + if( vcProject.Configuration.linker.OutputFile.isEmpty() ) + vcProject.Configuration.linker.OutputFile = ".\\"; + + if( !vcProject.Configuration.linker.OutputFile.endsWith("\\") ) + vcProject.Configuration.linker.OutputFile += '\\'; + + vcProject.Configuration.linker.OutputFile += project->first("MSVCPROJ_TARGET"); + vcProject.Configuration.linker.ProgramDatabaseFile = project->first("OBJECTS_DIR") + project->first("QMAKE_ORIG_TARGET") + ".pdb"; + + if ( project->isActiveConfig("debug") ){ + vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_DEBUG"] ); + } else { + vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_RELEASE"] ); + } + + if ( project->isActiveConfig("dll") ){ + vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_QT_DLL"] ); + } + + if ( project->isActiveConfig("console") ){ + vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_CONSOLE"] ); + } else { + vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_WINDOWS"] ); + } + +} + +void VcprojGenerator::initIDLTool() +{ +} + +void VcprojGenerator::initCustomBuildTool() +{ +} + +void VcprojGenerator::initPreBuildEventTools() +{ + QString collectionName = project->first("QMAKE_IMAGE_COLLECTION"); + if( !collectionName.isEmpty() ) { + QStringList& list = project->variables()["IMAGES"]; + vcProject.Configuration.preBuild.Description = "Generate imagecollection"; + //vcProject.Configuration.preBuild.AdditionalDependencies += list; + vcProject.Configuration.preBuild.CommandLine = project->first("QMAKE_UIC") + " -embed " + project->first("QMAKE_ORIG_TARGET") + " " + list.join(" ") + " -o " + collectionName; + //vcProject.Configuration.preBuild.Outputs = collectionName; + + } +} + +void VcprojGenerator::initPostBuildEventTools() +{ + if( project->isActiveConfig( "activeqt" ) ) { + QString name = project->first( "QMAKE_ORIG_TARGET" ); + QString nameext = project->first( "TARGET" ); + QString objdir = project->first( "OBJECTS_DIR" ); + QString idc = project->first( "QMAKE_IDC" ); + + vcProject.Configuration.postBuild.Description = "Finalizing ActiveQt server..."; + + if( project->isActiveConfig( "dll" ) ) { // In process + vcProject.Configuration.postBuild.CommandLine = + // call idc to generate .idl file from .dll + idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " -idl " + objdir + name + ".idl -version 1.0 && " + + // call midl to create implementations of the .idl file + project->first( "QMAKE_IDL" ) + " " + objdir + name + ".idl /nologo /o " + objdir + name + ".midl /tlb " + objdir + name + ".tlb /iid " + objdir + + "dump.midl /dlldata " + objdir + "dump.midl /cstub " + objdir + "dump.midl /header " + objdir + "dump.midl /proxy " + objdir + "dump.midl /sstub " + + objdir + "dump.midl && " + + // call idc to replace tlb... + idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /tlb " + objdir + name + ".tlb && " + + // register server + idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /regserver"; + } else { // out of process + vcProject.Configuration.postBuild.CommandLine = + // call application to dump idl + vcProject.Configuration.OutputDirectory + "\\" + nameext + " -dumpidl " + objdir + name + ".idl -version 1.0 && " + + // call midl to create implementations of the .idl file + project->first( "QMAKE_IDL" ) + " " + objdir + name + ".idl /nologo /o " + objdir + name + ".midl /tlb " + objdir + name + ".tlb /iid " + objdir + + "dump.midl /dlldata " + objdir + "dump.midl /cstub " + objdir + "dump.midl /header " + objdir + "dump.midl /proxy " + objdir + "dump.midl /sstub " + + objdir + "dump.midl && " + + // call idc to replace tlb... + idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /tlb " + objdir + name + ".tlb && " + + // call app to register + vcProject.Configuration.OutputDirectory + "\\" + nameext + " -regserver"; + } + } +} + +void VcprojGenerator::initPreLinkEventTools() +{ +} + +void VcprojGenerator::initSourceFiles() +{ + vcProject.SourceFiles.Name = "Source Files"; + vcProject.SourceFiles.Filter = "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"; + vcProject.SourceFiles.Files += project->variables()["SOURCES"]; + vcProject.SourceFiles.Files.sort(); + vcProject.SourceFiles.Project = this; + vcProject.SourceFiles.Config = &(vcProject.Configuration); + vcProject.SourceFiles.CustomBuild = none; +} + +void VcprojGenerator::initHeaderFiles() +{ + vcProject.HeaderFiles.Name = "Header Files"; + vcProject.HeaderFiles.Filter = "h;hpp;hxx;hm;inl"; + vcProject.HeaderFiles.Files += project->variables()["HEADERS"]; + vcProject.HeaderFiles.Files.sort(); + vcProject.HeaderFiles.Project = this; + vcProject.HeaderFiles.Config = &(vcProject.Configuration); + vcProject.HeaderFiles.CustomBuild = moc; +} + +void VcprojGenerator::initMOCFiles() +{ + vcProject.MOCFiles.Name = "Generated MOC Files"; + vcProject.MOCFiles.Filter = "cpp;c;cxx;moc"; + vcProject.MOCFiles.Files += project->variables()["SRCMOC"]; + vcProject.MOCFiles.Files.sort(); + vcProject.MOCFiles.Project = this; + vcProject.MOCFiles.Config = &(vcProject.Configuration); + vcProject.MOCFiles.CustomBuild = moc; +} + +void VcprojGenerator::initUICFiles() +{ + vcProject.UICFiles.Name = "Generated UI Files"; + vcProject.UICFiles.Filter = "cpp;c;cxx;h;hpp;hxx;"; + vcProject.UICFiles.Project = this; + vcProject.UICFiles.Files += project->variables()["UICDECLS"]; + vcProject.UICFiles.Files += project->variables()["UICIMPLS"]; + vcProject.UICFiles.Files.sort(); + vcProject.UICFiles.Config = &(vcProject.Configuration); + vcProject.UICFiles.CustomBuild = none; +} + +void VcprojGenerator::initFormsFiles() +{ + vcProject.FormFiles.Name = "Forms"; + vcProject.FormFiles.ParseFiles = _False; + vcProject.FormFiles.Filter = "ui"; + vcProject.FormFiles.Files += project->variables()["FORMS"]; + vcProject.FormFiles.Files.sort(); + vcProject.FormFiles.Project = this; + vcProject.FormFiles.Config = &(vcProject.Configuration); + vcProject.FormFiles.CustomBuild = uic; +} + +void VcprojGenerator::initTranslationFiles() +{ + vcProject.TranslationFiles.Name = "Translations Files"; + vcProject.TranslationFiles.ParseFiles = _False; + vcProject.TranslationFiles.Filter = "ts"; + vcProject.TranslationFiles.Files += project->variables()["TRANSLATIONS"]; + vcProject.TranslationFiles.Files.sort(); + vcProject.TranslationFiles.Project = this; + vcProject.TranslationFiles.Config = &(vcProject.Configuration); + vcProject.TranslationFiles.CustomBuild = none; +} + +void VcprojGenerator::initLexYaccFiles() +{ + vcProject.LexYaccFiles.Name = "Lex / Yacc Files"; + vcProject.LexYaccFiles.ParseFiles = _False; + vcProject.LexYaccFiles.Filter = "l;y"; + vcProject.LexYaccFiles.Files += project->variables()["LEXSOURCES"]; + vcProject.LexYaccFiles.Files += project->variables()["YACCSOURCES"]; + vcProject.LexYaccFiles.Files.sort(); + vcProject.LexYaccFiles.Project = this; + vcProject.LexYaccFiles.CustomBuild = lexyacc; +} + +void VcprojGenerator::initResourceFiles() +{ + vcProject.ResourceFiles.Name = "Resources"; + vcProject.ResourceFiles.ParseFiles = _False; + vcProject.ResourceFiles.Filter = "cpp;ico;png;jpg;jpeg;gif;xpm;bmp;rc;ts"; + vcProject.ResourceFiles.Files += project->variables()["RC_FILE"]; + vcProject.ResourceFiles.Files += project->variables()["QMAKE_IMAGE_COLLECTION"]; + vcProject.ResourceFiles.Files += project->variables()["IMAGES"]; + vcProject.ResourceFiles.Files += project->variables()["IDLSOURCES"]; + vcProject.ResourceFiles.Files.sort(); + vcProject.ResourceFiles.Project = this; + vcProject.ResourceFiles.CustomBuild = none; +} + +/* +// $$MSVCPROJ_IDLSOURCES --------------------------------------------- +void VcprojGenerator::writeIDLs( QTextStream &t ) +{ + QStringList &l = project->variables()["MSVCPROJ_IDLSOURCES"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + t << "# Begin Source File" << endl << endl; + t << "SOURCE=" << (*it) << endl; + t << "# PROP Exclude_From_Build 1" << endl; + t << "# End Source File" << endl << endl; + } + debug_msg(3, "Generator: MSVC.NET: Added IDLs" ); +} +*/ + +/* \internal + Sets up all needed variables from the environment and all the different caches and .conf files +*/ + +void VcprojGenerator::initOld() +{ + if( init_flag ) + return; + + init_flag = TRUE; + QStringList::Iterator it; + + // this should probably not be here, but I'm using it to wrap the .t files + if(project->first("TEMPLATE") == "vcapp" ) + project->variables()["QMAKE_APP_FLAG"].append("1"); + else if(project->first("TEMPLATE") == "vclib") + project->variables()["QMAKE_LIB_FLAG"].append("1"); + if ( project->variables()["QMAKESPEC"].isEmpty() ) + project->variables()["QMAKESPEC"].append( getenv("QMAKESPEC") ); + + bool is_qt = + ( project->first("TARGET") == "qt"QTDLL_POSTFIX || + project->first("TARGET") == "qt-mt"QTDLL_POSTFIX ); + + QStringList &configs = project->variables()["CONFIG"]; + + if ( project->isActiveConfig( "shared" ) ) + project->variables()["DEFINES"].append( "QT_DLL" ); + + if ( project->isActiveConfig( "qt_dll" ) && + configs.findIndex("qt") == -1 ) + configs.append("qt"); + + if ( project->isActiveConfig( "qt" ) ) { + if ( project->isActiveConfig( "plugin" ) ) { + project->variables()["CONFIG"].append( "dll" ); + project->variables()["DEFINES"].append( "QT_PLUGIN" ); + } + if ( ( project->variables()["DEFINES"].findIndex( "QT_NODLL" ) == -1 ) && + (( project->variables()["DEFINES"].findIndex( "QT_MAKEDLL" ) != -1 || + project->variables()["DEFINES"].findIndex( "QT_DLL" ) != -1 ) || + ( getenv( "QT_DLL" ) && !getenv( "QT_NODLL" ))) ) { + project->variables()["QMAKE_QT_DLL"].append( "1" ); + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) + project->variables()["CONFIG"].append( "dll" ); + } + } + + // If we are a dll, then we cannot be a staticlib at the same time... + if ( project->isActiveConfig( "dll" ) || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["CONFIG"].remove( "staticlib" ); + project->variables()["QMAKE_APP_OR_DLL"].append( "1" ); + } else { + project->variables()["CONFIG"].append( "staticlib" ); + } + + // If we need 'qt' and/or 'opengl', then we need windows and not console + if ( project->isActiveConfig( "qt" ) || project->isActiveConfig( "opengl" ) ) { + project->variables()["CONFIG"].append( "windows" ); + } + + // Decode version, and add it to $$MSVCPROJ_VERSION -------------- + if ( !project->variables()["VERSION"].isEmpty() ) { + QString version = project->variables()["VERSION"][0]; + int firstDot = version.find( "." ); + QString major = version.left( firstDot ); + QString minor = version.right( version.length() - firstDot - 1 ); + minor.replace( QRegExp( "\\." ), "" ); + project->variables()["MSVCPROJ_VERSION"].append( "/VERSION:" + major + "." + minor ); + } + + // QT ------------------------------------------------------------ + if ( project->isActiveConfig("qt") ) { + project->variables()["CONFIG"].append("moc"); + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; + project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; + + if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + project->variables()["DEFINES"].append("QT_MAKEDLL"); + project->variables()["QMAKE_LFLAGS"].append("/BASE:0x39D00000"); + } + } else { + if(project->isActiveConfig("thread")) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; + else + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; + if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { + int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); + if( hver==-1 ) { + hver = findHighestVersion( project->first("QMAKE_LIBDIR_QT"), "qt-mt" ); + } + + if(hver != -1) { + QString ver; + ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); + QStringList &libs = project->variables()["QMAKE_LIBS"]; + for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) + (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); + } + } + if ( project->isActiveConfig( "activeqt" ) ) { + project->variables().remove("QMAKE_LIBS_QT_ENTRY"); + project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; + if ( project->isActiveConfig( "dll" ) ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; + project->variables()["MSVCPROJ_LFLAGS"].append("/DEF:"+project->first("DEF_FILE")); + } + } + if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { + project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; + } + } + } + + // Set target directories ---------------------------------------- + // if ( !project->first("OBJECTS_DIR").isEmpty() ) + //project->variables()["MSVCPROJ_OBJECTSDIR"] = project->first("OBJECTS_DIR"); + // else + //project->variables()["MSVCPROJ_OBJECTSDIR"] = project->isActiveConfig( "release" )?"Release":"Debug"; + // if ( !project->first("DESTDIR").isEmpty() ) + //project->variables()["MSVCPROJ_TARGETDIR"] = project->first("DESTDIR"); + // else + //project->variables()["MSVCPROJ_TARGETDIR"] = project->isActiveConfig( "release" )?"Release":"Debug"; + + // OPENGL -------------------------------------------------------- + if ( project->isActiveConfig("opengl") ) { + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; + } + + // THREAD -------------------------------------------------------- + if ( project->isActiveConfig("thread") ) { + if(project->isActiveConfig("qt")) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT" ); + if ( !project->variables()["DEFINES"].contains("QT_DLL") && is_qt + && project->first("TARGET") != "qtmain" ) + project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:libc"); + } + + // ACCESSIBILITY ------------------------------------------------- + if(project->isActiveConfig("qt")) { + if ( project->isActiveConfig("accessibility" ) ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); + if ( project->isActiveConfig("tablet") ) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); + } + + // DLL ----------------------------------------------------------- + if ( project->isActiveConfig("dll") ) { + if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { + QString ver_xyz(project->first("VERSION")); + ver_xyz.replace(QRegExp("\\."), ""); + project->variables()["TARGET_EXT"].append(ver_xyz + ".dll"); + } else { + project->variables()["TARGET_EXT"].append(".dll"); + } + } + // EXE / LIB ----------------------------------------------------- + else { + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) + project->variables()["TARGET_EXT"].append(".exe"); + else + project->variables()["TARGET_EXT"].append(".lib"); + } + + project->variables()["MSVCPROJ_VER"] = "7.00"; + project->variables()["MSVCPROJ_DEBUG_OPT"] = "/GZ /ZI"; + + // INCREMENTAL:NO ------------------------------------------------ + if(!project->isActiveConfig("incremental")) { + project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); + if ( is_qt ) + project->variables()["MSVCPROJ_DEBUG_OPT"] = "/GZ /Zi"; + } + + // MOC ----------------------------------------------------------- + if ( project->isActiveConfig("moc") ) + setMocAware(TRUE); + + + project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + + // Run through all variables containing filepaths, and ----------- + // slash-slosh them correctly depending on current OS ----------- + project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); + QStringList &l = project->variables()["QMAKE_FILETAGS"]; + for(it = l.begin(); it != l.end(); ++it) { + QStringList &gdmf = project->variables()[(*it)]; + for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) + (*inner) = Option::fixPathToTargetOS((*inner), FALSE); + } + + // Get filename w/o extention ----------------------------------- + QString msvcproj_project = ""; + QString targetfilename = ""; + if ( project->variables()["TARGET"].count() ) { + msvcproj_project = project->variables()["TARGET"].first(); + targetfilename = msvcproj_project; + } + + // Save filename w/o extention in $$QMAKE_ORIG_TARGET ------------ + project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; + + // TARGET (add extention to $$TARGET) ---------------------------- + project->variables()["TARGET"].first() += project->first("TARGET_EXT"); + + // Init base class too ------------------------------------------- + MakefileGenerator::init(); + + + if ( msvcproj_project.isEmpty() ) + msvcproj_project = Option::output.name(); + + msvcproj_project = msvcproj_project.right( msvcproj_project.length() - msvcproj_project.findRev( "\\" ) - 1 ); + msvcproj_project = msvcproj_project.left( msvcproj_project.findRev( "." ) ); + msvcproj_project.replace(QRegExp("-"), ""); + + project->variables()["MSVCPROJ_PROJECT"].append(msvcproj_project); + QStringList &proj = project->variables()["MSVCPROJ_PROJECT"]; + + for(it = proj.begin(); it != proj.end(); ++it) + (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); + + // SUBSYSTEM ----------------------------------------------------- + if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { + project->variables()["MSVCPROJ_TEMPLATE"].append("win32app" + project->first( "VCPROJ_EXTENSION" ) ); + if ( project->isActiveConfig("console") ) { + project->variables()["MSVCPROJ_CONSOLE"].append("CONSOLE"); + project->variables()["MSVCPROJ_WINCONDEF"].append("_CONSOLE"); + project->variables()["MSVCPROJ_VCPROJTYPE"].append("0x0103"); + project->variables()["MSVCPROJ_SUBSYSTEM"].append("CONSOLE"); + } else { + project->variables()["MSVCPROJ_CONSOLE"].clear(); + project->variables()["MSVCPROJ_WINCONDEF"].append("_WINDOWS"); + project->variables()["MSVCPROJ_VCPROJTYPE"].append("0x0101"); + project->variables()["MSVCPROJ_SUBSYSTEM"].append("WINDOWS"); + } + } else { + if ( project->isActiveConfig("dll") ) { + project->variables()["MSVCPROJ_TEMPLATE"].append("win32dll" + project->first( "VCPROJ_EXTENSION" ) ); + } else { + project->variables()["MSVCPROJ_TEMPLATE"].append("win32lib" + project->first( "VCPROJ_EXTENSION" ) ); + } + } + + // $$QMAKE.. -> $$MSVCPROJ.. ------------------------------------- + project->variables()["MSVCPROJ_LIBS"] += project->variables()["QMAKE_LIBS"]; + project->variables()["MSVCPROJ_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; + project->variables()["MSVCPROJ_LFLAGS" ] += project->variables()["QMAKE_LFLAGS"]; + if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) + project->variables()["MSVCPROJ_LFLAGS" ].append(varGlue("QMAKE_LIBDIR","/LIBPATH:"," /LIBPATH:","")); + project->variables()["MSVCPROJ_CXXFLAGS" ] += project->variables()["QMAKE_CXXFLAGS"]; + // We don't use this... Direct manipulation of compiler object + //project->variables()["MSVCPROJ_DEFINES"].append(varGlue("DEFINES","/D ","" " /D ","")); + //project->variables()["MSVCPROJ_DEFINES"].append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ","")); + QStringList &incs = project->variables()["INCLUDEPATH"]; + for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { + QString inc = (*incit); + inc.replace(QRegExp("\""), ""); + project->variables()["MSVCPROJ_INCPATH"].append("/I" + inc ); + } + project->variables()["MSVCPROJ_INCPATH"].append("/I" + specdir()); + + QString dest; + project->variables()["MSVCPROJ_TARGET"] = project->first("TARGET"); + if ( !project->variables()["DESTDIR"].isEmpty() ) { + project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); + Option::fixPathToTargetOS(project->first("TARGET")); + dest = project->first("TARGET"); + if ( project->first("TARGET").startsWith("$(QTDIR)") ) + dest.replace( QRegExp("\\$\\(QTDIR\\)"), getenv("QTDIR") ); + project->variables()["MSVCPROJ_TARGET"].append( + QString("/OUT:") + dest ); + if ( project->isActiveConfig("dll") ) { + QString imp = dest; + imp.replace(QRegExp("\\.dll"), ".lib"); + project->variables()["MSVCPROJ_LIBOPTIONS"] += (QString("/IMPLIB:") + imp ); + } + } + + // DLL COPY ------------------------------------------------------ + if ( project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty() ) { + QStringList dlldirs = project->variables()["DLLDESTDIR"]; + QString copydll = "# Begin Special Build Tool\n" + "TargetPath=" + dest + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Copy DLL to " + project->first("DLLDESTDIR") + "\n" + "PostBuild_Cmds="; + + for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { + copydll += "copy \"" + dest + "\" \"" + *dlldir + "\"\t"; + } + + copydll += "\n# End Special Build Tool"; + project->variables()["MSVCPROJ_COPY_DLL_REL"].append( copydll ); + project->variables()["MSVCPROJ_COPY_DLL_DBG"].append( copydll ); + } + + // ACTIVEQT ------------------------------------------------------ + if ( project->isActiveConfig("activeqt") ) { + QString idl = project->variables()["QMAKE_IDL"].first(); + QString idc = project->variables()["QMAKE_IDC"].first(); + QString version = project->variables()["VERSION"].first(); + if ( version.isEmpty() ) + version = "1.0"; + + project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".idl" ); + project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".tlb" ); + project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".midl" ); + if ( project->isActiveConfig( "dll" ) ) { + QString regcmd = "# Begin Special Build Tool\n" + "TargetPath=" + targetfilename + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Finalizing ActiveQt server...\n" + "PostBuild_Cmds=" + + idc + " %1 -idl tmp\\" + targetfilename + ".idl -version " + version + + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" + "\tregsvr32 /s %1\n" + "# End Special Build Tool"; + + QString executable = project->variables()["MSVCPROJ_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCPROJ_COPY_DLL_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + + executable = project->variables()["MSVCPROJ_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCPROJ_COPY_DLL_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + } else { + QString regcmd = "# Begin Special Build Tool\n" + "TargetPath=" + targetfilename + "\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Finalizing ActiveQt server...\n" + "PostBuild_Cmds=" + "%1 -dumpidl tmp\\" + targetfilename + ".idl -version " + version + + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" + "\t%1 -regserver\n" + "# End Special Build Tool"; + + QString executable = project->variables()["MSVCPROJ_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCPROJ_REGSVR_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + + executable = project->variables()["MSVCPROJ_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); + project->variables()["MSVCPROJ_REGSVR_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + } + + } + + // FORMS --------------------------------------------------------- + QStringList &list = project->variables()["FORMS"]; + for( it = list.begin(); it != list.end(); ++it ) { + if ( QFile::exists( *it + ".h" ) ) + project->variables()["SOURCES"].append( *it + ".h" ); + } + + project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "MSVCPROJ_LFLAGS" << "MSVCPROJ_LIBS"; + + // Verbose output if "-d -d"... + outputVariables(); +} + +// ------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ + +bool VcprojGenerator::openOutput(QFile &file) const +{ + QString outdir; + if(!file.name().isEmpty()) { + QFileInfo fi(file); + if(fi.isDir()) + outdir = file.name() + QDir::separator(); + } + if(!outdir.isEmpty() || file.name().isEmpty()) { + QString ext = project->first("VCPROJ_EXTENSION"); + if(project->first("TEMPLATE") == "vcsubdirs") + ext = project->first("VCSOLUTION_EXTENSION"); + file.setName(outdir + project->first("TARGET") + ext); + } + if(QDir::isRelativePath(file.name())) { + QString ofile; + ofile = file.name(); + int slashfind = ofile.findRev('\\'); + if (slashfind == -1) { + ofile = ofile.replace("-", "_"); + } else { + int hypenfind = ofile.find('-', slashfind); + while (hypenfind != -1 && slashfind < hypenfind) { + ofile = ofile.replace(hypenfind, 1, "_"); + hypenfind = ofile.find('-', hypenfind + 1); + } + } + file.setName(Option::fixPathToLocalOS(QDir::currentDirPath() + Option::dir_sep + ofile)); + } + return Win32MakefileGenerator::openOutput(file); +} + +QString VcprojGenerator::findTemplate(QString file) +{ + QString ret; + if(!QFile::exists((ret = file)) && + !QFile::exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) && + !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/win32-msvc.net/" + file)) && + !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) + return ""; + debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.latin1() ); + return ret; +} + + +void VcprojGenerator::processPrlVariable(const QString &var, const QStringList &l) +{ + if(var == "QMAKE_PRL_DEFINES") { + QStringList &out = project->variables()["MSVCPROJ_DEFINES"]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if(out.findIndex((*it)) == -1) + out.append((" /D " + *it )); + } + } else { + MakefileGenerator::processPrlVariable(var, l); + } +} + +void VcprojGenerator::outputVariables() +{ +#if 0 + debug_msg(3, "Generator: MSVC.NET: List of current variables:" ); + for ( QMap<QString, QStringList>::ConstIterator it = project->variables().begin(); it != project->variables().end(); ++it) { + debug_msg(3, "Generator: MSVC.NET: %s => %s", it.key().latin1(), it.data().join(" | ").latin1() ); + } +#endif +} diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h new file mode 100644 index 0000000..583b164 --- a/dev/null +++ b/qmake/generators/win32/msvc_vcproj.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** $Id$ +** +** Definition of VcprojGenerator class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __VCPROJMAKE_H__ +#define __VCPROJMAKE_H__ + +#include "winmakefile.h" +#include "msvc_objectmodel.h" + +enum target { + Application, + SharedLib, + StaticLib +}; + +class VcprojGenerator : public Win32MakefileGenerator +{ + bool init_flag; + bool writeVcprojParts(QTextStream &); + + bool writeMakefile(QTextStream &); + virtual void writeSubDirs(QTextStream &t); + QString findTemplate(QString file); + void init(); + +public: + VcprojGenerator(QMakeProject *p); + ~VcprojGenerator(); + + QString defaultMakefile() const; + virtual bool doDepends() const { return FALSE; } //never necesary + +protected: + virtual bool openOutput(QFile &file) const; + virtual void processPrlVariable(const QString &, const QStringList &); + virtual bool findLibraries(); + virtual void outputVariables(); + + void initOld(); + void initProject(); + void initConfiguration(); + void initCompilerTool(); + void initLinkerTool(); + void initLibrarianTool(); + void initIDLTool(); + void initCustomBuildTool(); + void initPreBuildEventTools(); + void initPostBuildEventTools(); + void initPreLinkEventTools(); + void initSourceFiles(); + void initHeaderFiles(); + void initMOCFiles(); + void initUICFiles(); + void initFormsFiles(); + void initTranslationFiles(); + void initLexYaccFiles(); + void initResourceFiles(); + + /* + void writeGuid( QTextStream &t ); + void writeAdditionalOptions( QTextStream &t ); + void writeHeaders( QTextStream &t ); + void writeSources( QTextStream &t ); + void writeMocs( QTextStream &t ); + void writeLexs( QTextStream &t ); + void writeYaccs( QTextStream &t ); + void writePictures( QTextStream &t ); + void writeImages( QTextStream &t ); + void writeIDLs( QTextStream &t ); + + void writeForms( QTextStream &t ); + void writeFormsSourceHeaders( QString &variable, QTextStream &t ); + void writeTranslations( QTextStream &t ); + void writeStrippedTranslations( QTextStream &t ); + */ + + VCProject vcProject; + target projectTarget; + + friend class VCFilter; +}; + +inline VcprojGenerator::~VcprojGenerator() +{ } + +inline QString VcprojGenerator::defaultMakefile() const +{ + return project->first("TARGET") + project->first("VCPROJ_EXTENSION"); +} + +inline bool VcprojGenerator::findLibraries() +{ + return Win32MakefileGenerator::findLibraries("MSVCVCPROJ_LIBS"); +} + +#endif /* __VCPROJMAKE_H__ */ diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp new file mode 100644 index 0000000..a07c921 --- a/dev/null +++ b/qmake/generators/win32/winmakefile.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "winmakefile.h" +#include "option.h" +#include "project.h" +#include <qtextstream.h> +#include <qstring.h> +#include <qdict.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qdir.h> + + +Win32MakefileGenerator::Win32MakefileGenerator(QMakeProject *p) : MakefileGenerator(p) +{ + +} + + +struct SubDir +{ + QString directory, profile, target, makefile; +}; + +void +Win32MakefileGenerator::writeSubDirs(QTextStream &t) +{ + QPtrList<SubDir> subdirs; + { + QStringList subdirs_in = project->variables()["SUBDIRS"]; + for(QStringList::Iterator it = subdirs_in.begin(); it != subdirs_in.end(); ++it) { + QString file = (*it); + file = fileFixify(file); + SubDir *sd = new SubDir; + subdirs.append(sd); + sd->makefile = "$(MAKEFILE)"; + if((*it).right(4) == ".pro") { + int slsh = file.findRev(Option::dir_sep); + if(slsh != -1) { + sd->directory = file.left(slsh+1); + sd->profile = file.mid(slsh+1); + } else { + sd->profile = file; + } + } else { + sd->directory = file; + } + while(sd->directory.right(1) == Option::dir_sep) + sd->directory = sd->directory.left(sd->directory.length() - 1); + if(!sd->profile.isEmpty()) { + QString basename = sd->directory; + int new_slsh = basename.findRev(Option::dir_sep); + if(new_slsh != -1) + basename = basename.mid(new_slsh+1); + if(sd->profile != basename + ".pro") + sd->makefile += "." + sd->profile.left(sd->profile.length() - 4); //no need for the .pro + } + sd->target = "sub-" + (*it); + sd->target.replace('/', '-'); + sd->target.replace('.', '_'); + } + } + QPtrListIterator<SubDir> it(subdirs); + + if(!project->isEmpty("MAKEFILE")) + t << "MAKEFILE= " << var("MAKEFILE") << endl; + t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; + t << "SUBTARGETS = "; + for( it.toFirst(); it.current(); ++it) + t << " \\\n\t\t" << it.current()->target; + t << endl << endl; + t << "all: qmake_all $(SUBTARGETS)" << endl << endl; + + for( it.toFirst(); it.current(); ++it) { + bool have_dir = !(*it)->directory.isEmpty(); + + //make the makefile + QString mkfile = (*it)->makefile; + if(have_dir) + mkfile.prepend((*it)->directory + Option::dir_sep); + t << mkfile << ":"; + if(project->variables()["QMAKE_NOFORCE"].isEmpty()) + t << " FORCE"; + if(have_dir) + t << "\n\t" << "cd " << (*it)->directory; + t << "\n\t" << "$(QMAKE) " << (*it)->profile << " " << buildArgs(); + if((*it)->makefile != "$(MAKEFILE)") + t << " -o " << (*it)->makefile; + if(have_dir) { + int subLevels = it.current()->directory.contains(Option::dir_sep) + 1; + t << "\n\t" << "@cd .."; + for(int i = 1; i < subLevels; i++ ) + t << Option::dir_sep << ".."; + } + t << endl; + + //now actually build + t << (*it)->target << ": " << mkfile; + if(project->variables()["QMAKE_NOFORCE"].isEmpty()) + t << " FORCE"; + if(have_dir) + t << "\n\t" << "cd " << (*it)->directory; + t << "\n\t" << "$(MAKE)"; + if((*it)->makefile != "$(MAKEFILE)") + t << " -f " << (*it)->makefile; + if(have_dir) { + int subLevels = it.current()->directory.contains(Option::dir_sep) + 1; + t << "\n\t" << "@cd .."; + for(int i = 1; i < subLevels; i++ ) + t << Option::dir_sep << ".."; + } + t << endl << endl; + } + + if(project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].findIndex("qmake_all") == -1) + project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].append("qmake_all"); + writeMakeQmake(t); + + t << "qmake_all:"; + if ( !subdirs.isEmpty() ) { + for( it.toFirst(); it.current(); ++it) { + QString subdir = (*it)->directory; + int subLevels = subdir.contains(Option::dir_sep) + 1; + t << "\n\t" + << "cd " << subdir << "\n\t"; + int lastSlash = subdir.findRev(Option::dir_sep); + if(lastSlash != -1) + subdir = subdir.mid( lastSlash + 1 ); + t << "$(QMAKE) " << subdir << ".pro" + << (!project->isEmpty("MAKEFILE") ? QString(" -o ") + var("MAKEFILE") : QString("")) + << " " << buildArgs() << "\n\t" + << "@cd .."; + for(int i = 1; i < subLevels; i++ ) + t << Option::dir_sep << ".."; + } + } else { + // Borland make does not like empty an empty command section, so insert + // a dummy command. + t << "\n\t" << "@cd ."; + } + t << endl << endl; + + QString targs[] = { QString("clean"), QString("install"), QString("mocclean"), QString::null }; + for(int x = 0; targs[x] != QString::null; x++) { + t << targs[x] << ": qmake_all"; + if(targs[x] == "clean") + t << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ", ""); + if (!subdirs.isEmpty()) { + for( it.toFirst(); it.current(); ++it) { + int subLevels = (*it)->directory.contains(Option::dir_sep) + 1; + bool have_dir = !(*it)->directory.isEmpty(); + if(have_dir) + t << "\n\t" << "cd " << (*it)->directory; + QString in_file; + if((*it)->makefile != "$(MAKEFILE)") + in_file = " -f " + (*it)->makefile; + t << "\n\t" << "$(MAKE) " << in_file << " " << targs[x]; + if(have_dir) { + t << "\n\t" << "@cd .."; + for(int i = 1; i < subLevels; i++ ) + t << Option::dir_sep << ".."; + } + } + } else { + // Borland make does not like empty an empty command section, so + // insert a dummy command. + t << "\n\t" << "@cd ."; + } + t << endl << endl; + } + + if(project->variables()["QMAKE_NOFORCE"].isEmpty()) + t << "FORCE:" << endl << endl; +} + + +int +Win32MakefileGenerator::findHighestVersion(const QString &d, const + QString &stem) +{ + if(!QFile::exists(Option::fixPathToLocalOS(d))) + return -1; + if(!project->variables()["QMAKE_" + stem.upper() + + "_VERSION_OVERRIDE"].isEmpty()) + return project->variables()["QMAKE_" + stem.upper() + + "_VERSION_OVERRIDE"].first().toInt(); + QString bd = d; + fixEnvVariables(bd); + QDir dir(bd); + int biggest=-1; + QStringList entries = dir.entryList(); + QRegExp regx( "(" + stem + "([0-9]*)).lib", FALSE ); + for(QStringList::Iterator it = entries.begin(); it != entries.end(); + ++it) { + if(regx.exactMatch((*it))) + biggest = QMAX(biggest, (regx.cap(1) == stem || + regx.cap(2).isEmpty()) ? -1 : regx.cap(2).toInt()); + } + return biggest; +} + + +bool +Win32MakefileGenerator::findLibraries(const QString &where) +{ + + QStringList &l = project->variables()[where]; + QPtrList<MakefileDependDir> dirs; + dirs.setAutoDelete(TRUE); + for(QStringList::Iterator it = l.begin(); it != l.end(); ) { + QString opt = (*it); + bool remove = FALSE; + if(opt.startsWith("-L") || opt.startsWith("/L")) { + QString r = opt.right(opt.length() - 2), l = Option::fixPathToLocalOS(r); + dirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + remove = TRUE; + } else if(opt.startsWith("-l") || opt.startsWith("/l")) { + QString lib = opt.right(opt.length() - 2), out; + if(!lib.isEmpty()) { + for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) { + int ver = findHighestVersion(mdd->local_dir, lib); + if(ver > 0) + lib += QString::number(ver); + lib += ".lib"; + if(QFile::exists(mdd->local_dir + Option::dir_sep + lib)) { + out = mdd->real_dir + Option::dir_sep + lib; + break; + } + } + } + if(out.isEmpty()) + remove = TRUE; + else + (*it) = out; + } else if(!QFile::exists(Option::fixPathToLocalOS(opt))) { + QString dir, file = opt; + int slsh = file.findRev(Option::dir_sep); + if(slsh != -1) { + dir = file.left(slsh+1); + file = file.right(file.length() - slsh - 1); + } + if ( !(project->variables()["QMAKE_QT_DLL"].isEmpty() && (file == "qt.lib" || file == "qt-mt.lib")) ) { + if(file.endsWith(".lib")) { + file = file.left(file.length() - 4); + if(!file.at(file.length()-1).isNumber()) { + int ver = findHighestVersion(dir, file); + if(ver != -1) { + file = QString(dir + file + "%1" + ".lib"); + if(ver) + (*it) = file.arg(ver); + else + (*it) = file.arg(""); + } + } + } + } + } + if(remove) + it = l.remove(it); + else + ++it; + } + return TRUE; +} + +void +Win32MakefileGenerator::processPrlFiles() +{ + QDict<void> processed; + QPtrList<MakefileDependDir> libdirs; + libdirs.setAutoDelete(TRUE); + { + QStringList &libpaths = project->variables()["QMAKE_LIBDIR"]; + for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit) { + QString r = (*libpathit), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + } + } + for(bool ret = FALSE; TRUE; ret = FALSE) { + //read in any prl files included.. + QStringList l_out; + QString where = "QMAKE_LIBS"; + if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) + where = project->first("QMAKE_INTERNAL_PRL_LIBS"); + QStringList &l = project->variables()[where]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString opt = (*it); + if(opt.left(1) == "/") { + if(opt.left(9) == "/LIBPATH:") { + QString r = opt.mid(9), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + } + } else { + if(!processed[opt]) { + if(processPrlFile(opt)) { + processed.insert(opt, (void*)1); + ret = TRUE; + } else { + for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { + QString prl = mdd->local_dir + Option::dir_sep + opt; + if(processed[prl]) { + break; + } else if(processPrlFile(prl)) { + processed.insert(prl, (void*)1); + ret = TRUE; + break; + } + } + } + } + } + if(!opt.isEmpty()) + l_out.append(opt); + } + if(ret) + l = l_out; + else + break; + } +} diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h new file mode 100644 index 0000000..75ba0e0 --- a/dev/null +++ b/qmake/generators/win32/winmakefile.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __WINMAKEFILE_H__ +#define __WINMAKEFILE_H__ + +#include "makefile.h" + +// In the Qt evaluation and educational version, we have a postfix in the +// library name (e.g. qtmteval301.dll). QTDLL_POSTFIX is used for this. +// A script modifies these lines when building eval/edu version, so be careful +// when changing them. +#ifndef QTDLL_POSTFIX +#define QTDLL_POSTFIX "" +#endif + +class Win32MakefileGenerator : public MakefileGenerator +{ +protected: + virtual void writeSubDirs(QTextStream &t); + int findHighestVersion(const QString &dir, const QString &stem); + bool findLibraries(const QString &); + virtual bool findLibraries(); + virtual void processPrlFiles(); + +public: + Win32MakefileGenerator(QMakeProject *p); + ~Win32MakefileGenerator(); +}; + +inline Win32MakefileGenerator::~Win32MakefileGenerator() +{ } + +inline bool Win32MakefileGenerator::findLibraries() +{ return findLibraries("QMAKE_LIBS"); } + + + +#endif /* __WINMAKEFILE_H__ */ diff --git a/qmake/include/private/qapplication_p.h b/qmake/include/private/qapplication_p.h new file mode 100644 index 0000000..6fab6b3 --- a/dev/null +++ b/qmake/include/private/qapplication_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some Qt private functions. +** +** Created : 000228 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QAPPLICATION_P_H +#define QAPPLICATION_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp +// and many other. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#endif // QT_H + +class QWidget; +class QObject; +class QClipboard; +class QKeyEvent; +class QMouseEvent; +class QWheelEvent; + +extern Q_EXPORT bool qt_modal_state(); +extern Q_EXPORT void qt_enter_modal( QWidget* ); +extern Q_EXPORT void qt_leave_modal( QWidget* ); + +extern bool qt_is_gui_used; +#ifndef QT_NO_CLIPBOARD +extern QClipboard *qt_clipboard; +#endif + +#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) +extern Qt::WindowsVersion qt_winver; +#endif + +#if defined (Q_WS_X11) +extern int qt_ncols_option; +#endif + + +extern void qt_dispatchEnterLeave( QWidget*, QWidget* ); + + + +#endif diff --git a/qmake/include/private/qcolor_p.h b/qmake/include/private/qcolor_p.h new file mode 100644 index 0000000..942a803 --- a/dev/null +++ b/qmake/include/private/qcolor_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** $Id$ +** +** Named color support for non-X platforms. +** The color names have been borrowed from X. +** +** Created : 000228 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCOLOR_P_H +#define QCOLOR_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qmenudata.cpp, qmenubar.cpp, qmenubar.cpp, qpopupmenu.cpp, +// qmotifstyle.cpp and qwindowssstyle.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#endif // QT_H + +extern uint qt_get_rgb_val( const char *name ); +extern bool qt_get_named_rgb( const char *, QRgb* ); +extern void qt_reset_color_avail(); + +#endif diff --git a/qmake/include/private/qcom_p.h b/qmake/include/private/qcom_p.h new file mode 100644 index 0000000..6e7e1c8 --- a/dev/null +++ b/qmake/include/private/qcom_p.h @@ -0,0 +1,337 @@ +/**************************************************************************** +** $Id$ +** +** ... +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCOM_H +#define QCOM_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qstringlist.h" +#include "quuid.h" +#endif // QT_H + +#ifndef QT_NO_COMPONENT + +class QObject; +struct QUInterfaceDescription; +struct QUObject; + +#define QRESULT unsigned long +#define QS_OK (QRESULT)0x00000000 +#define QS_FALSE (QRESULT)0x00000001 + +#define QE_NOTIMPL (QRESULT)0x80000001 +#define QE_OUTOFMEMORY (QRESULT)0x80000002 +#define QE_INVALIDARG (QRESULT)0x80000003 +#define QE_NOINTERFACE (QRESULT)0x80000004 +#define QE_NOCOMPONENT (QRESULT)0x80000005 + + +// {1D8518CD-E8F5-4366-99E8-879FD7E482DE} +#ifndef IID_QUnknown +#define IID_QUnknown QUuid(0x1d8518cd, 0xe8f5, 0x4366, 0x99, 0xe8, 0x87, 0x9f, 0xd7, 0xe4, 0x82, 0xde) +#endif + +struct Q_EXPORT QUnknownInterface +{ + virtual QRESULT queryInterface( const QUuid&, QUnknownInterface** ) = 0; + virtual ulong addRef() = 0; + virtual ulong release() = 0; +}; + +// {FBAC965E-A441-413F-935E-CDF582573FAB} +#ifndef IID_QDispatch +#define IID_QDispatch QUuid( 0xfbac965e, 0xa441, 0x413f, 0x93, 0x5e, 0xcd, 0xf5, 0x82, 0x57, 0x3f, 0xab) +#endif + +// the dispatch interface that inherits the unknown interface.. It is +// used to explore interfaces during runtime and to do dynamic calls. +struct Q_EXPORT QDispatchInterface : public QUnknownInterface +{ + // returns the interface description of this dispatch interface. + virtual const QUInterfaceDescription* interfaceDescription() const = 0; + + // returns the event description of this dispatch interface. + virtual const QUInterfaceDescription* eventsDescription() const = 0; + + // invokes method id with parameters V*. Returns some sort of + // exception code. + virtual QRESULT invoke( int id, QUObject* o ) = 0; + + // installs listener as event listener + virtual void installListener( QDispatchInterface* listener ) = 0; + + // remove listener as event listener + virtual void removeListener( QDispatchInterface* listener ) = 0; +}; + +template <class T> +class QInterfacePtr +{ +public: + QInterfacePtr():iface(0){} + + QInterfacePtr( T* i) { + if ( (iface = i) ) + iface->addRef(); + } + + QInterfacePtr(const QInterfacePtr<T> &p) { + if ( (iface = p.iface) ) + iface->addRef(); + } + + ~QInterfacePtr() { + if ( iface ) + iface->release(); + } + + QInterfacePtr<T> &operator=(const QInterfacePtr<T> &p) { + if ( iface != p.iface ) { + if ( iface ) + iface->release(); + if ( (iface = p.iface) ) + iface->addRef(); + } + return *this; + } + + QInterfacePtr<T> &operator=(T* i) { + if (iface != i ) { + if ( iface ) + iface->release(); + if ( (iface = i) ) + iface->addRef(); + } + return *this; + } + + bool operator==( const QInterfacePtr<T> &p ) const { return iface == p.iface; } + + bool operator!= ( const QInterfacePtr<T>& p ) const { return !( *this == p ); } + + bool isNull() const { return !iface; } + + T* operator->() const { return iface; } + + T& operator*() const { return *iface; } + + operator T*() const { return iface; } + + QUnknownInterface** operator &() const { + if( iface ) + iface->release(); + return (QUnknownInterface**)&iface; + } + + T** operator &() { + if ( iface ) + iface->release(); + return &iface; + } + +private: + T* iface; +}; + +// {10A1501B-4C5F-4914-95DD-C400486CF900} +#ifndef IID_QObject +#define IID_QObject QUuid( 0x10a1501b, 0x4c5f, 0x4914, 0x95, 0xdd, 0xc4, 0x00, 0x48, 0x6c, 0xf9, 0x00) +#endif + +struct Q_EXPORT QObjectInterface +{ + virtual QObject* qObject() = 0; +}; + +// {5F3968A5-F451-45b1-96FB-061AD98F926E} +#ifndef IID_QComponentInformation +#define IID_QComponentInformation QUuid(0x5f3968a5, 0xf451, 0x45b1, 0x96, 0xfb, 0x6, 0x1a, 0xd9, 0x8f, 0x92, 0x6e) +#endif + +struct Q_EXPORT QComponentInformationInterface : public QUnknownInterface +{ + virtual QString name() const = 0; + virtual QString description() const = 0; + virtual QString author() const = 0; + virtual QString version() const = 0; +}; + +// {6CAA771B-17BB-4988-9E78-BA5CDDAAC31E} +#ifndef IID_QComponentFactory +#define IID_QComponentFactory QUuid( 0x6caa771b, 0x17bb, 0x4988, 0x9e, 0x78, 0xba, 0x5c, 0xdd, 0xaa, 0xc3, 0x1e) +#endif + +struct Q_EXPORT QComponentFactoryInterface : public QUnknownInterface +{ + virtual QRESULT createInstance( const QUuid &cid, const QUuid &iid, QUnknownInterface** instance, QUnknownInterface *outer ) = 0; +}; + +// {D16111D4-E1E7-4C47-8599-24483DAE2E07} +#ifndef IID_QLibrary +#define IID_QLibrary QUuid( 0xd16111d4, 0xe1e7, 0x4c47, 0x85, 0x99, 0x24, 0x48, 0x3d, 0xae, 0x2e, 0x07) +#endif + +struct Q_EXPORT QLibraryInterface : public QUnknownInterface +{ + virtual bool init() = 0; + virtual void cleanup() = 0; + virtual bool canUnload() const = 0; +}; + +// {3F8FDC44-3015-4f3e-B6D6-E4AAAABDEAAD} +#ifndef IID_QFeatureList +#define IID_QFeatureList QUuid(0x3f8fdc44, 0x3015, 0x4f3e, 0xb6, 0xd6, 0xe4, 0xaa, 0xaa, 0xbd, 0xea, 0xad) +#endif + +struct Q_EXPORT QFeatureListInterface : public QUnknownInterface +{ + virtual QStringList featureList() const = 0; +}; + +// {B5FEB5DE-E0CD-4E37-B0EB-8A812499A0C1} +#ifndef IID_QComponentRegistration +#define IID_QComponentRegistration QUuid( 0xb5feb5de, 0xe0cd, 0x4e37, 0xb0, 0xeb, 0x8a, 0x81, 0x24, 0x99, 0xa0, 0xc1) +#endif + +struct Q_EXPORT QComponentRegistrationInterface : public QUnknownInterface +{ + virtual bool registerComponents( const QString &filepath ) const = 0; + virtual bool unregisterComponents() const = 0; +}; + +// internal class that wraps an initialized ulong +struct Q_EXPORT QtULong +{ + QtULong() : ref( 0 ) { } + operator unsigned long () const { return ref; } + unsigned long& operator++() { return ++ref; } + unsigned long operator++( int ) { return ref++; } + unsigned long& operator--() { return --ref; } + unsigned long operator--( int ) { return ref--; } + + unsigned long ref; +}; +// default implementation of ref counting. A variable "ulong ref" has to be a member + + +#define Q_REFCOUNT \ +private: \ + QtULong qtrefcount; \ +public: \ + ulong addRef() {return qtrefcount++;} \ + ulong release() {if(!--qtrefcount){delete this;return 0;}return qtrefcount;} + +#ifndef Q_EXPORT_COMPONENT +#if defined(QT_THREAD_SUPPORT) +#define QT_THREADED_BUILD 1 +#define Q_UCM_FLAGS_STRING "11" +#else +#define QT_THREADED_BUILD 0 +#define Q_UCM_FLAGS_STRING "01" +#endif + +#ifndef Q_EXTERN_C +#ifdef __cplusplus +#define Q_EXTERN_C extern "C" +#else +#define Q_EXTERN_C extern +#endif +#endif + +// this is duplicated at Q_PLUGIN_VERIFICATION_DATA in qgplugin.h +// NOTE: if you change pattern, you MUST change the pattern in +// qcomlibrary.cpp as well. changing the pattern will break all +// backwards compatibility as well (no old plugins will be loaded). +#ifndef Q_UCM_VERIFICATION_DATA +# define Q_UCM_VERIFICATION_DATA \ + static const char *qt_ucm_verification_data = \ + "pattern=""QT_UCM_VERIFICATION_DATA""\n" \ + "version="QT_VERSION_STR"\n" \ + "flags="Q_UCM_FLAGS_STRING"\n" \ + "buildkey="QT_BUILD_KEY"\0"; +#endif // Q_UCM_VERIFICATION_DATA + +// This macro expands to the default implementation of ucm_instantiate. +#ifndef Q_CREATE_INSTANCE +# define Q_CREATE_INSTANCE( IMPLEMENTATION ) \ + IMPLEMENTATION *i = new IMPLEMENTATION; \ + QUnknownInterface* iface = 0; \ + i->queryInterface( IID_QUnknown, &iface ); \ + return iface; +#endif // Q_CREATE_INSTANCE + +# ifdef Q_WS_WIN +# ifdef Q_CC_BOR +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + Q_EXTERN_C __declspec(dllexport) \ + const char * __stdcall qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + Q_EXTERN_C __declspec(dllexport) QUnknownInterface* \ + __stdcall ucm_instantiate() +# else +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + Q_EXTERN_C __declspec(dllexport) \ + const char *qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + Q_EXTERN_C __declspec(dllexport) QUnknownInterface* ucm_instantiate() +# endif +# else +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + Q_EXTERN_C \ + const char *qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + Q_EXTERN_C QUnknownInterface* ucm_instantiate() +# endif +# define Q_EXPORT_INTERFACE() Q_EXPORT_COMPONENT() +#endif + +#endif //QT_NO_COMPONENT + +#endif //QCOM_H diff --git a/qmake/include/private/qcomlibrary_p.h b/qmake/include/private/qcomlibrary_p.h new file mode 100644 index 0000000..f52f679 --- a/dev/null +++ b/qmake/include/private/qcomlibrary_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QComLibrary class +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QUCOMLIBRARY_H +#define QUCOMLIBRARY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qcom_p.h" +#include "qlibrary.h" +#endif // QT_H + +#ifndef QT_NO_COMPONENT + +class Q_EXPORT QComLibrary : public QLibrary +{ +public: + QComLibrary( const QString &filename ); + ~QComLibrary(); + + bool unload(); + QRESULT queryInterface( const QUuid &iid, QUnknownInterface **iface ); + uint qtVersion(); + +private: + void createInstanceInternal(); + + QUnknownInterface *entry; + QLibraryInterface *libiface; + uint qt_version; + +}; + +#endif //QT_NO_COMPONENT + +#endif // QUCOMLIBRARY_H diff --git a/qmake/include/private/qcomplextext_p.h b/qmake/include/private/qcomplextext_p.h new file mode 100644 index 0000000..2132522 --- a/dev/null +++ b/qmake/include/private/qcomplextext_p.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** $Id$ +** +** Internal header file. +** +** Created : +** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCOMPLEXTEXT_H +#define QCOMPLEXTEXT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Remote Control. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include <qstring.h> +#include <qpointarray.h> +#include <qfont.h> +#include <qpainter.h> +#include <qptrlist.h> +#include <qshared.h> +#endif // QT_H + +#ifndef QT_NO_COMPLEXTEXT + +// bidi helper classes. Internal to Qt +struct Q_EXPORT QBidiStatus { + QBidiStatus() { + eor = QChar::DirON; + lastStrong = QChar::DirON; + last = QChar:: DirON; + } + QChar::Direction eor; + QChar::Direction lastStrong; + QChar::Direction last; +}; + +struct Q_EXPORT QBidiContext : public QShared { + // ### ref and deref parent? + QBidiContext( uchar level, QChar::Direction embedding, QBidiContext *parent = 0, bool override = FALSE ); + ~QBidiContext(); + + unsigned char level; + bool override : 1; + QChar::Direction dir : 5; + + QBidiContext *parent; +}; + +struct Q_EXPORT QBidiControl { + QBidiControl() { context = 0; } + QBidiControl( QBidiContext *c, QBidiStatus s) + { context = c; if( context ) context->ref(); status = s; } + ~QBidiControl() { if ( context && context->deref() ) delete context; } + void setContext( QBidiContext *c ) { if ( context == c ) return; if ( context && context->deref() ) delete context; context = c; context->ref(); } + QBidiContext *context; + QBidiStatus status; +}; + +struct Q_EXPORT QTextRun { + QTextRun(int _start, int _stop, QBidiContext *context, QChar::Direction dir); + + int start; + int stop; + // explicit + implicit levels here + uchar level; +}; + +class Q_EXPORT QComplexText { +public: + static QString shapedString( const QString &str, int from = 0, int len = -1, QPainter::TextDirection dir = QPainter::Auto, const QFontMetrics *fm = 0); + static QChar shapedCharacter(const QString &str, int pos, const QFontMetrics *fm = 0); + + // positions non spacing marks relative to the base character at position pos. + static QPointArray positionMarks( QFontPrivate *f, const QString &str, int pos, QRect *boundingRect = 0 ); + + static QPtrList<QTextRun> *bidiReorderLine( QBidiControl *control, const QString &str, int start, int len, + QChar::Direction basicDir = QChar::DirON ); + static QString bidiReorderString( const QString &str, QChar::Direction basicDir = QChar::DirON ); +}; + + +#endif //QT_NO_COMPLEXTEXT + +#endif diff --git a/qmake/include/private/qcomponentfactory_p.h b/qmake/include/private/qcomponentfactory_p.h new file mode 100644 index 0000000..1ac973f --- a/dev/null +++ b/qmake/include/private/qcomponentfactory_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the QComponentFactory class +** +** Created : 990101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCOMPONENTFACTORY_H +#define QCOMPONENTFACTORY_H + +#ifndef QT_H +#include "qcom_p.h" +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_NO_COMPONENT + +class Q_EXPORT QComponentFactory +{ +public: + static QRESULT createInstance( const QString &cid, const QUuid &iid, QUnknownInterface** instance, QUnknownInterface *outer = 0 ); + static QRESULT registerServer( const QString &filename ); + static QRESULT unregisterServer( const QString &filename ); + + static bool registerComponent( const QUuid &cid, const QString &filename, const QString &name = QString::null, + int version = 0, const QString &description = QString::null ); + static bool unregisterComponent( const QUuid &cid ); +}; + +#endif // QT_NO_COMPONENT + +#endif // QCOMPONENTFACTORY_H diff --git a/qmake/include/private/qcriticalsection_p.h b/qmake/include/private/qcriticalsection_p.h new file mode 100644 index 0000000..7d9feca --- a/dev/null +++ b/qmake/include/private/qcriticalsection_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QCriticalSection class +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCRITICALSECTION_H +#define QCRITICALSECTION_H + +#ifndef QT_H +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Remote Control. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#if defined(QT_THREAD_SUPPORT) + +#if defined(Q_WS_WIN) + +/* + QCriticalSection +*/ + +class QCriticalSectionPrivate; + +class QCriticalSection +{ +public: + QCriticalSection(); + ~QCriticalSection(); + void enter(); + void leave(); + +private: + QCriticalSectionPrivate *d; +}; + +#endif + +#endif + +#endif diff --git a/qmake/include/private/qdir_p.h b/qmake/include/private/qdir_p.h new file mode 100644 index 0000000..35dba28 --- a/dev/null +++ b/qmake/include/private/qdir_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some private QDir functions. +** +** Created : 2000.11.06 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QDIR_P_H +#define QDIR_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qdir.cpp and qdir_*.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#endif // QT_H + +extern QStringList qt_makeFilterList( const QString & ); + + +extern int qt_cmp_si_sortSpec; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +#ifdef Q_OS_TEMP +extern int __cdecl qt_cmp_si( const void *, const void * ); +#else +extern int qt_cmp_si( const void *, const void * ); +#endif + +#if defined(Q_C_CALLBACKS) +} +#endif + + +#endif // QDIR_P_H diff --git a/qmake/include/private/qeffects_p.h b/qmake/include/private/qeffects_p.h new file mode 100644 index 0000000..4178b6f --- a/dev/null +++ b/qmake/include/private/qeffects_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QEffects functions +** +** Created : 2000.06.21 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QEFFECTS_P_H +#define QEFFECTS_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qeffects.cpp, qcombobox.cpp, qpopupmenu.cpp and qtooltip.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qnamespace.h" +#endif // QT_H + +#ifndef QT_NO_EFFECTS +class QWidget; + +struct QEffects +{ + enum Direction { + LeftScroll = 0x0001, + RightScroll = 0x0002, + UpScroll = 0x0004, + DownScroll = 0x0008 + }; + + typedef uint DirFlags; +}; + +extern void Q_EXPORT qScrollEffect( QWidget*, QEffects::DirFlags dir = QEffects::DownScroll, int time = -1 ); +extern void Q_EXPORT qFadeEffect( QWidget*, int time = -1 ); +#endif // QT_NO_EFFECTS + +#endif // QEFFECTS_P_H diff --git a/qmake/include/private/qeventloop_p.h b/qmake/include/private/qeventloop_p.h new file mode 100644 index 0000000..b64d0df --- a/dev/null +++ b/qmake/include/private/qeventloop_p.h @@ -0,0 +1,74 @@ +#ifndef QEVENTLOOP_P_H +#define QEVENTLOOP_P_H + +#include "qplatformdefs.h" +#include "qwindowdefs.h" + +class QSocketNotifier; + +#if defined(Q_OS_UNIX) +#include <qptrlist.h> + +struct QSockNot +{ + QSocketNotifier *obj; + int fd; + fd_set *queue; +}; + +class QSockNotType +{ +public: + QSockNotType(); + ~QSockNotType(); + + QPtrList<QSockNot> *list; + fd_set select_fds; + fd_set enabled_fds; + fd_set pending_fds; + +}; +#endif // Q_OS_UNIX + + +class QEventLoopPrivate +{ +public: + QEventLoopPrivate() + { + reset(); + } + + void reset() { + looplevel = 0; + quitcode = 0; + quitnow = FALSE; + exitloop = FALSE; + } + + int looplevel; + int quitcode; + bool quitnow; + bool exitloop; + +#if defined(Q_WS_MAC) + EventLoopTimerRef select_timer; +#endif + +#if defined(Q_WS_X11) + int xfd; +#endif // Q_WS_X11 + +#if defined(Q_OS_UNIX) + int thread_pipe[2]; + + // pending socket notifiers list + QPtrList<QSockNot> sn_pending_list; + // highest fd for all socket notifiers + int sn_highest; + // 3 socket notifier types - read, write and exception + QSockNotType sn_vec[3]; +#endif +}; + +#endif // QEVENTLOOP_P_H diff --git a/qmake/include/private/qfiledefs_p.h b/qmake/include/private/qfiledefs_p.h new file mode 100644 index 0000000..627717f --- a/dev/null +++ b/qmake/include/private/qfiledefs_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** $Id$ +** +** Common macros and system include files for QFile, QFileInfo and QDir. +** +** Created : 930812 +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QFILEDEFS_P_H +#define QFILEDEFS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qfileinfo*.cpp. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +// Be sure to include qplatformdefs.h first! +struct QFileInfoCache +{ +#if defined(Q_WS_WIN) + QT_STATBUF st; +#else + struct stat st; +#endif +}; + + +#endif diff --git a/qmake/include/private/qfontcodecs_p.h b/qmake/include/private/qfontcodecs_p.h new file mode 100644 index 0000000..8222f98 --- a/dev/null +++ b/qmake/include/private/qfontcodecs_p.h @@ -0,0 +1,368 @@ +/**************************************************************************** +** $Id$ +** +** Font utilities for X11 +** +** Created : 20001101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QFONTCODECS_P_H +#define QFONTCODECS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qfontencodings_x11.cpp and qfont_x11.cpp. This header file may +// change from version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include <qglobal.h> +#include <qtextcodec.h> +#endif // QT_H + + +#ifndef QT_NO_CODECS +#ifndef QT_NO_BIG_CODECS + + +class QJpUnicodeConv; + + +class QFontJis0201Codec : public QTextCodec +{ +public: + QFontJis0201Codec(); + + const char *name() const; + + int mibEnum() const; + +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + int heuristicNameMatch(const char* hint) const; + +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; +}; + + +class QFontJis0208Codec : public QTextCodec +{ +public: + QFontJis0208Codec(); + ~QFontJis0208Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + int heuristicNameMatch(const char* hint) const; + +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; + +private: + QJpUnicodeConv *convJP; +}; + + + + +class QFontKsc5601Codec : public QTextCodec +{ +public: + QFontKsc5601Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; +}; + + + + +class QFontGb2312Codec : public QTextCodec +{ +public: + QFontGb2312Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + bool canEncode( QChar ) const; +}; + + + + +class QFontGbkCodec : public QTextCodec +{ +public: + QFontGbkCodec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + int heuristicNameMatch(const char* hint) const; + bool canEncode( QChar ) const; +}; + + + + +class QFontGb18030_0Codec : public QTextCodec +{ +public: + QFontGb18030_0Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; +}; + + + + +class QFontBig5Codec : public QTextCodec +{ +public: + QFontBig5Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + int heuristicNameMatch(const char* hint) const; + bool canEncode( QChar ) const; +}; + + + +class QFontBig5hkscsCodec : public QTextCodec +{ +public: + QFontBig5hkscsCodec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + int heuristicNameMatch(const char* hint) const; +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; +}; + + + + +// ------------------------------------------------------------------ +// the shaping codec for iso8859-6.8x fonts (see www.langbox.com) + +class QFontArabic68Codec : public QTextCodec +{ +public: + QFontArabic68Codec(); + + // Return the official name for the encoding. + const char* name() const ; + + // Return the MIB enum for the encoding if it is listed in the + // IANA character-sets encoding file. + int mibEnum() const ; + + // Converts len characters from chars to Unicode. + QString toUnicode(const char* chars, int len) const ; + + // Converts lenInOut characters (of type QChar) from the start of + // the string uc, returning a QCString result, and also returning + // the length of the result in lenInOut. + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + QByteArray fromUnicode( const QString &str, int from, int len ) const; + unsigned short characterFromUnicode(const QString &str, int pos) const; +}; + + +class QFontLaoCodec : public QTextCodec +{ +public: + QFontLaoCodec(); + + const char *name() const; + + int mibEnum() const; + +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::fromUnicode; +#endif + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + int heuristicContentMatch(const char *, int) const; + +#if !defined(Q_NO_USING_KEYWORD) + using QTextCodec::canEncode; +#endif + bool canEncode( QChar ) const; +}; + +#endif // QT_NO_BIG_CODECS +#endif // QT_NO_CODECS + +#endif // QFONTCODECS_P_H diff --git a/qmake/include/private/qfontdata_p.h b/qmake/include/private/qfontdata_p.h new file mode 100644 index 0000000..917d14f --- a/dev/null +++ b/qmake/include/private/qfontdata_p.h @@ -0,0 +1,479 @@ +/**************************************************************************** +** $Id$ +** +** Definition of internal QFontData struct +** +** Created : 941229 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QFONTDATA_P_H +#define QFONTDATA_P_H + +#ifndef QT_H +#include <qcache.h> +#include <qobject.h> +#include <qpaintdevice.h> +#endif // QT_H +#include <limits.h> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +class QPaintDevice; + +#ifdef Q_WS_WIN +#include <qt_windows.h> +#endif + +#ifdef Q_WS_X11 +#include <qt_x11.h> + +class QCharStruct; +#endif + +// font description +struct QFontDef { + QFontDef() + : pixelSize(0), pointSize(0), lbearing(SHRT_MIN), rbearing(SHRT_MIN), + styleStrategy(QFont::PreferDefault), styleHint(QFont::AnyStyle), + weight(0), italic(FALSE), underline(FALSE), strikeOut(FALSE), + fixedPitch(FALSE), hintSetByUser(FALSE), rawMode(FALSE), dirty(TRUE) + { ; } + + QString family; + QString addStyle; + + int pixelSize; + int pointSize; + short lbearing; + short rbearing; + + ushort styleStrategy; + uchar styleHint; + uchar weight; + + bool italic; + bool underline; + bool strikeOut; + bool fixedPitch; + bool hintSetByUser; + bool rawMode; + + bool dirty; +}; + + +class QTextCodec; + +#ifdef Q_WS_X11 + +// this is a shared wrapper for XFontStruct (to prevent a font being freed by +// the cache while it's being used) +class QFontStruct : public QShared +{ +public: + QFontStruct(Qt::HANDLE h, Qt::HANDLE xfth, Qt::HANDLE xftp, + QCString n, QTextCodec *c, int a) : + QShared(), handle(h), xfthandle(xfth), xftpattern(xftp), + name(n), codec(c), cache_cost(a), scale( 1. ) + { ; } + + ~QFontStruct(); + + Qt::HANDLE handle, xfthandle, xftpattern; + QCString name; + QTextCodec *codec; + int cache_cost; + float scale; // needed for printing, to correctly scale font metrics for bitmap fonts +}; + +enum { widthCacheSize = 0x500 }; + +class QFontX11Data // used as a QFontPrivate member +{ +public: + // X fontstruct handles for each character set + QFontStruct *fontstruct[QFont::LastPrivateScript]; + + uchar widthCache[widthCacheSize]; + + QFontX11Data(); + ~QFontX11Data(); +}; + +#endif // Q_WS_X11 + + +#ifdef Q_WS_WIN + +class QFontStruct : public QShared +{ +public: + QFontStruct( const QString &key ); + ~QFontStruct() { reset(); } + bool dirty() const { return hfont == 0; } + HDC dc() const; + HFONT font() const { return hfont; } + const TEXTMETRICA *textMetricA() const { return &tm.a; } + const TEXTMETRICW *textMetricW() const { return &tm.w; } + QString key() const { return k; } + void reset(); + + QString k; + HDC hdc; + HFONT hfont; + uint stockFont:1; + uint paintDevice:1; + union { + TEXTMETRICW w; + TEXTMETRICA a; + } tm; + int lw; + int cache_cost; +// friend void QFont::initFontInfo() const; +}; + +#endif // Q_WS_WIN + +#if defined( Q_WS_MAC ) + +#if defined( Q_WS_MACX ) +# define QMAC_FONT_ATSUI +#endif +#include "qt_mac.h" +class QMacFontInfo; + +class QFontStruct : public QShared +{ +public: + inline QFontStruct() : QShared(), info(NULL), fnum(-1), cache_cost(0), internal_fi(NULL) { } +#if defined( QMAC_FONT_ATSUI ) && 0 + ATSFontMetrics *info; + int maxWidth() const { return (int)info->maxAdvanceWidth; } +#else + FontInfo *info; + int maxWidth() const { return info->widMax; } +#endif + int ascent() const { return (int)info->ascent; } + int descent() const { return (int)info->descent; } + int leading() const { return (int)info->leading; } + int minLeftBearing() const { return 0; } + int minRightBearing() const { return 0; } + + short fnum; + int psize, cache_cost; + QMacFontInfo *internal_fi; +}; + +#endif + +#ifdef Q_WS_QWS +class QFontStruct; +class QGfx; +#endif + +typedef QCacheIterator<QFontStruct> QFontCacheIterator; +class QFontCache : public QObject, public QCache<QFontStruct> +{ +public: + QFontCache(); + ~QFontCache(); + + bool insert(const QString &, const QFontStruct *, int c); +#ifndef Q_WS_MAC + void deleteItem(Item d); +#endif + void timerEvent(QTimerEvent *); + + +protected: + + +private: + int timer_id; + bool fast; +}; + + +// QFontPrivate - holds all data on which a font operates +class QFontPrivate : public QShared +{ +public: + static QFontCache *fontCache; + + +public: + + QFontPrivate(); + QFontPrivate(const QFontPrivate &fp); + QFontPrivate( const QFontPrivate &fp, QPaintDevice *pd ); + ~QFontPrivate(); + + // requested font + QFontDef request; + // actual font + QFontDef actual; + + bool exactMatch; + int lineWidth; + + // common functions + QString defaultFamily() const; + QString lastResortFamily() const; + QString lastResortFont() const; + QString key() const; + + static int getFontWeight(const QCString &, bool = FALSE); + QRect boundingRect( const QChar &ch ); + + struct TextRun { + TextRun() + { + xoff = 0; + yoff = 0; + x2off = 0; + script = QFont::NoScript; + string = 0; + length = 0; + next = 0; + } + + ~TextRun() + { + if ( next ) + delete next; + } + + void setParams( int x, int y, int x2, const QChar *s, int len, + QFont::Script sc = QFont::NoScript ) { + xoff = x; + yoff = y; + x2off = x2; + string = s; + length = len; + script = sc; + } + int xoff; + int yoff; + int x2off; + QFont::Script script; + const QChar *string; + int length; + TextRun *next; +#ifdef Q_WS_X11 + QByteArray mapped; +#endif + }; + + // some replacement functions for native calls. This is needed, because shaping and + // non spacing marks can change the extents of a string to draw. At the same time + // drawing needs to take care to correctly position non spacing marks. + int textWidth( const QString &str, int pos, int len ); + + // returns the script a certain character is in. Needed to separate the string + // into runs of different scripts as required for X11 and opentype. + QFont::Script scriptForChar(const QChar &c); + +#ifdef Q_WS_X11 + QFont::Script hanHack( const QChar & c ); + static char **getXFontNames(const char *, int *); + static bool fontExists(const QString &); + static bool parseXFontName(char *, char **); + static QCString fixXLFD( const QCString & ); + static bool fillFontDef(XFontStruct *, QFontDef *, int); + static bool fillFontDef(const QCString &, QFontDef *, int); + + static inline bool isZero(char *x) + { + return (x[0] == '0' && x[1] == 0); + } + + static inline bool isScalable( char **tokens ) + { + return (isZero(tokens[PixelSize]) && + isZero(tokens[PointSize]) && + isZero(tokens[AverageWidth])); + } + + static inline bool isSmoothlyScalable( char **tokens ) + { + return (isZero(tokens[ResolutionX]) && isZero(tokens[ResolutionY])); + } + + static inline bool isFixedPitch( char **tokens ) + { + return (tokens[Spacing][0] == 'm' || + tokens[Spacing][0] == 'c' || + tokens[Spacing][0] == 'M' || + tokens[Spacing][0] == 'C'); + } + + // XLFD fields + enum FontFieldNames { + Foundry, + Family, + Weight, + Slant, + Width, + AddStyle, + PixelSize, + PointSize, + ResolutionX, + ResolutionY, + Spacing, + AverageWidth, + CharsetRegistry, + CharsetEncoding, + NFontFields + }; + +#ifndef QT_NO_XFTFREETYPE + XftPattern *findXftFont(const QChar &, bool *, double *scale) const; + XftPattern *bestXftPattern(const QString &, const QString &, const QChar &, double *scale) const; +#endif // QT_NO_XFTFREETYPE + QCString findFont(QFont::Script, bool *, double *) const; + QCString bestFamilyMember(QFont::Script, const QString &, const QString &, + const QString &, int *, double *) const; + QCString bestMatch(const char *, int *, QFont::Script, double *) const; + int fontMatchScore(const char *, QCString &, float *, int *, bool *, + bool *, QFont::Script, double *) const; + void initFontInfo(QFont::Script, double scale); + void load(QFont::Script = QFont::NoScript, bool = TRUE); + bool loadUnicode(QFont::Script, const QChar &); + void computeLineWidth(); + + int textWidth( const QString &str, int pos, int len, TextRun *cache ); + void textExtents( const QString &str, int pos, int len, QCharStruct *overall ); + void drawText( Display *dpy, int screen, Qt::HANDLE hd, Qt::HANDLE rendhd, + GC gc, const QColor &pen, Qt::BGMode, const QColor &bgcolor, + int x, int y, const TextRun *cache, int pdWidth ); + bool inFont( const QChar &ch ); + + QFontX11Data x11data; + static QFont::Script defaultScript; + int x11Screen; +#endif // Q_WS_X11 + + QPaintDevice *paintdevice; + +#ifdef Q_WS_WIN + void load(); + void initFontInfo(); + HFONT create( bool *stockFont, HDC hdc = 0, bool compatMode = FALSE ); + QFontStruct *fin; + + void buildCache( HDC hdc, const QString &str, int pos, int len, TextRun *cache ); + void drawText( HDC hdc, int x, int y, TextRun *cache ); +#endif // Q_WS_WIN + +#ifdef Q_WS_QWS + void load(); + QFontStruct *fin; + int textWidth( const QString &str, int pos, int len, TextRun *cache ); + void drawText( QGfx *gfx, int x, int y, const TextRun *cache ); +#endif + +#if defined( Q_WS_MAC ) + void macSetFont(QPaintDevice *); + void drawText(int x, int y, QString s, int len, QPaintDevice *dev, const QRegion *rgn); + void computeLineWidth(); + void load(); + QFontStruct *fin; +#endif + +}; + +inline QFontPrivate::QFontPrivate() + : QShared(), exactMatch(FALSE), lineWidth(1) +{ + +#if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) + fin = 0; +#endif // Q_WS_WIN || Q_WS_QWS +#if defined(Q_WS_X11) + x11Screen = QPaintDevice::x11AppScreen(); +#endif // Q_WS_X11 + paintdevice = 0; +} + +inline QFontPrivate::QFontPrivate(const QFontPrivate &fp) + : QShared(), request(fp.request), actual(fp.actual), +exactMatch(fp.exactMatch), lineWidth(1) +{ + Q_ASSERT(!fp.paintdevice); +#if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) + fin = 0; +#endif // Q_WS_WIN || Q_WS_QWS +#if defined(Q_WS_X11) + x11Screen = fp.x11Screen; +#endif // Q_WS_X11 + paintdevice = 0; +} + +inline QFontPrivate::QFontPrivate( const QFontPrivate &fp, QPaintDevice *pd ) + : QShared(), request(fp.request), actual(fp.actual), +exactMatch(fp.exactMatch), lineWidth(1) +{ + +#if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) + fin = 0; +#endif // Q_WS_WIN || Q_WS_QWS +#if defined(Q_WS_X11) + x11Screen = pd->x11Screen(); +#endif // Q_WS_X11 + paintdevice = pd; +} + +#ifndef Q_WS_QWS +inline QFontPrivate::~QFontPrivate() +{ +#if defined(Q_WS_WIN) + if( fin ) + fin->deref(); +#endif +#if defined(Q_WS_MAC) + if( fin && fin->deref() ) + delete fin; +#endif +} +#endif + +#endif // QFONTDATA_P_H diff --git a/qmake/include/private/qgfxdriverinterface_p.h b/qmake/include/private/qgfxdriverinterface_p.h new file mode 100644 index 0000000..1782ed4 --- a/dev/null +++ b/qmake/include/private/qgfxdriverinterface_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** $Id$ +** +** Definition of Qt/Embedded Graphics Driver Interface +** +** Created : 20020211 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGFXDRIVERINTERFACE_H +#define QGFXDRIVERINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#ifndef QT_NO_COMPONENT + +// {449EC6C6-DF3E-43E3-9E57-354A3D05AB34} +#ifndef IID_QGfxDriver +#define IID_QGfxDriver QUuid( 0x449ec6c6, 0xdf3e, 0x43e3, 0x9e, 0x57, 0x35, 0x4a, 0x3d, 0x05, 0xab, 0x34) +#endif + +class QScreen; + +struct Q_EXPORT QGfxDriverInterface : public QFeatureListInterface +{ + virtual QScreen* create( const QString& driver, int displayId ) = 0; +}; + +#endif // QT_NO_COMPONENT + +#endif // QGFXDRIVERINTERFACE_H diff --git a/qmake/include/private/qgpluginmanager_p.h b/qmake/include/private/qgpluginmanager_p.h new file mode 100644 index 0000000..e0c0e78 --- a/dev/null +++ b/qmake/include/private/qgpluginmanager_p.h @@ -0,0 +1,107 @@ +/********************************************************************** +** $Id$ +** +** Definition of QGPluginManager class +** +** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGPLUGINMANAGER_H +#define QGPLUGINMANAGER_H + +#ifndef QT_H +#include "qdict.h" +#include "qlibrary.h" +#include "quuid.h" +#include "qstringlist.h" +#include "qcom_p.h" +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_NO_COMPONENT + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QLibrary>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QGPluginManager +{ +public: + QGPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ); + ~QGPluginManager(); + + void addLibraryPath( const QString& path ); + const QLibrary* library( const QString& feature ) const; + QStringList featureList() const; + + bool autoUnload() const; + void setAutoUnload( bool ); + +protected: + bool enabled() const; + bool addLibrary( QLibrary* plugin ); + + QRESULT queryUnknownInterface(const QString& feature, QUnknownInterface** iface) const; + + QUuid interfaceId; + QDict<QLibrary> plugDict; // Dict to match feature with library + QDict<QLibrary> libDict; // Dict to match library file with library + QStringList libList; + + uint casesens : 1; + uint autounload : 1; +}; + +inline void QGPluginManager::setAutoUnload( bool unload ) +{ + autounload = unload; +} + +inline bool QGPluginManager::autoUnload() const +{ + return autounload; +} + +#endif + +#endif //QGPLUGINMANAGER_H diff --git a/qmake/include/private/qimageformatinterface_p.h b/qmake/include/private/qimageformatinterface_p.h new file mode 100644 index 0000000..5f7601c --- a/dev/null +++ b/qmake/include/private/qimageformatinterface_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ??? +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QIMAGEFORMATINTERFACE_H +#define QIMAGEFORMATINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_NO_COMPONENT + +// {04903F05-54B1-4726-A849-FB5CB097CA87} +#ifndef IID_QImageFormat +#define IID_QImageFormat QUuid( 0x04903f05, 0x54b1, 0x4726, 0xa8, 0x49, 0xfb, 0x5c, 0xb0, 0x97, 0xca, 0x87 ) +#endif + +class QImage; + +struct Q_EXPORT QImageFormatInterface : public QFeatureListInterface +{ + virtual QRESULT loadImage( const QString &format, const QString &filename, QImage * ) = 0; + virtual QRESULT saveImage( const QString &format, const QString &filename, const QImage & ) = 0; + + virtual QRESULT installIOHandler( const QString & ) = 0; +}; + +#endif // QT_NO_COMPONENT + +#endif // QIMAGEFORMATINTERFACE_H diff --git a/qmake/include/private/qinputcontext_p.h b/qmake/include/private/qinputcontext_p.h new file mode 100644 index 0000000..9ac0d2b --- a/dev/null +++ b/qmake/include/private/qinputcontext_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ??? +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINPUTCONTEXT_P_H +#define QINPUTCONTEXT_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +#include <qglobal.h> + +class QKeyEvent; +class QWidget; +class QFont; +class QString; + + +#ifdef Q_WS_X11 +#include "qarray.h" +#include "qwindowdefs.h" +#include "qt_x11.h" +#endif + +#ifdef Q_WS_WIN +#include <qt_windows.h> +#endif + +#ifdef Q_WS_QWS +class QWSIMEvent; +#endif + +class QInputContext +{ +public: +#ifdef Q_WS_X11 + QInputContext(QWidget *); // should be a toplevel widget + ~QInputContext(); + + void setFocus(); + void setComposePosition(int, int); + void setComposeArea(int, int, int, int); + void reset(); + + int lookupString(XKeyEvent *, QCString &, KeySym *, Status *) const; + void setXFontSet(const QFont &); + + void *ic; + QString text, lastcompose; + QWidget *focusWidget; + bool composing; + QFont font; + XFontSet fontset; + QMemArray<bool> selectedChars; +#endif // Q_WS_X11 + +#ifdef Q_WS_QWS + static void translateIMEvent( QWSIMEvent *, QWidget * ); + static void reset(); +private: + static QWidget* focusWidget; + static QString* composition; +#endif //Q_WS_QWS + +#ifdef Q_WS_WIN + static void init(); + static void shutdown(); + + static void TranslateMessage( const MSG *msg); + static LRESULT DefWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); + + static void setFont( const QWidget *w, const QFont & ); + static void setFocusHint( int x, int y, int w, int h, const QWidget *widget ); + static bool startComposition(); + static bool endComposition( QWidget *fw = 0 ); + static bool composition( LPARAM lparam ); +#endif +}; + +#endif // QINPUTCONTEXT_P_H diff --git a/qmake/include/private/qinternal_p.h b/qmake/include/private/qinternal_p.h new file mode 100644 index 0000000..ae38695 --- a/dev/null +++ b/qmake/include/private/qinternal_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some shared interal classes +** +** Created : 010427 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINTERNAL_P_H +#define QINTERNAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// +#ifndef QT_H +#include <qnamespace.h> +#include <qrect.h> +#endif // QT_H + +class QWidget; +class QPainter; +class QPixmap; + +class Q_EXPORT QSharedDoubleBuffer +{ +public: + enum DoubleBufferFlags { + NoFlags = 0x00, + InitBG = 0x01, + Force = 0x02, + Default = InitBG | Force + }; + typedef uint DBFlags; + + QSharedDoubleBuffer( DBFlags f = Default ); + QSharedDoubleBuffer( QWidget* widget, + int x = 0, int y = 0, int w = -1, int h = -1, + DBFlags f = Default ); + QSharedDoubleBuffer( QPainter* painter, + int x = 0, int y = 0, int w = -1, int h = -1, + DBFlags f = Default ); + QSharedDoubleBuffer( QWidget *widget, const QRect &r, DBFlags f = Default ); + QSharedDoubleBuffer( QPainter *painter, const QRect &r, DBFlags f = Default ); + ~QSharedDoubleBuffer(); + + bool begin( QWidget* widget, int x = 0, int y = 0, int w = -1, int h = -1 ); + bool begin( QPainter* painter, int x = 0, int y = 0, int w = -1, int h = -1); + bool begin( QWidget* widget, const QRect &r ); + bool begin( QPainter* painter, const QRect &r ); + bool end(); + + QPainter* painter() const; + + bool isActive() const; + bool isBuffered() const; + void flush(); + + static bool isDisabled() { return !dblbufr; } + static void setDisabled( bool off ) { dblbufr = !off; } + + static void cleanup(); + +private: + enum DoubleBufferState { + Active = 0x0100, + BufferActive = 0x0200, + ExternalPainter = 0x0400 + }; + typedef uint DBState; + + QPixmap *getPixmap(); + void releasePixmap(); + + QWidget *wid; + int rx, ry, rw, rh; + DBFlags flags; + DBState state; + + QPainter *p, *external_p; + QPixmap *pix; + + static bool dblbufr; +}; + +inline bool QSharedDoubleBuffer::begin( QWidget* widget, const QRect &r ) +{ return begin( widget, r.x(), r.y(), r.width(), r.height() ); } + +inline bool QSharedDoubleBuffer::begin( QPainter *painter, const QRect &r ) +{ return begin( painter, r.x(), r.y(), r.width(), r.height() ); } + +inline QPainter* QSharedDoubleBuffer::painter() const +{ return p; } + +inline bool QSharedDoubleBuffer::isActive() const +{ return ( state & Active ); } + +inline bool QSharedDoubleBuffer::isBuffered() const +{ return ( state & BufferActive ); } + + +class QVirtualDestructor { +public: + virtual ~QVirtualDestructor() {} +}; + +template <class T> +class QAutoDeleter : public QVirtualDestructor { +public: + QAutoDeleter( T* p ) : ptr( p ) {} + ~QAutoDeleter() { delete ptr; } +private: + T* ptr; +}; + +template <class T> +QAutoDeleter<T>* qAutoDeleter( T* p ) +{ + return new QAutoDeleter<T>( p ); +} +#endif // QINTERNAL_P_H diff --git a/qmake/include/private/qkbddriverinterface_p.h b/qmake/include/private/qkbddriverinterface_p.h new file mode 100644 index 0000000..efc7ded --- a/dev/null +++ b/qmake/include/private/qkbddriverinterface_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** $Id$ +** +** Definition of Qt/Embedded Keyboard Driver Interface +** +** Created : 20020218 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QKBDDRIVERINTERFACE_H +#define QKBDDRIVERINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#ifndef QT_NO_COMPONENT + +// {C7C838EA-FC3E-4905-92AD-F479E81F1D02} +#ifndef IID_QKbdDriver +#define IID_QKbdDriver QUuid( 0xc7c838ea, 0xfc3e, 0x4905, 0x92, 0xad, 0xf4, 0x79, 0xe8, 0x1f, 0x1d, 0x02) +#endif + +class QWSKeyboardHandler; + +struct Q_EXPORT QKbdDriverInterface : public QFeatureListInterface +{ + virtual QWSKeyboardHandler* create( const QString& driver, const QString& device ) = 0; +}; + +#endif // QT_NO_COMPONENT + +#endif // QKBDDRIVERINTERFACE_H diff --git a/qmake/include/private/qlayoutengine_p.h b/qmake/include/private/qlayoutengine_p.h new file mode 100644 index 0000000..4d88afe --- a/dev/null +++ b/qmake/include/private/qlayoutengine_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** $Id$ +** +** Internal header file. +** +** Created : 981027 +** +** Copyright (C) 1998-99 by Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLAYOUTENGINE_P_H +#define QLAYOUTENGINE_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qlayout.cpp, qlayoutengine.cpp, qmainwindow.cpp and qsplitter.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qabstractlayout.h" +#endif // QT_H + +#ifndef QT_NO_LAYOUT + +struct QLayoutStruct +{ + void initParameters() { + minimumSize = sizeHint = 0; + maximumSize = QLAYOUTSIZE_MAX; + expansive = FALSE; + empty = TRUE; + } + void init() { + stretch = 0; + initParameters(); + } + + QCOORD smartSizeHint() { + return ( stretch > 0 ) ? minimumSize : sizeHint; + } + + // permanent storage + int stretch; + + // parameters + QCOORD sizeHint; + QCOORD maximumSize; + QCOORD minimumSize; + bool expansive; + bool empty; + + // temporary storage + bool done; + + // result + int pos; + int size; +}; + + +Q_EXPORT void qGeomCalc( QMemArray<QLayoutStruct> &chain, int start, int count, + int pos, int space, int spacer ); +Q_EXPORT QSize qSmartMinSize( const QWidgetItem *i ); +Q_EXPORT QSize qSmartMinSize( QWidget *w ); +Q_EXPORT QSize qSmartMaxSize( const QWidgetItem *i, int align = 0 ); +Q_EXPORT QSize qSmartMaxSize( QWidget *w, int align = 0 ); + + +/* + Modify total maximum (max) and total expansion (exp) + when adding boxmax/boxexp. + + Expansive boxes win over non-expansive boxes. +*/ +static inline void qMaxExpCalc( QCOORD & max, bool &exp, + QCOORD boxmax, bool boxexp ) +{ + if ( exp ) { + if ( boxexp ) + max = QMAX( max, boxmax ); + } else { + if ( boxexp ) + max = boxmax; + else + max = QMIN( max, boxmax ); + } + exp = exp || boxexp; +} + +#endif //QT_NO_LAYOUT +#endif diff --git a/qmake/include/private/qlibrary_p.h b/qmake/include/private/qlibrary_p.h new file mode 100644 index 0000000..c4dd565 --- a/dev/null +++ b/qmake/include/private/qlibrary_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** $Id$ +** +** Definition of an internal QLibrary class +** +** Created : 2000-01-01 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLIBRARY_P_H +#define QLIBRARY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#include "qlibrary.h" + +#ifndef QT_NO_LIBRARY + +#ifndef QT_H +#if defined(Q_CC_GNU) +#warning "avoid including header file \"qwindowdefs.h\" in directory 'tools'" +#endif +#include "qwindowdefs.h" +#endif // QT_H + +class QLibraryPrivate +{ +public: + QLibraryPrivate( QLibrary *lib ); + +#ifdef Q_WS_WIN + HINSTANCE pHnd; +#else + void *pHnd; +#endif + + bool loadLibrary(); + bool freeLibrary(); + void *resolveSymbol( const char * ); + +private: + QLibrary *library; +}; + +#endif // QT_NO_LIBRARY +#endif // QLIBRARY_P_H diff --git a/qmake/include/private/qmousedriverinterface_p.h b/qmake/include/private/qmousedriverinterface_p.h new file mode 100644 index 0000000..fd76308 --- a/dev/null +++ b/qmake/include/private/qmousedriverinterface_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** $Id$ +** +** Definition of Qt/Embedded Mouse Driver Interface +** +** Created : 20020220 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QMOUSEDRIVERINTERFACE_H +#define QMOUSEDRIVERINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#ifndef QT_NO_COMPONENT + +// {4367CF5A-F7CE-407B-8BB6-DF19AEDA2EBB} +#ifndef IID_QMouseDriver +#define IID_QMouseDriver QUuid( 0x4367cf5a, 0xf7ce, 0x407b, 0x8b, 0xb6, 0xdf, 0x19, 0xae, 0xda, 0x2e, 0xbb) +#endif + +class QWSMouseHandler; + +struct Q_EXPORT QMouseDriverInterface : public QFeatureListInterface +{ + virtual QWSMouseHandler* create( const QString& driver, const QString &device ) = 0; +}; + +#endif // QT_NO_COMPONENT + +#endif // QMOUSEDRIVERINTERFACE_H diff --git a/qmake/include/private/qmutex_p.h b/qmake/include/private/qmutex_p.h new file mode 100644 index 0000000..d4ce97a --- a/dev/null +++ b/qmake/include/private/qmutex_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** $Id$ +** +** QMutex private class declarations +** +** Created : 20012507 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QMUTEX_P_H +#define QMUTEX_P_H + +#ifndef QT_H +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qmutex_unix.cpp and qmutex_win.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// + +class QMutexPrivate { +public: + // Q_MUTEX_T is defined in the various *.cpp files + Q_MUTEX_T handle; + + virtual ~QMutexPrivate(); + + virtual void lock() = 0; + virtual void unlock() = 0; + virtual bool locked() = 0; + virtual bool trylock() = 0; + virtual int type() const = 0; +}; + + +#endif // QMUTEX_P_H diff --git a/qmake/include/private/qmutexpool_p.h b/qmake/include/private/qmutexpool_p.h new file mode 100644 index 0000000..3d9fef7 --- a/dev/null +++ b/qmake/include/private/qmutexpool_p.h @@ -0,0 +1,39 @@ +#ifndef QMUTEXPOOL_H +#define QMUTEXPOOL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of QSettings. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifdef QT_THREAD_SUPPORT + +#include "qmutex.h" +#include "qmemarray.h" + +class QMutexPool +{ +public: + QMutexPool( bool recursive = FALSE, int size = 17 ); + ~QMutexPool(); + + QMutex *get( void *address ); + +private: + QMutex mutex; + QMemArray<QMutex*> mutexes; + bool recurs; +}; + +extern QMutexPool *qt_global_mutexpool; + +#endif // QT_THREAD_SUPPORT + +#endif // QMUTEXPOOL_H diff --git a/qmake/include/private/qpainter_p.h b/qmake/include/private/qpainter_p.h new file mode 100644 index 0000000..43f454e --- a/dev/null +++ b/qmake/include/private/qpainter_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some Qt private functions. +** +** Created : 000909 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPAINTER_P_H +#define QPAINTER_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qpainter.cpp and qfont.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#endif // QT_H + +extern void qt_format_text( const QFont& f, const QRect &r, + int tf, const QString& str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + QTextParag **internal, QPainter* painter ); + + +#endif diff --git a/qmake/include/private/qpluginmanager_p.h b/qmake/include/private/qpluginmanager_p.h new file mode 100644 index 0000000..4b64ba0 --- a/dev/null +++ b/qmake/include/private/qpluginmanager_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QPluginManager class +** +** Created : 2000-01-01 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPLUGINMANAGER_H +#define QPLUGINMANAGER_H + +#ifndef QT_H +#include "qgpluginmanager_p.h" +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_NO_COMPONENT + +template<class Type> +class QPluginManager : public QGPluginManager +{ +public: + QPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ) + : QGPluginManager( id, paths, suffix, cs ) {} + QRESULT queryInterface(const QString& feature, Type** iface) const + { + return queryUnknownInterface( feature, (QUnknownInterface**)iface ); + } +}; + +#endif //QT_NO_COMPONENT + +#endif //QPLUGINMANAGER_H diff --git a/qmake/include/private/qpsprinter_p.h b/qmake/include/private/qpsprinter_p.h new file mode 100644 index 0000000..27a4968 --- a/dev/null +++ b/qmake/include/private/qpsprinter_p.h @@ -0,0 +1,89 @@ +/********************************************************************** +** $Id$ +** +** Definition of internal QPSPrinter class. +** QPSPrinter implements PostScript (tm) output via QPrinter. +** +** Created : 940927 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPSPRINTER_P_H +#define QPSPRINTER_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qpsprinter.cpp and qprinter_x11.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qprinter.h" +#include "qtextstream.h" +#endif // QT_H + +#ifndef QT_NO_PRINTER + +struct QPSPrinterPrivate; + +class Q_EXPORT QPSPrinter : public QPaintDevice +{ +private: + // QPrinter uses these + QPSPrinter( QPrinter *, int ); + ~QPSPrinter(); + + bool cmd ( int, QPainter *, QPDevCmdParam * ); + + enum { NewPage = 100, AbortPrinting }; + + friend class QPrinter; +private: + // not used by QPrinter + QPSPrinterPrivate *d; + + // Disabled copy constructor and operator= + QPSPrinter( const QPSPrinter & ); + QPSPrinter &operator=( const QPSPrinter & ); +}; + +#endif // QT_NO_PRINTER + +#endif // QPSPRINTER_P_H diff --git a/qmake/include/private/qrichtext_p.h b/qmake/include/private/qrichtext_p.h new file mode 100644 index 0000000..8e29804 --- a/dev/null +++ b/qmake/include/private/qrichtext_p.h @@ -0,0 +1,2133 @@ +/**************************************************************************** +** $Id$ +** +** Definition of internal rich text classes +** +** Created : 990124 +** +** Copyright (C) 1999-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QRICHTEXT_P_H +#define QRICHTEXT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qstring.h" +#include "qptrlist.h" +#include "qrect.h" +#include "qfontmetrics.h" +#include "qintdict.h" +#include "qmap.h" +#include "qstringlist.h" +#include "qfont.h" +#include "qcolor.h" +#include "qsize.h" +#include "qvaluelist.h" +#include "qvaluestack.h" +#include "qobject.h" +#include "qdict.h" +#include "qpixmap.h" +#include "qstylesheet.h" +#include "qptrvector.h" +#include "qpainter.h" +#include "qlayout.h" +#include "qobject.h" +#include "private/qcomplextext_p.h" +#include "qapplication.h" +#endif // QT_H + +#ifndef QT_NO_RICHTEXT + +class QTextDocument; +class QTextString; +class QTextPreProcessor; +class QTextFormat; +class QTextCursor; +class QTextParagraph; +class QTextFormatter; +class QTextIndent; +class QTextFormatCollection; +class QStyleSheetItem; +#ifndef QT_NO_TEXTCUSTOMITEM +class QTextCustomItem; +#endif +class QTextFlow; +struct QBidiContext; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextStringChar +{ + friend class QTextString; + +public: + // this is never called, initialize variables in QTextString::insert()!!! + QTextStringChar() : lineStart( 0 ), type( Regular ), startOfRun( 0 ) {d.format=0;} + ~QTextStringChar(); + + QChar c; + enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; + uint lineStart : 1; + uint rightToLeft : 1; + uint hasCursor : 1; + uint canBreak : 1; + Type type : 2; + uint startOfRun : 1; + + int x; + int height() const; + int ascent() const; + int descent() const; + bool isCustom() const { return (type & Custom) != 0; } + QTextFormat *format() const; +#ifndef QT_NO_TEXTCUSTOMITEM + QTextCustomItem *customItem() const; +#endif + void setFormat( QTextFormat *f ); +#ifndef QT_NO_TEXTCUSTOMITEM + void setCustomItem( QTextCustomItem *i ); +#endif + struct CustomData + { + QTextFormat *format; +#ifndef QT_NO_TEXTCUSTOMITEM + QTextCustomItem *custom; +#endif + QString anchorName; + QString anchorHref; + }; + +#ifndef QT_NO_TEXTCUSTOMITEM + void loseCustomItem(); +#endif + + union { + QTextFormat* format; + CustomData* custom; + } d; + + bool isAnchor() const { return ( type & Anchor) != 0; } + bool isLink() const { return isAnchor() && !!d.custom->anchorHref; } + QString anchorName() const; + QString anchorHref() const; + void setAnchor( const QString& name, const QString& href ); + +private: + QTextStringChar &operator=( const QTextStringChar & ) { + //abort(); + return *this; + } + friend class QComplexText; + friend class QTextParagraph; +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<QTextStringChar>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextString +{ +public: + + QTextString(); + QTextString( const QTextString &s ); + virtual ~QTextString(); + + static QString toString( const QMemArray<QTextStringChar> &data ); + QString toString() const; + + QTextStringChar &at( int i ) const; +#if defined(Q_STRICT_INLINING_RULES) + // This is for the IRIX MIPSpro o32 ABI - it fails, claiming the + // implementation to be a redefinition. + inline int length() const; +#else + int length() const; +#endif + + int width( int idx ) const; + + void insert( int index, const QString &s, QTextFormat *f ); + void insert( int index, const QChar *unicode, int len, QTextFormat *f ); + void insert( int index, QTextStringChar *c, bool doAddRefFormat = FALSE ); + void truncate( int index ); + void remove( int index, int len ); + void clear(); + + void setFormat( int index, QTextFormat *f, bool useCollection ); + + void setBidi( bool b ) { bidi = b; } + bool isBidi() const; + bool isRightToLeft() const; + QChar::Direction direction() const; + void setDirection( QChar::Direction d ) { dir = d; bidiDirty = TRUE; } + + QMemArray<QTextStringChar> subString( int start = 0, int len = 0xFFFFFF ) const; + QMemArray<QTextStringChar> rawData() const { return data.copy(); } + + void operator=( const QString &s ) { clear(); insert( 0, s, 0 ); } + void operator+=( const QString &s ) { insert( length(), s, 0 ); } + void prepend( const QString &s ) { insert( 0, s, 0 ); } + +private: + void checkBidi() const; + + QMemArray<QTextStringChar> data; + uint bidiDirty : 1; + uint bidi : 1; // true when the paragraph has right to left characters + uint rightToLeft : 1; + uint dir : 5; +}; + +inline bool QTextString::isBidi() const +{ + if ( bidiDirty ) + checkBidi(); + return bidi; +} + +inline bool QTextString::isRightToLeft() const +{ + if ( bidiDirty ) + checkBidi(); + return rightToLeft; +} + +inline QChar::Direction QTextString::direction() const +{ + return (QChar::Direction) dir; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<int>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<QTextParagraph*>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<bool>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextCursor +{ +public: + QTextCursor( QTextDocument *d = 0 ); + QTextCursor( const QTextCursor &c ); + QTextCursor &operator=( const QTextCursor &c ); + virtual ~QTextCursor() {} + + bool operator==( const QTextCursor &c ) const; + bool operator!=( const QTextCursor &c ) const { return !(*this == c); } + +#if defined(Q_STRICT_INLINING_RULES) + // This is for the IRIX MIPSpro o32 ABI - it fails, claiming the + // implementation to be a redefinition. + inline QTextParagraph *paragraph() const; +#else + QTextParagraph *paragraph() const; +#endif + + void setParagraph( QTextParagraph*p ) { gotoPosition(p, 0 ); } + QTextDocument *document() const; + int index() const; + void setIndex( int index ) { gotoPosition(paragraph(), index ); } + + void gotoPosition( QTextParagraph* p, int index = 0); + void gotoLeft(); + void gotoRight(); + void gotoNextLetter(); + void gotoPreviousLetter(); + void gotoUp(); + void gotoDown(); + void gotoLineEnd(); + void gotoLineStart(); + void gotoHome(); + void gotoEnd(); + void gotoPageUp( int visibleHeight ); + void gotoPageDown( int visibleHeight ); + void gotoNextWord(); + void gotoPreviousWord(); + void gotoWordLeft(); + void gotoWordRight(); + + void insert( const QString &s, bool checkNewLine, QMemArray<QTextStringChar> *formatting = 0 ); + void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE ); + bool remove(); + void indent(); + + bool atParagStart(); + bool atParagEnd(); + + int x() const; // x in current paragraph + int y() const; // y in current paragraph + + int globalX() const; + int globalY() const; + + QTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); } + int offsetX() const { return ox; } // inner document offset + int offsetY() const { return oy; } // inner document offset + int totalOffsetX() const; // total document offset + int totalOffsetY() const; // total document offset + + bool place( const QPoint &pos, QTextParagraph *s ) { return place( pos, s, FALSE ); } + bool place( const QPoint &pos, QTextParagraph *s, bool link ); + void restoreState(); + + + int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast + void oneUp() { if ( !indices.isEmpty() ) pop(); } + void setValid( bool b ) { valid = b; } + bool isValid() const { return valid; } + +private: + enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down }; + + void push(); + void pop(); + void processNesting( Operation op ); + void invalidateNested(); + void gotoIntoNested( const QPoint &globalPos ); + + QTextParagraph *para; + int idx, tmpIndex; + int ox, oy; + QValueStack<int> indices; + QValueStack<QTextParagraph*> paras; + QValueStack<int> xOffsets; + QValueStack<int> yOffsets; + uint valid : 1; + +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextCommand +{ +public: + enum Commands { Invalid, Insert, Delete, Format, Style }; + + QTextCommand( QTextDocument *d ) : doc( d ), cursor( d ) {} + virtual ~QTextCommand(); + + virtual Commands type() const; + + virtual QTextCursor *execute( QTextCursor *c ) = 0; + virtual QTextCursor *unexecute( QTextCursor *c ) = 0; + +protected: + QTextDocument *doc; + QTextCursor cursor; + +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCommand>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextCommandHistory +{ +public: + QTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); } + virtual ~QTextCommandHistory(); + + void clear() { history.clear(); current = -1; } + + void addCommand( QTextCommand *cmd ); + QTextCursor *undo( QTextCursor *c ); + QTextCursor *redo( QTextCursor *c ); + + bool isUndoAvailable(); + bool isRedoAvailable(); + + void setUndoDepth( int d ) { steps = d; } + int undoDepth() const { return steps; } + + int historySize() const { return history.count(); } + int currentPosition() const { return current; } + +private: + QPtrList<QTextCommand> history; + int current, steps; + +}; + +inline QTextCommandHistory::~QTextCommandHistory() +{ + clear(); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#ifndef QT_NO_TEXTCUSTOMITEM +class Q_EXPORT QTextCustomItem +{ +public: + QTextCustomItem( QTextDocument *p ) + : xpos(0), ypos(-1), width(-1), height(0), parent( p ) + {} + virtual ~QTextCustomItem(); + virtual void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) = 0; + + virtual void adjustToPainter( QPainter* ); + + enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight }; + virtual Placement placement() const; + bool placeInline() { return placement() == PlaceInline; } + + virtual bool ownLine() const; + virtual void resize( int nwidth ); + virtual void invalidate(); + virtual int ascent() const { return height; } + + virtual bool isNested() const; + virtual int minimumWidth() const; + + virtual QString richText() const; + + int xpos; // used for floating items + int ypos; // used for floating items + int width; + int height; + + QRect geometry() const { return QRect( xpos, ypos, width, height ); } + + virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint & ); + virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + + void setParagraph( QTextParagraph *p ) { parag = p; } + QTextParagraph *paragraph() const { return parag; } + + QTextDocument *parent; + QTextParagraph *parag; + + virtual void pageBreak( int y, QTextFlow* flow ); +}; +#endif + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QString, QString>; +// MOC_SKIP_END +#endif + +#ifndef QT_NO_TEXTCUSTOMITEM +class Q_EXPORT QTextImage : public QTextCustomItem +{ +public: + QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, + QMimeSourceFactory &factory ); + virtual ~QTextImage(); + + Placement placement() const { return place; } + void adjustToPainter( QPainter* ); + int minimumWidth() const { return width; } + + QString richText() const; + + void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); + +private: + QRegion* reg; + QPixmap pm; + Placement place; + int tmpwidth, tmpheight; + QMap<QString, QString> attributes; + QString imgId; + +}; +#endif + +#ifndef QT_NO_TEXTCUSTOMITEM +class Q_EXPORT QTextHorizontalLine : public QTextCustomItem +{ +public: + QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, + QMimeSourceFactory &factory ); + virtual ~QTextHorizontalLine(); + + void adjustToPainter( QPainter* ); + void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); + QString richText() const; + + bool ownLine() const { return TRUE; } + +private: + int tmpheight; + QColor color; + bool shade; + +}; +#endif + +#ifndef QT_NO_TEXTCUSTOMITEM +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCustomItem>; +// MOC_SKIP_END +#endif +#endif + +class Q_EXPORT QTextFlow +{ + friend class QTextDocument; +#ifndef QT_NO_TEXTCUSTOMITEM + friend class QTextTableCell; +#endif + +public: + QTextFlow(); + virtual ~QTextFlow(); + + virtual void setWidth( int width ); + int width() const; + + virtual void setPageSize( int ps ); + int pageSize() const { return pagesize; } + + virtual int adjustLMargin( int yp, int h, int margin, int space ); + virtual int adjustRMargin( int yp, int h, int margin, int space ); + +#ifndef QT_NO_TEXTCUSTOMITEM + virtual void registerFloatingItem( QTextCustomItem* item ); + virtual void unregisterFloatingItem( QTextCustomItem* item ); +#endif + virtual QRect boundingRect() const; + virtual void drawFloatingItems(QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); + + virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift. + + virtual bool isEmpty(); + + void clear(); + +private: + int w; + int pagesize; + +#ifndef QT_NO_TEXTCUSTOMITEM + QPtrList<QTextCustomItem> leftItems; + QPtrList<QTextCustomItem> rightItems; +#endif +}; + +inline int QTextFlow::width() const { return w; } + +#ifndef QT_NO_TEXTCUSTOMITEM +class QTextTable; + +class Q_EXPORT QTextTableCell : public QLayoutItem +{ + friend class QTextTable; + +public: + QTextTableCell( QTextTable* table, + int row, int column, + const QMap<QString, QString> &attr, + const QStyleSheetItem* style, + const QTextFormat& fmt, const QString& context, + QMimeSourceFactory &factory, QStyleSheet *sheet, const QString& doc ); + virtual ~QTextTableCell(); + + QSize sizeHint() const ; + QSize minimumSize() const ; + QSize maximumSize() const ; + QSizePolicy::ExpandData expanding() const; + bool isEmpty() const; + void setGeometry( const QRect& ) ; + QRect geometry() const; + + bool hasHeightForWidth() const; + int heightForWidth( int ) const; + + void adjustToPainter( QPainter* ); + + int row() const { return row_; } + int column() const { return col_; } + int rowspan() const { return rowspan_; } + int colspan() const { return colspan_; } + int stretch() const { return stretch_; } + + QTextDocument* richText() const { return richtext; } + QTextTable* table() const { return parent; } + + void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); + + QBrush *backGround() const { return background; } + virtual void invalidate(); + + int verticalAlignmentOffset() const; + int horizontalAlignmentOffset() const; + +private: + QRect geom; + QTextTable* parent; + QTextDocument* richtext; + int row_; + int col_; + int rowspan_; + int colspan_; + int stretch_; + int maxw; + int minw; + bool hasFixedWidth; + QBrush *background; + int cached_width; + int cached_sizehint; + QMap<QString, QString> attributes; + int align; +}; +#endif + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextTableCell>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QTextCursor*, int>; +// MOC_SKIP_END +#endif + +#ifndef QT_NO_TEXTCUSTOMITEM +class Q_EXPORT QTextTable: public QTextCustomItem +{ + friend class QTextTableCell; + +public: + QTextTable( QTextDocument *p, const QMap<QString, QString> &attr ); + virtual ~QTextTable(); + + void adjustToPainter( QPainter *p ); + void pageBreak( int y, QTextFlow* flow ); + void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, + const QColorGroup& cg, bool selected ); + + bool noErase() const { return TRUE; } + bool ownLine() const { return TRUE; } + Placement placement() const { return place; } + bool isNested() const { return TRUE; } + void resize( int nwidth ); + virtual void invalidate(); + + virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint &pos ); + virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + + QString richText() const; + + int minimumWidth() const; + + QPtrList<QTextTableCell> tableCells() const { return cells; } + + bool isStretching() const { return stretch; } + +private: + void format( int w ); + void addCell( QTextTableCell* cell ); + +private: + QGridLayout* layout; + QPtrList<QTextTableCell> cells; + int cachewidth; + int fixwidth; + int cellpadding; + int cellspacing; + int border; + int outerborder; + int stretch; + int innerborder; + int us_cp, us_ib, us_b, us_ob, us_cs; + QMap<QString, QString> attributes; + QMap<QTextCursor*, int> currCell; + Placement place; + void adjustCells( int y , int shift ); + int pageBreakFor; +}; +#endif +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#ifndef QT_NO_TEXTCUSTOMITEM +class QTextTableCell; +class QTextParagraph; +#endif + +struct Q_EXPORT QTextDocumentSelection +{ + QTextCursor startCursor, endCursor; + bool swapped; +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QColor>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, bool>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextDocumentSelection>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextDocument>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextDocument : public QObject +{ + Q_OBJECT + +#ifndef QT_NO_TEXTCUSTOMITEM + friend class QTextTableCell; +#endif + friend class QTextCursor; + friend class QTextEdit; + friend class QTextParagraph; + +public: + enum SelectionIds { + Standard = 0, + IMSelectionText = 31998, + IMCompositionText = 31999, // this must be higher! + Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to + // remove multiple lines with removeSelectedText() + }; + + QTextDocument( QTextDocument *p ); + QTextDocument( QTextDocument *d, QTextFormatCollection *f ); + virtual ~QTextDocument(); + + QTextDocument *parent() const { return par; } + QTextParagraph *parentParagraph() const { return parentPar; } + + void setText( const QString &text, const QString &context ); + QMap<QString, QString> attributes() const { return attribs; } + void setAttributes( const QMap<QString, QString> &attr ) { attribs = attr; } + + QString text() const; + QString text( int parag ) const; + QString originalText() const; + + int x() const; + int y() const; + int width() const; + int widthUsed() const; + int visibleWidth() const; + int height() const; + void setWidth( int w ); + int minimumWidth() const; + bool setMinimumWidth( int needed, int used = -1, QTextParagraph *parag = 0 ); + + void setY( int y ); + int leftMargin() const; + void setLeftMargin( int lm ); + int rightMargin() const; + void setRightMargin( int rm ); + + QTextParagraph *firstParagraph() const; + QTextParagraph *lastParagraph() const; + void setFirstParagraph( QTextParagraph *p ); + void setLastParagraph( QTextParagraph *p ); + + void invalidate(); + + void setPreProcessor( QTextPreProcessor *sh ); + QTextPreProcessor *preProcessor() const; + + void setFormatter( QTextFormatter *f ); + QTextFormatter *formatter() const; + + void setIndent( QTextIndent *i ); + QTextIndent *indent() const; + + QColor selectionColor( int id ) const; + bool invertSelectionText( int id ) const; + void setSelectionColor( int id, const QColor &c ); + void setInvertSelectionText( int id, bool b ); + bool hasSelection( int id, bool visible = FALSE ) const; + void setSelectionStart( int id, const QTextCursor &cursor ); + bool setSelectionEnd( int id, const QTextCursor &cursor ); + void selectAll( int id ); + bool removeSelection( int id ); + void selectionStart( int id, int ¶gId, int &index ); + QTextCursor selectionStartCursor( int id ); + QTextCursor selectionEndCursor( int id ); + void selectionEnd( int id, int ¶gId, int &index ); + void setFormat( int id, QTextFormat *f, int flags ); + int numSelections() const { return nSelections; } + void addSelection( int id ); + + QString selectedText( int id, bool asRichText = FALSE ) const; + void removeSelectedText( int id, QTextCursor *cursor ); + void indentSelection( int id ); + + QTextParagraph *paragAt( int i ) const; + + void addCommand( QTextCommand *cmd ); + QTextCursor *undo( QTextCursor *c = 0 ); + QTextCursor *redo( QTextCursor *c = 0 ); + QTextCommandHistory *commands() const { return commandHistory; } + + QTextFormatCollection *formatCollection() const; + + bool find( QTextCursor &cursor, const QString &expr, bool cs, bool wo, bool forward); + + void setTextFormat( Qt::TextFormat f ); + Qt::TextFormat textFormat() const; + + bool inSelection( int selId, const QPoint &pos ) const; + + QStyleSheet *styleSheet() const { return sheet_; } +#ifndef QT_NO_MIME + QMimeSourceFactory *mimeSourceFactory() const { return factory_; } +#endif + QString context() const { return contxt; } + + void setStyleSheet( QStyleSheet *s ); + void setDefaultFormat( const QFont &font, const QColor &color ); +#ifndef QT_NO_MIME + void setMimeSourceFactory( QMimeSourceFactory *f ) { if ( f ) factory_ = f; } +#endif + void setContext( const QString &c ) { if ( !c.isEmpty() ) contxt = c; } + + void setUnderlineLinks( bool b ); + bool underlineLinks() const { return underlLinks; } + + void setPaper( QBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; } + QBrush *paper() const { return backBrush; } + + void doLayout( QPainter *p, int w ); + void draw( QPainter *p, const QRect& rect, const QColorGroup &cg, const QBrush *paper = 0 ); + void drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, + QPixmap *&doubleBuffer, const QColorGroup &cg, + bool drawCursor, QTextCursor *cursor, bool resetChanged = TRUE ); + QTextParagraph *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, + bool onlyChanged = FALSE, bool drawCursor = FALSE, QTextCursor *cursor = 0, + bool resetChanged = TRUE ); + +#ifndef QT_NO_TEXTCUSTOMITEM + void registerCustomItem( QTextCustomItem *i, QTextParagraph *p ); + void unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ); +#endif + + void setFlow( QTextFlow *f ); + void takeFlow(); + QTextFlow *flow() const { return flow_; } + bool isPageBreakEnabled() const { return pages; } + void setPageBreakEnabled( bool b ) { pages = b; } + + void setUseFormatCollection( bool b ) { useFC = b; } + bool useFormatCollection() const { return useFC; } + +#ifndef QT_NO_TEXTCUSTOMITEM + QTextTableCell *tableCell() const { return tc; } + void setTableCell( QTextTableCell *c ) { tc = c; } +#endif + + void setPlainText( const QString &text ); + void setRichText( const QString &text, const QString &context ); + QString richText() const; + QString plainText() const; + + bool focusNextPrevChild( bool next ); + + int alignment() const; + void setAlignment( int a ); + + int *tabArray() const; + int tabStopWidth() const; + void setTabArray( int *a ); + void setTabStops( int tw ); + + void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); } + int undoDepth() const { return commandHistory->undoDepth(); } + + int length() const; + void clear( bool createEmptyParag = FALSE ); + + virtual QTextParagraph *createParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); + void insertChild( QObject *o ) { QObject::insertChild( o ); } + void removeChild( QObject *o ) { QObject::removeChild( o ); } + void insertChild( QTextDocument *d ) { childList.append( d ); } + void removeChild( QTextDocument *d ) { childList.removeRef( d ); } + QPtrList<QTextDocument> children() const { return childList; } + + bool hasFocusParagraph() const; + QString focusHref() const; + QString focusName() const; + + void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } + +signals: + void minimumWidthChanged( int ); + +private: + void init(); + QPixmap *bufferPixmap( const QSize &s ); + // HTML parser + bool hasPrefix(const QChar* doc, int length, int pos, QChar c); + bool hasPrefix(const QChar* doc, int length, int pos, const QString& s); +#ifndef QT_NO_TEXTCUSTOMITEM + QTextCustomItem* parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, + const QChar* doc, int length, int& pos, QTextParagraph *curpar ); +#endif + bool eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp = FALSE ); + bool eat(const QChar* doc, int length, int& pos, QChar c); + QString parseOpenTag(const QChar* doc, int length, int& pos, QMap<QString, QString> &attr, bool& emptyTag); + QString parseCloseTag( const QChar* doc, int length, int& pos ); + QChar parseHTMLSpecialChar(const QChar* doc, int length, int& pos); + QString parseWord(const QChar* doc, int length, int& pos, bool lower = TRUE); + QChar parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ); + void setRichTextInternal( const QString &text, QTextCursor* cursor = 0 ); + void setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ); + +private: + struct Q_EXPORT Focus { + QTextParagraph *parag; + int start, len; + QString href; + QString name; + }; + + int cx, cy, cw, vw; + QTextParagraph *fParag, *lParag; + QTextPreProcessor *pProcessor; + QMap<int, QColor> selectionColors; + QMap<int, QTextDocumentSelection> selections; + QMap<int, bool> selectionText; + QTextCommandHistory *commandHistory; + QTextFormatter *pFormatter; + QTextIndent *indenter; + QTextFormatCollection *fCollection; + Qt::TextFormat txtFormat; + uint preferRichText : 1; + uint pages : 1; + uint useFC : 1; + uint withoutDoubleBuffer : 1; + uint underlLinks : 1; + uint nextDoubleBuffered : 1; + uint oTextValid : 1; + uint mightHaveCustomItems : 1; + int align; + int nSelections; + QTextFlow *flow_; + QTextDocument *par; + QTextParagraph *parentPar; +#ifndef QT_NO_TEXTCUSTOMITEM + QTextTableCell *tc; +#endif + QBrush *backBrush; + QPixmap *buf_pixmap; + Focus focusIndicator; + int minw; + int wused; + int leftmargin; + int rightmargin; + QTextParagraph *minwParag, *curParag; + QStyleSheet* sheet_; +#ifndef QT_NO_MIME + QMimeSourceFactory* factory_; +#endif + QString contxt; + QMap<QString, QString> attribs; + int *tArray; + int tStopWidth; + int uDepth; + QString oText; + QPtrList<QTextDocument> childList; + QColor linkColor; + double scaleFontsFactor; + + short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm; +#if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator= + QTextDocument( const QTextDocument & ); + QTextDocument &operator=( const QTextDocument & ); +#endif +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +class Q_EXPORT QTextDeleteCommand : public QTextCommand +{ +public: + QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, + const QByteArray& oldStyle ); + QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ); + virtual ~QTextDeleteCommand(); + + Commands type() const { return Delete; } + QTextCursor *execute( QTextCursor *c ); + QTextCursor *unexecute( QTextCursor *c ); + +protected: + int id, index; + QTextParagraph *parag; + QMemArray<QTextStringChar> text; + QByteArray styleInformation; + +}; + +class Q_EXPORT QTextInsertCommand : public QTextDeleteCommand +{ +public: + QTextInsertCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, + const QByteArray& oldStyleInfo ) + : QTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {} + QTextInsertCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) + : QTextDeleteCommand( p, idx, str ) {} + virtual ~QTextInsertCommand() {} + + Commands type() const { return Insert; } + QTextCursor *execute( QTextCursor *c ) { return QTextDeleteCommand::unexecute( c ); } + QTextCursor *unexecute( QTextCursor *c ) { return QTextDeleteCommand::execute( c ); } + +}; + +class Q_EXPORT QTextFormatCommand : public QTextCommand +{ +public: + QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ); + virtual ~QTextFormatCommand(); + + Commands type() const { return Format; } + QTextCursor *execute( QTextCursor *c ); + QTextCursor *unexecute( QTextCursor *c ); + +protected: + int startId, startIndex, endId, endIndex; + QTextFormat *format; + QMemArray<QTextStringChar> oldFormats; + int flags; + +}; + +class Q_EXPORT QTextStyleCommand : public QTextCommand +{ +public: + QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ); + virtual ~QTextStyleCommand() {} + + Commands type() const { return Style; } + QTextCursor *execute( QTextCursor *c ); + QTextCursor *unexecute( QTextCursor *c ); + + static QByteArray readStyleInformation( QTextDocument* d, int fParag, int lParag ); + static void writeStyleInformation( QTextDocument* d, int fParag, const QByteArray& style ); + +private: + int firstParag, lastParag; + QByteArray before; + QByteArray after; +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +struct Q_EXPORT QTextParagraphSelection +{ + int start, end; +}; + +struct Q_EXPORT QTextLineStart +{ + QTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) +#ifndef QT_NO_COMPLEXTEXT + , bidicontext( 0 ) +#endif + { } + QTextLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ), + w( 0 ) +#ifndef QT_NO_COMPLEXTEXT + , bidicontext( 0 ) +#endif + { } +#ifndef QT_NO_COMPLEXTEXT + QTextLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0), + status( s ), bidicontext( c ) { if ( bidicontext ) bidicontext->ref(); } +#endif + + virtual ~QTextLineStart() + { +#ifndef QT_NO_COMPLEXTEXT + if ( bidicontext && bidicontext->deref() ) + delete bidicontext; +#endif + } + +#ifndef QT_NO_COMPLEXTEXT + void setContext( QBidiContext *c ) { + if ( c == bidicontext ) + return; + if ( bidicontext && bidicontext->deref() ) + delete bidicontext; + bidicontext = c; + if ( bidicontext ) + bidicontext->ref(); + } + QBidiContext *context() const { return bidicontext; } +#endif + +public: + ushort y, baseLine, h; +#ifndef QT_NO_COMPLEXTEXT + QBidiStatus status; +#endif + int w; + +private: +#ifndef QT_NO_COMPLEXTEXT + QBidiContext *bidicontext; +#endif +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextParagraphSelection>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextLineStart*>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextParagraphData +{ +public: + QTextParagraphData() {} + virtual ~QTextParagraphData(); + virtual void join( QTextParagraphData * ); +}; + +class Q_EXPORT QTextParagraphPseudoDocument +{ +public: + QTextParagraphPseudoDocument(); + ~QTextParagraphPseudoDocument(); + QRect docRect; + QTextFormatter *pFormatter; + QTextCommandHistory *commandHistory; + int minw; + int wused; +}; + +//nase +class Q_EXPORT QTextParagraph +{ + friend class QTextDocument; + friend class QTextCursor; + +public: + QTextParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); + virtual ~QTextParagraph(); + + QTextString *string() const; + QTextStringChar *at( int i ) const; // maybe remove later + int leftGap() const; + int length() const; // maybe remove later + + void setListStyle( QStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; } + QStyleSheetItem::ListStyle listStyle() const { return lstyle; } + void setListItem( bool li ); + bool isListItem() const { return litem; } + void setListValue( int v ) { list_val = v; } + int listValue() const { return list_val > 0 ? list_val : -1; } + + void setListDepth( int depth ); + int listDepth() const { return ldepth; } + +// void setFormat( QTextFormat *fm ); +// QTextFormat *paragFormat() const; + + QTextDocument *document() const; + QTextParagraphPseudoDocument *pseudoDocument() const; + + QRect rect() const; + void setHeight( int h ) { r.setHeight( h ); } + void show(); + void hide(); + bool isVisible() const { return visible; } + + QTextParagraph *prev() const; + QTextParagraph *next() const; + void setPrev( QTextParagraph *s ); + void setNext( QTextParagraph *s ); + + void insert( int index, const QString &s ); + void insert( int index, const QChar *unicode, int len ); + void append( const QString &s, bool reallyAtEnd = FALSE ); + void truncate( int index ); + void remove( int index, int len ); + void join( QTextParagraph *s ); + + void invalidate( int chr ); + + void move( int &dy ); + void format( int start = -1, bool doMove = TRUE ); + + bool isValid() const; + bool hasChanged() const; + void setChanged( bool b, bool recursive = FALSE ); + + int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; + QTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; + int lines() const; + QTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; + int lineY( int l ) const; + int lineBaseLine( int l ) const; + int lineHeight( int l ) const; + void lineInfo( int l, int &y, int &h, int &bl ) const; + + void setSelection( int id, int start, int end ); + void removeSelection( int id ); + int selectionStart( int id ) const; + int selectionEnd( int id ) const; + bool hasSelection( int id ) const; + bool hasAnySelection() const; + bool fullSelected( int id ) const; + + void setEndState( int s ); + int endState() const; + + void setParagId( int i ); + int paragId() const; + + bool firstPreProcess() const; + void setFirstPreProcess( bool b ); + + void indent( int *oldIndent = 0, int *newIndent = 0 ); + + void setExtraData( QTextParagraphData *data ); + QTextParagraphData *extraData() const; + + QMap<int, QTextLineStart*> &lineStartList(); + + void setFormat( int index, int len, QTextFormat *f, bool useCollection = TRUE, int flags = -1 ); + + void setAlignment( int a ); + int alignment() const; + + virtual void paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor = 0, bool drawSelections = FALSE, + int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); + + virtual int topMargin() const; + virtual int bottomMargin() const; + virtual int leftMargin() const; + virtual int firstLineMargin() const; + virtual int rightMargin() const; + virtual int lineSpacing() const; + +#ifndef QT_NO_TEXTCUSTOMITEM + void registerFloatingItem( QTextCustomItem *i ); + void unregisterFloatingItem( QTextCustomItem *i ); +#endif + + void setFullWidth( bool b ) { fullWidth = b; } + bool isFullWidth() const { return fullWidth; } + +#ifndef QT_NO_TEXTCUSTOMITEM + QTextTableCell *tableCell() const; +#endif + + QBrush *background() const; + + int documentWidth() const; + int documentVisibleWidth() const; + int documentX() const; + int documentY() const; + QTextFormatCollection *formatCollection() const; + QTextFormatter *formatter() const; + + virtual int nextTab( int i, int x ); + int *tabArray() const; + void setTabArray( int *a ); + void setTabStops( int tw ); + + void adjustToPainter( QPainter *p ); + + void setNewLinesAllowed( bool b ); + bool isNewLinesAllowed() const; + + QString richText() const; + + void addCommand( QTextCommand *cmd ); + QTextCursor *undo( QTextCursor *c = 0 ); + QTextCursor *redo( QTextCursor *c = 0 ); + QTextCommandHistory *commands() const; + virtual void copyParagData( QTextParagraph *parag ); + + void setBreakable( bool b ) { breakable = b; } + bool isBreakable() const { return breakable; } + + void setBackgroundColor( const QColor &c ); + QColor *backgroundColor() const { return bgcol; } + void clearBackgroundColor(); + + void setMovedDown( bool b ) { movedDown = b; } + bool wasMovedDown() const { return movedDown; } + + void setDirection( QChar::Direction d ); + QChar::Direction direction() const; + void setPaintDevice( QPaintDevice *pd ) { paintdevice = pd; } + + void readStyleInformation( QDataStream& stream ); + void writeStyleInformation( QDataStream& stream ) const; + +protected: + virtual void setColorForSelection( QColor &c, QPainter &p, const QColorGroup& cg, int selection ); + virtual void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ); + virtual void drawString( QPainter &painter, const QString &str, int start, int len, int xstart, + int y, int baseLine, int w, int h, int selection, + QTextStringChar *formatChar, const QColorGroup& cg, + bool rightToLeft ); + +private: + QMap<int, QTextParagraphSelection> &selections() const; +#ifndef QT_NO_TEXTCUSTOMITEM + QPtrList<QTextCustomItem> &floatingItems() const; +#endif + QBrush backgroundBrush( const QColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( QColorGroup::Base ); } + void invalidateStyleCache(); + + QMap<int, QTextLineStart*> lineStarts; + int invalid; + QRect r; + QTextParagraph *p, *n; + void *docOrPseudo; + uint changed : 1; + uint firstFormat : 1; + uint firstPProcess : 1; + uint needPreProcess : 1; + uint fullWidth : 1; + uint lastInFrame : 1; + uint visible : 1; + uint breakable : 1; + uint movedDown : 1; + uint mightHaveCustomItems : 1; + uint hasdoc : 1; + uint litem : 1; // whether the paragraph is a list item + uint rtext : 1; // whether the paragraph needs rich text margin + int align : 4; + int state, id; + QTextString *str; + QMap<int, QTextParagraphSelection> *mSelections; +#ifndef QT_NO_TEXTCUSTOMITEM + QPtrList<QTextCustomItem> *mFloatingItems; +#endif + QStyleSheetItem::ListStyle lstyle; + short utm, ubm, ulm, urm, uflm, ulinespacing; + int *tArray; + short tabStopWidth; + QTextParagraphData *eData; + short list_val; + QColor *bgcol; + ushort ldepth; + QPaintDevice *paintdevice; +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextFormatter +{ +public: + QTextFormatter(); + virtual ~QTextFormatter(); + + virtual int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ) = 0; + virtual int formatVertically( QTextDocument* doc, QTextParagraph* parag ); + + bool isWrapEnabled( QTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} + int wrapAtColumn() const { return wrapColumn;} + virtual void setWrapEnabled( bool b ); + virtual void setWrapAtColumn( int c ); + virtual void setAllowBreakInWords( bool b ) { biw = b; } + bool allowBreakInWords() const { return biw; } + + int minimumWidth() const { return thisminw; } + int widthUsed() const { return thiswused; } + + static bool isBreakable( QTextString *string, int pos ); + +protected: + virtual QTextLineStart *formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, + QTextStringChar *last, int align = Qt::AlignAuto, int space = 0 ); +#ifndef QT_NO_COMPLEXTEXT + virtual QTextLineStart *bidiReorderLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, + QTextStringChar *last, int align, int space ); +#endif + void insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ); + + int thisminw; + int thiswused; + +private: + bool wrapEnabled; + int wrapColumn; + bool biw; + +#ifdef HAVE_THAI_BREAKS + static QCString *thaiCache; + static QTextString *cachedString; + static ThBreakIterator *thaiIt; +#endif +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextFormatterBreakInWords : public QTextFormatter +{ +public: + QTextFormatterBreakInWords(); + virtual ~QTextFormatterBreakInWords() {} + + int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextFormatterBreakWords : public QTextFormatter +{ +public: + QTextFormatterBreakWords(); + virtual ~QTextFormatterBreakWords() {} + + int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextIndent +{ +public: + QTextIndent(); + virtual ~QTextIndent() {} + + virtual void indent( QTextDocument *doc, QTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextPreProcessor +{ +public: + enum Ids { + Standard = 0 + }; + + QTextPreProcessor(); + virtual ~QTextPreProcessor() {} + + virtual void process( QTextDocument *doc, QTextParagraph *, int, bool = TRUE ) = 0; + virtual QTextFormat *format( int id ) = 0; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class Q_EXPORT QTextFormat +{ + friend class QTextFormatCollection; + friend class QTextDocument; + +public: + enum Flags { + NoFlags, + Bold = 1, + Italic = 2, + Underline = 4, + Family = 8, + Size = 16, + Color = 32, + Misspelled = 64, + VAlign = 128, + StrikeOut= 256, + Font = Bold | Italic | Underline | Family | Size | StrikeOut, + Format = Font | Color | Misspelled | VAlign + }; + + enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript }; + + QTextFormat(); + virtual ~QTextFormat(); + + QTextFormat( const QStyleSheetItem *s ); + QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent = 0 ); + QTextFormat( const QTextFormat &fm ); + QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const; + QTextFormat& operator=( const QTextFormat &fm ); + QColor color() const; + QFont font() const; + bool isMisspelled() const; + VerticalAlignment vAlign() const; + int minLeftBearing() const; + int minRightBearing() const; + int width( const QChar &c ) const; + int width( const QString &str, int pos ) const; + int height() const; + int ascent() const; + int descent() const; + int leading() const; + bool useLinkColor() const; + + void setBold( bool b ); + void setItalic( bool b ); + void setUnderline( bool b ); + void setStrikeOut( bool b ); + void setFamily( const QString &f ); + void setPointSize( int s ); + void setFont( const QFont &f ); + void setColor( const QColor &c ); + void setMisspelled( bool b ); + void setVAlign( VerticalAlignment a ); + + bool operator==( const QTextFormat &f ) const; + QTextFormatCollection *parent() const; + const QString &key() const; + + static QString getKey( const QFont &f, const QColor &c, bool misspelled, VerticalAlignment vAlign ); + + void addRef(); + void removeRef(); + + QString makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const; + QString makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const; + + static void setPainter( QPainter *p ); + static QPainter* painter(); + + bool fontSizesInPixels() { return usePixelSizes; } + +protected: + virtual void generateKey(); + +private: + void update(); + static void applyFont( const QFont &f ); + +private: + QFont fn; + QColor col; + QFontMetrics fm; + uint missp : 1; + uint linkColor : 1; + uint usePixelSizes : 1; + int leftBearing, rightBearing; + VerticalAlignment ha; + uchar widths[ 256 ]; + int hei, asc, dsc; + QTextFormatCollection *collection; + int ref; + QString k; + int logicalFontSize; + int stdSize; + static QPainter *pntr; + static QFontMetrics *pntr_fm; + static int pntr_asc; + static int pntr_hei; + static int pntr_ldg; + static int pntr_dsc; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QTextFormat>; +// MOC_SKIP_END +#endif + +class Q_EXPORT QTextFormatCollection +{ + friend class QTextDocument; + friend class QTextFormat; + +public: + QTextFormatCollection(); + virtual ~QTextFormatCollection(); + + void setDefaultFormat( QTextFormat *f ); + QTextFormat *defaultFormat() const; + virtual QTextFormat *format( QTextFormat *f ); + virtual QTextFormat *format( QTextFormat *of, QTextFormat *nf, int flags ); + virtual QTextFormat *format( const QFont &f, const QColor &c ); + virtual void remove( QTextFormat *f ); + virtual QTextFormat *createFormat( const QTextFormat &f ) { return new QTextFormat( f ); } + virtual QTextFormat *createFormat( const QFont &f, const QColor &c ) { return new QTextFormat( f, c, this ); } + + void updateDefaultFormat( const QFont &font, const QColor &c, QStyleSheet *sheet ); + QDict<QTextFormat> dict() const { return cKey; } + + QPaintDevice *paintDevice() const { return paintdevice; } + void setPaintDevice( QPaintDevice * ); + +private: + void updateKeys(); + +private: + QTextFormat *defFormat, *lastFormat, *cachedFormat; + QDict<QTextFormat> cKey; + QTextFormat *cres; + QFont cfont; + QColor ccol; + QString kof, knf; + int cflags; + + QPaintDevice *paintdevice; +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline int QTextString::length() const +{ + return data.size(); +} + +inline int QTextParagraph::length() const +{ + return str->length(); +} + +inline QRect QTextParagraph::rect() const +{ + return r; +} + +inline QTextParagraph *QTextCursor::paragraph() const +{ + return para; +} + +inline int QTextCursor::index() const +{ + return idx; +} + + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline int QTextDocument::x() const +{ + return cx; +} + +inline int QTextDocument::y() const +{ + return cy; +} + +inline int QTextDocument::width() const +{ + return QMAX( cw, flow_->width() ); +} + +inline int QTextDocument::visibleWidth() const +{ + return vw; +} + +inline QTextParagraph *QTextDocument::firstParagraph() const +{ + return fParag; +} + +inline QTextParagraph *QTextDocument::lastParagraph() const +{ + return lParag; +} + +inline void QTextDocument::setFirstParagraph( QTextParagraph *p ) +{ + fParag = p; +} + +inline void QTextDocument::setLastParagraph( QTextParagraph *p ) +{ + lParag = p; +} + +inline void QTextDocument::setWidth( int w ) +{ + cw = QMAX( w, minw ); + flow_->setWidth( cw ); + vw = w; +} + +inline int QTextDocument::minimumWidth() const +{ + return minw; +} + +inline void QTextDocument::setY( int y ) +{ + cy = y; +} + +inline int QTextDocument::leftMargin() const +{ + return leftmargin; +} + +inline void QTextDocument::setLeftMargin( int lm ) +{ + leftmargin = lm; +} + +inline int QTextDocument::rightMargin() const +{ + return rightmargin; +} + +inline void QTextDocument::setRightMargin( int rm ) +{ + rightmargin = rm; +} + +inline QTextPreProcessor *QTextDocument::preProcessor() const +{ + return pProcessor; +} + +inline void QTextDocument::setPreProcessor( QTextPreProcessor * sh ) +{ + pProcessor = sh; +} + +inline void QTextDocument::setFormatter( QTextFormatter *f ) +{ + delete pFormatter; + pFormatter = f; +} + +inline QTextFormatter *QTextDocument::formatter() const +{ + return pFormatter; +} + +inline void QTextDocument::setIndent( QTextIndent *i ) +{ + indenter = i; +} + +inline QTextIndent *QTextDocument::indent() const +{ + return indenter; +} + +inline QColor QTextDocument::selectionColor( int id ) const +{ + return selectionColors[ id ]; +} + +inline bool QTextDocument::invertSelectionText( int id ) const +{ + return selectionText[ id ]; +} + +inline void QTextDocument::setSelectionColor( int id, const QColor &c ) +{ + selectionColors[ id ] = c; +} + +inline void QTextDocument::setInvertSelectionText( int id, bool b ) +{ + selectionText[ id ] = b; +} + +inline QTextFormatCollection *QTextDocument::formatCollection() const +{ + return fCollection; +} + +inline int QTextDocument::alignment() const +{ + return align; +} + +inline void QTextDocument::setAlignment( int a ) +{ + align = a; +} + +inline int *QTextDocument::tabArray() const +{ + return tArray; +} + +inline int QTextDocument::tabStopWidth() const +{ + return tStopWidth; +} + +inline void QTextDocument::setTabArray( int *a ) +{ + tArray = a; +} + +inline void QTextDocument::setTabStops( int tw ) +{ + tStopWidth = tw; +} + +inline QString QTextDocument::originalText() const +{ + if ( oTextValid ) + return oText; + return text(); +} + +inline void QTextDocument::setFlow( QTextFlow *f ) +{ + if ( flow_ ) + delete flow_; + flow_ = f; +} + +inline void QTextDocument::takeFlow() +{ + flow_ = 0; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline QColor QTextFormat::color() const +{ + return col; +} + +inline QFont QTextFormat::font() const +{ + return fn; +} + +inline bool QTextFormat::isMisspelled() const +{ + return missp; +} + +inline QTextFormat::VerticalAlignment QTextFormat::vAlign() const +{ + return ha; +} + +inline bool QTextFormat::operator==( const QTextFormat &f ) const +{ + return k == f.k; +} + +inline QTextFormatCollection *QTextFormat::parent() const +{ + return collection; +} + +inline void QTextFormat::addRef() +{ + ref++; +} + +inline void QTextFormat::removeRef() +{ + ref--; + if ( !collection ) + return; + if ( this == collection->defFormat ) + return; + if ( ref == 0 ) + collection->remove( this ); +} + +inline const QString &QTextFormat::key() const +{ + return k; +} + +inline bool QTextFormat::useLinkColor() const +{ + return linkColor; +} + + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline QTextStringChar &QTextString::at( int i ) const +{ + return data[ i ]; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline QTextStringChar *QTextParagraph::at( int i ) const +{ + return &str->at( i ); +} + +inline bool QTextParagraph::isValid() const +{ + return invalid == -1; +} + +inline bool QTextParagraph::hasChanged() const +{ + return changed; +} + +inline void QTextParagraph::setBackgroundColor( const QColor & c ) +{ + delete bgcol; + bgcol = new QColor( c ); + setChanged( TRUE ); +} + +inline void QTextParagraph::clearBackgroundColor() +{ + delete bgcol; bgcol = 0; setChanged( TRUE ); +} + +inline void QTextParagraph::append( const QString &s, bool reallyAtEnd ) +{ + if ( reallyAtEnd ) + insert( str->length(), s ); + else + insert( QMAX( str->length() - 1, 0 ), s ); +} + +inline QTextParagraph *QTextParagraph::prev() const +{ + return p; +} + +inline QTextParagraph *QTextParagraph::next() const +{ + return n; +} + +inline bool QTextParagraph::hasAnySelection() const +{ + return mSelections ? !selections().isEmpty() : FALSE; +} + +inline void QTextParagraph::setEndState( int s ) +{ + if ( s == state ) + return; + state = s; +} + +inline int QTextParagraph::endState() const +{ + return state; +} + +inline void QTextParagraph::setParagId( int i ) +{ + id = i; +} + +inline int QTextParagraph::paragId() const +{ + if ( id == -1 ) + qWarning( "invalid parag id!!!!!!!! (%p)", (void*)this ); + return id; +} + +inline bool QTextParagraph::firstPreProcess() const +{ + return firstPProcess; +} + +inline void QTextParagraph::setFirstPreProcess( bool b ) +{ + firstPProcess = b; +} + +inline QMap<int, QTextLineStart*> &QTextParagraph::lineStartList() +{ + return lineStarts; +} + +inline QTextString *QTextParagraph::string() const +{ + return str; +} + +inline QTextDocument *QTextParagraph::document() const +{ + if ( hasdoc ) + return (QTextDocument*) docOrPseudo; + return 0; +} + +inline QTextParagraphPseudoDocument *QTextParagraph::pseudoDocument() const +{ + if ( hasdoc ) + return 0; + return (QTextParagraphPseudoDocument*) docOrPseudo; +} + + +#ifndef QT_NO_TEXTCUSTOMITEM +inline QTextTableCell *QTextParagraph::tableCell() const +{ + return hasdoc ? document()->tableCell () : 0; +} +#endif + +inline QTextCommandHistory *QTextParagraph::commands() const +{ + return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; +} + + +inline int QTextParagraph::alignment() const +{ + return align; +} + +#ifndef QT_NO_TEXTCUSTOMITEM +inline void QTextParagraph::registerFloatingItem( QTextCustomItem *i ) +{ + floatingItems().append( i ); +} + +inline void QTextParagraph::unregisterFloatingItem( QTextCustomItem *i ) +{ + floatingItems().removeRef( i ); +} +#endif + +inline QBrush *QTextParagraph::background() const +{ +#ifndef QT_NO_TEXTCUSTOMITEM + return tableCell() ? tableCell()->backGround() : 0; +#else + return 0; +#endif +} + +inline int QTextParagraph::documentWidth() const +{ + return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); +} + +inline int QTextParagraph::documentVisibleWidth() const +{ + return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); +} + +inline int QTextParagraph::documentX() const +{ + return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); +} + +inline int QTextParagraph::documentY() const +{ + return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); +} + +inline void QTextParagraph::setExtraData( QTextParagraphData *data ) +{ + eData = data; +} + +inline QTextParagraphData *QTextParagraph::extraData() const +{ + return eData; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline void QTextFormatCollection::setDefaultFormat( QTextFormat *f ) +{ + defFormat = f; +} + +inline QTextFormat *QTextFormatCollection::defaultFormat() const +{ + return defFormat; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline QTextFormat *QTextStringChar::format() const +{ + return (type == Regular) ? d.format : d.custom->format; +} + + +#ifndef QT_NO_TEXTCUSTOMITEM +inline QTextCustomItem *QTextStringChar::customItem() const +{ + return isCustom() ? d.custom->custom : 0; +} +#endif + +inline int QTextStringChar::height() const +{ +#ifndef QT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->height() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->height : 0 ); +#else + return format()->height(); +#endif +} + +inline int QTextStringChar::ascent() const +{ +#ifndef QT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->ascent() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->ascent() : 0 ); +#else + return format()->ascent(); +#endif +} + +inline int QTextStringChar::descent() const +{ +#ifndef QT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->descent() : 0; +#else + return format()->descent(); +#endif +} + +#endif //QT_NO_RICHTEXT + +#endif diff --git a/qmake/include/private/qsettings_p.h b/qmake/include/private/qsettings_p.h new file mode 100644 index 0000000..18d118b --- a/dev/null +++ b/qmake/include/private/qsettings_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QSettings related classes +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Windows may use this file in accordance with the Qt Commercial +** License Agreement provided with the Software. +** +** This file is not available for use under any other license without +** express written permission from the copyright holder. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSETTINGS_P_H +#define QSETTINGS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of QSettings. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qstringlist.h" +#include "qmap.h" +#include "qvaluestack.h" +#endif // QT_H + +class QSettingsSysPrivate; + +// QSettingsGroup is a map of key/value pairs +class QSettingsGroup : public QMap<QString,QString> +{ +public: + QSettingsGroup(); + + bool modified; +}; + +// QSettingsHeading is a map of heading/group pairs +class QSettingsHeading : public QMap<QString,QSettingsGroup> +{ +public: + QSettingsHeading::Iterator git; + void read(const QString &); + void parseLine(QTextStream &); +}; + + +class QSettingsPrivate +{ +public: + QSettingsPrivate( QSettings::Format format ); + ~QSettingsPrivate(); + + QSettingsGroup readGroup(); + void removeGroup(const QString &); + void writeGroup(const QString &, const QString &); + QDateTime modificationTime(); + + QStringList searchPaths; + QMap<QString,QSettingsHeading> headings; + QString group; + QString heading; + + /*### static data brings threading trouble + static QString *defProduct; + static QString *defDomain; + */ + QValueStack<QString> groupStack; + QString groupPrefix; + + bool groupDirty :1; + bool modified :1; + bool globalScope :1; + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + // system dependent implementations to use the + // system specific setting database (ie. registry on Windows) + + QSettingsSysPrivate *sysd; + void sysInit(); + void sysClear(); + +#if !defined(Q_NO_BOOL_TYPE) + bool sysWriteEntry( const QString &, bool ); +#endif + bool sysWriteEntry( const QString &, double ); + bool sysWriteEntry( const QString &, int ); + bool sysWriteEntry( const QString &, const QString & ); + bool sysWriteEntry( const QString &, const QStringList & ); + bool sysWriteEntry( const QString &, const QStringList &, const QChar& sep ); + + QStringList sysEntryList(const QString &) const; + QStringList sysSubkeyList(const QString &) const; + + QStringList sysReadListEntry( const QString &, bool * = 0 ) const; + QStringList sysReadListEntry( const QString &, const QChar& sep, bool * = 0 ) const; + QString sysReadEntry( const QString &, const QString &def = QString::null, bool * = 0 ) const; + int sysReadNumEntry( const QString &, int def = 0, bool * = 0 ) const; + double sysReadDoubleEntry( const QString &, double def = 0, bool * = 0 ) const; + bool sysReadBoolEntry( const QString &, bool def = 0, bool * = 0 ) const; + + bool sysRemoveEntry( const QString & ); + + bool sysSync(); + + void sysInsertSearchPath( QSettings::System, const QString & ); + void sysRemoveSearchPath( QSettings::System, const QString & ); +#endif +}; + +#endif // QSETTINGS_P_H diff --git a/qmake/include/private/qsharedmemory_p.h b/qmake/include/private/qsharedmemory_p.h new file mode 100644 index 0000000..4a8339d --- a/dev/null +++ b/qmake/include/private/qsharedmemory_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** $Id$ +** +** Includes system files for shared memory +** +** Created : 020124 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_qws.cpp and qgfxvnc_qws.cpp. This header file may +// change from version to version without notice, or even be removed. +// +// + +#if !defined(QT_QSHM_H) +#define QT_QSHM_H + +#include <qstring.h> + +#if !defined (QT_QWS_NO_SHM) + +#include <sys/types.h> +#include <sys/ipc.h> + +class QSharedMemory { +public: + QSharedMemory(){}; + QSharedMemory(int, QString, char c = 'Q'); + ~QSharedMemory(){}; + + bool create(); + void destroy(); + + bool attach(); + void detach(); + + void setPermissions(mode_t mode); + int size(); + void * base() { return shmBase; }; + +private: + void *shmBase; + int shmSize; + QString shmFile; + char character; +#if defined(QT_POSIX_QSHM) + int shmFD; +#else + int shmId; + key_t key; + int idInitted; +#endif +}; + +#endif +#endif diff --git a/qmake/include/private/qsqldriverinterface_p.h b/qmake/include/private/qsqldriverinterface_p.h new file mode 100644 index 0000000..8957b86 --- a/dev/null +++ b/qmake/include/private/qsqldriverinterface_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Definition of QSqlDriverInterface class +** +** Created : 2000-11-03 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSQLDRIVERINTERFACE_H +#define QSQLDRIVERINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) +#define QM_EXPORT_SQL +#else +#define QM_EXPORT_SQL Q_EXPORT +#endif + +#ifndef QT_NO_SQL + +#ifndef QT_NO_COMPONENT + +// {EDDD5AD5-DF3C-400c-A711-163B72FE5F61} +#ifndef IID_QSqlDriverFactory +#define IID_QSqlDriverFactory QUuid(0xeddd5ad5, 0xdf3c, 0x400c, 0xa7, 0x11, 0x16, 0x3b, 0x72, 0xfe, 0x5f, 0x61) +#endif + +class QSqlDriver; + +struct QM_EXPORT_SQL QSqlDriverFactoryInterface : public QFeatureListInterface +{ + virtual QSqlDriver* create( const QString& name ) = 0; +}; + +#endif //QT_NO_COMPONENT +#endif // QT_NO_SQL + +#endif // QSQLDRIVERINTERFACE_H diff --git a/qmake/include/private/qsqlextension_p.h b/qmake/include/private/qsqlextension_p.h new file mode 100644 index 0000000..597b266 --- a/dev/null +++ b/qmake/include/private/qsqlextension_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Definition of the QSqlExtension class +** +** Created : 2002-06-03 +** +** Copyright (C) 2002 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSQLEXTENSION_P_H +#define QSQLEXTENSION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qmap.h" +#include "qstring.h" +#include "qvariant.h" +#endif // QT_H + +#ifndef QT_NO_SQL + +#if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) +#define QM_EXPORT_SQL +#else +#define QM_EXPORT_SQL Q_EXPORT +#endif + +#if defined(Q_TEMPLATEDLL) +Q_TEMPLATE_EXTERN template class QM_EXPORT_SQL QMap<QString,QVariant>; +Q_TEMPLATE_EXTERN template class QM_EXPORT_SQL QMap<int,QString>; +#endif + +class QM_EXPORT_SQL QSqlExtension { +public: + QSqlExtension(); + virtual ~QSqlExtension(); + virtual bool prepare( const QString& query ); + virtual bool exec(); + virtual void bindValue( const QString& holder, const QVariant& value ); + virtual void bindValue( int pos, const QVariant& value ); + virtual void addBindValue( const QVariant& value ); + void clearValues(); + void clearIndex(); + + enum BindMethod { BindByPosition, BindByName }; + BindMethod bindMethod(); + BindMethod bindm; + int bindCount; + + QMap<int, QString> index; + QMap<QString, QVariant> values; +}; + +class QM_EXPORT_SQL QSqlDriverExtension +{ +public: + QSqlDriverExtension(); + virtual ~QSqlDriverExtension(); + virtual bool isOpen() const = 0; +}; + +#endif +#endif diff --git a/qmake/include/private/qsqlmanager_p.h b/qmake/include/private/qsqlmanager_p.h new file mode 100644 index 0000000..e5f45b8 --- a/dev/null +++ b/qmake/include/private/qsqlmanager_p.h @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Definition of QSqlManager class +** +** Created : 2000-11-03 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the sql module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSQLMANAGER_P_H +#define QSQLMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qglobal.h" +#include "qstring.h" +#include "qstringlist.h" +#include "qsql.h" +#include "qsqlerror.h" +#include "qsqlindex.h" +#include "qsqlcursor.h" +#endif // QT_H + +#if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) +#define QM_EXPORT_SQL +#else +#define QM_EXPORT_SQL Q_EXPORT +#endif + +#ifndef QT_NO_SQL + +class QSqlCursor; +class QSqlForm; +class QSqlCursorManagerPrivate; + +class QM_EXPORT_SQL QSqlCursorManager +{ +public: + QSqlCursorManager(); + virtual ~QSqlCursorManager(); + + virtual void setSort( const QSqlIndex& sort ); + virtual void setSort( const QStringList& sort ); + QStringList sort() const; + virtual void setFilter( const QString& filter ); + QString filter() const; + virtual void setCursor( QSqlCursor* cursor, bool autoDelete = FALSE ); + QSqlCursor* cursor() const; + + virtual void setAutoDelete( bool enable ); + bool autoDelete() const; + + virtual bool refresh(); + virtual bool findBuffer( const QSqlIndex& idx, int atHint = 0 ); + +private: + QSqlCursorManagerPrivate* d; +}; + +#ifndef QT_NO_SQL_FORM + +class QSqlFormManagerPrivate; + +class QM_EXPORT_SQL QSqlFormManager +{ +public: + QSqlFormManager(); + virtual ~QSqlFormManager(); + + virtual void setForm( QSqlForm* form ); + QSqlForm* form(); + virtual void setRecord( QSqlRecord* record ); + QSqlRecord* record(); + + virtual void clearValues(); + virtual void readFields(); + virtual void writeFields(); + +private: + QSqlFormManagerPrivate* d; +}; + +#endif + +class QWidget; +class QDataManagerPrivate; + +class QM_EXPORT_SQL QDataManager +{ +public: + QDataManager(); + virtual ~QDataManager(); + + virtual void setMode( QSql::Op m ); + QSql::Op mode() const; + virtual void setAutoEdit( bool autoEdit ); + bool autoEdit() const; + + virtual void handleError( QWidget* parent, const QSqlError& error ); + virtual QSql::Confirm confirmEdit( QWidget* parent, QSql::Op m ); + virtual QSql::Confirm confirmCancel( QWidget* parent, QSql::Op m ); + + virtual void setConfirmEdits( bool confirm ); + virtual void setConfirmInsert( bool confirm ); + virtual void setConfirmUpdate( bool confirm ); + virtual void setConfirmDelete( bool confirm ); + virtual void setConfirmCancels( bool confirm ); + + bool confirmEdits() const; + bool confirmInsert() const; + bool confirmUpdate() const; + bool confirmDelete() const; + bool confirmCancels() const; + +private: + QDataManagerPrivate* d; +}; + + +#endif +#endif diff --git a/qmake/include/private/qstyleinterface_p.h b/qmake/include/private/qstyleinterface_p.h new file mode 100644 index 0000000..4aaedc7 --- a/dev/null +++ b/qmake/include/private/qstyleinterface_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** $Id$ +** +** ... +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSTYLEINTERFACE_H +#define QSTYLEINTERFACE_H + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#ifndef QT_NO_STYLE +#ifndef QT_NO_COMPONENT + +class QStyle; + +// {FC1B6EBE-053C-49c1-A483-C377739AB9A5} +#ifndef IID_QStyleFactory +#define IID_QStyleFactory QUuid(0xfc1b6ebe, 0x53c, 0x49c1, 0xa4, 0x83, 0xc3, 0x77, 0x73, 0x9a, 0xb9, 0xa5) +#endif + +struct Q_EXPORT QStyleFactoryInterface : public QFeatureListInterface +{ + virtual QStyle* create( const QString& style ) = 0; +}; + +#endif //QT_NO_COMPONENT +#endif //QT_NO_STYLE + +#endif //QSTYLEINTERFACE_H diff --git a/qmake/include/private/qsvgdevice_p.h b/qmake/include/private/qsvgdevice_p.h new file mode 100644 index 0000000..c1cc389 --- a/dev/null +++ b/qmake/include/private/qsvgdevice_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the QSvgDevice class +** +** Created : 20001024 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the xml module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +*****************************************************************************/ + +#ifndef QSVGDEVICE_H +#define QSVGDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QPicture class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "qpaintdevice.h" +#include "qrect.h" +#include "qdom.h" +#endif // QT_H + +#if !defined(QT_MODULE_XML) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_XML ) +#define QM_EXPORT_SVG +#else +#define QM_EXPORT_SVG Q_EXPORT +#endif + +#ifndef QT_NO_SVG + +class QPainter; +class QDomNode; +class QDomNamedNodeMap; +struct QSvgDeviceState; +class QSvgDevicePrivate; + +class QM_EXPORT_SVG QSvgDevice : public QPaintDevice +{ +public: + QSvgDevice(); + ~QSvgDevice(); + + bool play( QPainter *p ); + + QString toString() const; + + bool load( QIODevice *dev ); + bool save( QIODevice *dev ); + bool save( const QString &fileName ); + + QRect boundingRect() const; + void setBoundingRect( const QRect &r ); + +protected: + virtual bool cmd ( int, QPainter*, QPDevCmdParam* ); + virtual int metric( int ) const; + +private: + // reading + bool play( const QDomNode &node ); + void saveAttributes(); + void restoreAttributes(); + QColor parseColor( const QString &col ); + double parseLen( const QString &str, bool *ok=0, bool horiz=TRUE ) const; + int lenToInt( const QDomNamedNodeMap &map, const QString &attr, + int def=0 ) const; + void setStyleProperty( const QString &prop, const QString &val, + QPen *pen, QFont *font, int *talign ); + void setStyle( const QString &s ); + void setTransform( const QString &tr ); + void drawPath( const QString &data ); + + // writing + void applyStyle( QDomElement *e, int c ) const; + void applyTransform( QDomElement *e ) const; + + // reading + QRect brect; // bounding rectangle + QDomDocument doc; // document tree + QDomNode current; + QPoint curPt; + QSvgDeviceState *curr; + QPainter *pt; // used by play() et al + + // writing + bool dirtyTransform, dirtyStyle; + + QSvgDevicePrivate *d; +}; + +inline QRect QSvgDevice::boundingRect() const +{ + return brect; +} + +#endif // QT_NO_SVG + +#endif // QSVGDEVICE_H diff --git a/qmake/include/private/qtextcodecinterface_p.h b/qmake/include/private/qtextcodecinterface_p.h new file mode 100644 index 0000000..d2a2cb9 --- a/dev/null +++ b/qmake/include/private/qtextcodecinterface_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QTextCodecFactoryInterface interface +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTEXTCODECINTERFACE_P_H +#define QTEXTCODECINTERFACE_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qpsprinter.cpp and qprinter_x11.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include <private/qcom_p.h> +#endif // QT_H + +#ifndef QT_NO_TEXTCODEC +#ifndef QT_NO_COMPONENT + +class QTextCodec; + + +// {F55BFA60-F695-11D4-823E-009027DC0F37} +#ifndef IID_QTextCodecFactory +#define IID_QTextCodecFactory QUuid( 0xf55bfa60, 0xf695, 0x11d4, 0x82, 0x3e, 0x00, 0x90, 0x27, 0xdc, 0x0f, 0x37) +#endif + + +struct Q_EXPORT QTextCodecFactoryInterface : public QFeatureListInterface +{ + virtual QTextCodec *createForMib( int mib ) = 0; + virtual QTextCodec *createForName( const QString &name ) = 0; +}; + +#endif // QT_NO_COMPONENT +#endif // QT_NO_TEXTCODEC + +#endif // QTEXTCODECINTERFACE_P_H diff --git a/qmake/include/private/qtitlebar_p.h b/qmake/include/private/qtitlebar_p.h new file mode 100644 index 0000000..dabb6bf --- a/dev/null +++ b/qmake/include/private/qtitlebar_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some Qt private functions. +** +** Created : 2000-01-01 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTITLEBAR_P_H +#define QTITLEBAR_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qworkspace.cpp and qdockwindow.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "qbutton.h" +#include "qlabel.h" +#endif // QT_H + +#if !defined(QT_NO_TITLEBAR) + +class QToolTip; +class QTitleBarPrivate; +class QPixmap; + +class Q_EXPORT QTitleBar : public QWidget +{ + Q_OBJECT + Q_PROPERTY( bool autoRaise READ autoRaise WRITE setAutoRaise ) + Q_PROPERTY( bool movable READ isMovable WRITE setMovable ) + +public: + QTitleBar (QWidget* w, QWidget* parent, const char* name=0); + ~QTitleBar(); + + bool isActive() const; + bool usesActiveColor() const; + virtual QString visibleText() const; + + bool isMovable() const; + void setMovable(bool); + + bool autoRaise() const; + void setAutoRaise(bool); + + QWidget *window() const; + + QSize sizeHint() const; + +#ifdef QT_NO_WIDGET_TOPEXTRA + // We provide one, since titlebar is useless otherwise. + QString caption() const; +#endif + +public slots: + void setActive( bool ); + void setCaption( const QString& title ); + void setIcon( const QPixmap& icon ); + +signals: + void doActivate(); + void doNormal(); + void doClose(); + void doMaximize(); + void doMinimize(); + void doShade(); + void showOperationMenu(); + void popupOperationMenu( const QPoint& ); + void doubleClicked(); + +protected: + bool event( QEvent *); + void resizeEvent( QResizeEvent *); + void contextMenuEvent( QContextMenuEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseDoubleClickEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void enterEvent( QEvent *e ); + void leaveEvent( QEvent *e ); + void paintEvent( QPaintEvent *p ); + + virtual void cutText(); + +private: + void readColors(); + + QTitleBarPrivate *d; +#if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator= + QTitleBar( const QTitleBar & ); + QTitleBar &operator=( const QTitleBar & ); +#endif +}; + +#endif +#endif //QTITLEBAR_P_H diff --git a/qmake/include/private/qucom_p.h b/qmake/include/private/qucom_p.h new file mode 100644 index 0000000..d2ff48e --- a/dev/null +++ b/qmake/include/private/qucom_p.h @@ -0,0 +1,499 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the QUcom interfaces +** +** Created : 990101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QUCOM_H +#define QUCOM_H + +#ifndef QT_H +#include <qstring.h> +#include "quuid.h" +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifdef check +#undef check +#endif + +struct QUObject; +struct QUInterfaceDescription; +struct QUnknownInterface; +struct QDispatchInterface; + + +struct Q_EXPORT QUBuffer +{ + virtual long read( char *data, ulong maxlen ) = 0; + virtual long write( const char *data, ulong len ) = 0; +}; + + +// A type for a QUObject +struct Q_EXPORT QUType +{ + virtual const QUuid *uuid() const = 0; + virtual const char *desc() const = 0; + + + virtual bool canConvertFrom( QUObject *, QUType * ) = 0; + // virtual private, only called by canConvertFrom + virtual bool canConvertTo( QUObject *, QUType * ) = 0; + + + virtual bool convertFrom( QUObject *, QUType * ) = 0; + // virtual private, only called by convertFrom + virtual bool convertTo( QUObject *, QUType * ) = 0; + + virtual void clear( QUObject * ) = 0; + + virtual int serializeTo( QUObject *, QUBuffer * ) = 0; + virtual int serializeFrom( QUObject *, QUBuffer * ) = 0; + + static bool isEqual( const QUType *t1, const QUType *t2 ); + static bool check( QUObject* o, QUType* t ); +}; + + +// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} +extern Q_EXPORT const QUuid TID_QUType_Null; +struct Q_EXPORT QUType_Null : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ); + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_Null static_QUType_Null; + + +// The magic QUObject +struct Q_EXPORT QUObject +{ +public: // scary MSVC bug makes this necessary + QUObject() : type( &static_QUType_Null ) {} + ~QUObject() { type->clear( this ); } + + QUType *type; + + // the unavoidable union + union + { + bool b; + + char c; + short s; + int i; + long l; + + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + + float f; + double d; + + char byte[16]; + + struct { + char* data; + unsigned long size; + } bytearray; + + void* ptr; + + struct { + void *ptr; + bool owner; + } voidstar; + + struct { + char *ptr; + bool owner; + } charstar; + + struct { + char *ptr; + bool owner; + } utf8; + + struct { + char *ptr; + bool owner; + } local8bit; + + QUnknownInterface* iface; + QDispatchInterface* idisp; + + } payload; + +}; + + +// A parameter description describes one method parameters. A +// parameter has a name, a type and a flag describing whether it's an +// in parameter, an out parameter, or both ways +struct Q_EXPORT QUParameter +{ + const char* name; + QUType *type; + const void* typeExtra; //Usually 0, UEnum* for QUType_enum, const char* for QUType_ptr, int* for QUType_varptr + enum { In = 1, Out = 2, InOut = In | Out }; + int inOut; +}; + +// A method description describes one method. A method has a name and +// an array of parameters. +struct Q_EXPORT QUMethod +{ + const char* name; + int count; + const QUParameter* parameters; +}; + +// A Property description. Not used yet in the example. +struct Q_EXPORT QUProperty +{ + const char* name; + QUType* type; + const void* typeExtra; //type dependend. Usually 0, but UEnum for QUTypeenum or const char* for QUTypeptr + + int set; // -1 undefined + int get; // -1 undefined + + int designable; // -1 FALSE, -2 TRUE, else method + int stored; // -1 FALSE, -2 TRUE, else method +}; + +// An interface description describes one interface, that is all its +// methods and properties. +struct Q_EXPORT QUInterfaceDescription +{ + int methodCount; + const QUMethod* methods; + int propertyCount; + const QUProperty* properties; +}; + + +// A component description describe one component, that is its name, +// vendor, release, info, its component uuid and all its interface +// uuids. +struct Q_EXPORT QUComponentDescription +{ + const char* name; + const char* vendor; + const char* release; + const char* info; + QUuid cid; + int count; + const QUuid* interfaces; +}; + + +// A component server description describe one component server, that +// is its name, vendor, release, info and the descriptions of all +// components it can instantiate. +struct Q_EXPORT QUComponentServerDescription +{ + const char* name; + const char* vendor; + const char* release; + const char* info; + int count; + const QUComponentDescription* components; +}; + + + +struct Q_EXPORT QUEnumItem // - a name/value pair +{ + const char *key; + int value; +}; + +struct Q_EXPORT QUEnum +{ + const char *name; // - enumerator name + unsigned int count; // - number of values + const QUEnumItem *items; // - the name/value pairs + bool set; // whether enum has to be treated as a set +}; + +inline bool QUType::isEqual( const QUType *t1, const QUType *t2 ) { + return t1 == t2 || t1->uuid() == t2->uuid() || + *(t1->uuid()) == *(t2->uuid()); +} + +inline bool QUType::check( QUObject* o, QUType* t ) { + return isEqual( o->type, t ) || t->convertFrom( o, o->type ); +} + + + +// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} +extern Q_EXPORT const QUuid TID_QUType_enum; +struct Q_EXPORT QUType_enum : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, int ); + int &get( QUObject * o ) { return o->payload.i; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_enum static_QUType_enum; + + +// {8AC26448-5AB4-49eb-968C-8F30AB13D732} +extern Q_EXPORT const QUuid TID_QUType_ptr; +struct Q_EXPORT QUType_ptr : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, const void* ); + void* &get( QUObject * o ) { return o->payload.ptr; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_ptr static_QUType_ptr; + +// {97A2594D-6496-4402-A11E-55AEF2D4D25C} +extern Q_EXPORT const QUuid TID_QUType_iface; +struct Q_EXPORT QUType_iface : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, QUnknownInterface* ); + QUnknownInterface* &get( QUObject *o ){ return o->payload.iface; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_iface static_QUType_iface; + +// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} +extern Q_EXPORT const QUuid TID_QUType_idisp; +struct Q_EXPORT QUType_idisp : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, QDispatchInterface* ); + QDispatchInterface* &get( QUObject *o ){ return o->payload.idisp; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_idisp static_QUType_idisp; + +// {CA42115D-13D0-456c-82B5-FC10187F313E} +extern Q_EXPORT const QUuid TID_QUType_bool; +struct Q_EXPORT QUType_bool : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, bool ); + bool &get( QUObject *o ) { return o->payload.b; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_bool static_QUType_bool; + +// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} +extern Q_EXPORT const QUuid TID_QUType_int; +struct Q_EXPORT QUType_int : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, int ); + int &get( QUObject *o ) { return o->payload.i; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_int static_QUType_int; + +// {5938712A-C496-11D5-8CB2-00C0F03BC0F3} +extern Q_EXPORT const QUuid TID_QUType_uint; +struct Q_EXPORT QUType_uint : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, uint ); + uint &get( QUObject *o ) { return o->payload.ui; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_uint static_QUType_uint; + +// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} +extern Q_EXPORT const QUuid TID_QUType_double; +struct Q_EXPORT QUType_double : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, double ); + double &get( QUObject *o ) { return o->payload.d; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_double static_QUType_double; + +// {544C5175-6993-4486-B04D-CEC4D21BF4B9 } +extern Q_EXPORT const QUuid TID_QUType_float; +struct Q_EXPORT QUType_float : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, float ); + float &get( QUObject *o ) { return o->payload.f; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_float static_QUType_float; + +// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} +extern Q_EXPORT const QUuid TID_QUType_charstar; +struct Q_EXPORT QUType_charstar : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, const char*, bool take = FALSE ); + char* get( QUObject *o ){ return o->payload.charstar.ptr; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ); + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); + +}; +extern Q_EXPORT QUType_charstar static_QUType_charstar; + +// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} +extern const QUuid TID_QUType_QString; + +struct Q_EXPORT QUType_QString : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, const QString & ); + QString &get( QUObject * o ) { return *(QString*)o->payload.ptr; } + + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ); + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); + +}; +extern Q_EXPORT QUType_QString static_QUType_QString; + + +#endif // QUCOM_H diff --git a/qmake/include/private/qucomextra_p.h b/qmake/include/private/qucomextra_p.h new file mode 100644 index 0000000..3de6104 --- a/dev/null +++ b/qmake/include/private/qucomextra_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** $Id$ +** +** Definition of extra QUcom classes +** +** Created : 990101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QUCOMEXTRA_H +#define QUCOMEXTRA_H + +#ifndef QT_H +#include <private/qucom_p.h> +#endif // QT_H + + +class QVariant; + +#ifndef QT_NO_VARIANT +// 6dc75d58-a1d9-4417-b591-d45c63a3a4ea +extern const QUuid TID_QUType_QVariant; + +struct Q_EXPORT QUType_QVariant : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, const QVariant & ); + QVariant &get( QUObject * o ); + + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ); + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_QVariant static_QUType_QVariant; +#endif //QT_NO_VARIANT + + +// {0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 } +extern Q_EXPORT const QUuid TID_QUType_varptr; +struct Q_EXPORT QUType_varptr : public QUType +{ + const QUuid *uuid() const; + const char *desc() const; + + void set( QUObject *, const void* ); + void* &get( QUObject * o ) { return o->payload.ptr; } + bool canConvertFrom( QUObject *, QUType * ); + bool canConvertTo( QUObject *, QUType * ); + bool convertFrom( QUObject *, QUType * ); + bool convertTo( QUObject *, QUType * ); + void clear( QUObject * ) {} + int serializeTo( QUObject *, QUBuffer * ); + int serializeFrom( QUObject *, QUBuffer * ); +}; +extern Q_EXPORT QUType_varptr static_QUType_varptr; + + +#endif // QUCOMEXTRA_H + diff --git a/qmake/include/private/qwidget_p.h b/qmake/include/private/qwidget_p.h new file mode 100644 index 0000000..80368d0 --- a/dev/null +++ b/qmake/include/private/qwidget_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** $Id$ +** +** Definition of some Qt private functions. +** +** Created : 000903 +** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QWIDGET_P_H +#define QWIDGET_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#endif // QT_H + +#if defined (Q_WS_X11) || defined (Q_WS_QWS) +extern int qt_widget_tlw_gravity; +#endif + +#endif diff --git a/qmake/include/private/qwidgetinterface_p.h b/qmake/include/private/qwidgetinterface_p.h new file mode 100644 index 0000000..5b5776b --- a/dev/null +++ b/qmake/include/private/qwidgetinterface_p.h @@ -0,0 +1,111 @@ + /********************************************************************** +** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** +** This file is part of Qt Designer. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QWIDGETINTERFACE_H +#define QWIDGETINTERFACE_H + + +#ifndef QT_H +#include <private/qcom_p.h> +#include <qiconset.h> +#endif // QT_H + +#ifndef QT_NO_WIDGETPLUGIN + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +class QWidget; + +// {55184143-f18f-42c0-a8eb-71c01516019a} +#ifndef IID_QWidgetFactory +#define IID_QWidgetFactory QUuid( 0x55184143, 0xf18f, 0x42c0, 0xa8, 0xeb, 0x71, 0xc0, 0x15, 0x16, 0x1, 0x9a ) +#endif + +/*! To add custom widgets to the Qt Designer, implement that interface + in your custom widget plugin. + + You also have to implement the function featureList() (\sa + QFeatureListInterface) and return there all widgets (names of it) + which this interface provides. +*/ + +struct QWidgetFactoryInterface : public QFeatureListInterface +{ +public: + + /*! In the implementation create and return the widget \a widget + here, use \a parent and \a name when creating the widget */ + virtual QWidget* create( const QString &widget, QWidget* parent = 0, const char* name = 0 ) = 0; + + /*! In the implementation return the name of the group of the + widget \a widget */ + virtual QString group( const QString &widget ) const = 0; + + /*! In the implementation return the iconset, which should be used + in the Qt Designer menubar and toolbar to represent the widget + \a widget */ + virtual QIconSet iconSet( const QString &widget ) const = 0; + + /*! In the implementation return the include file which is needed + for the widget \a widget in the generated code which uic + generates. */ + virtual QString includeFile( const QString &widget ) const = 0; + + /*! In the implementation return the text which should be + displayed as tooltip for the widget \a widget */ + virtual QString toolTip( const QString &widget ) const = 0; + + /*! In the implementation return the text which should be used for + what's this help for the widget \a widget. */ + virtual QString whatsThis( const QString &widget ) const = 0; + + /*! In the implementation return TRUE here, of the \a widget + should be able to contain other widget in the Qt Designer, else + FALSE. */ + virtual bool isContainer( const QString &widget ) const = 0; +}; + +#if CONTAINER_CUSTOM_WIDGETS +// {15976628-e3c3-47f4-b525-d124a3caf30e} +#ifndef IID_QWidgetContainer +#define IID_QWidgetContainer QUuid( 0x15976628, 0xe3c3, 0x47f4, 0xb5, 0x25, 0xd1, 0x24, 0xa3, 0xca, 0xf3, 0x0e ) +#endif + +struct QWidgetContainerInterfacePrivate : public QUnknownInterface +{ +public: + virtual QWidget *containerOfWidget( QWidget *widget ) const = 0; + virtual QWidgetList containersOf( QWidget *widget ) const = 0; + virtual bool isPassiveInteractor( QWidget *widget ) const = 0; +}; +#endif + +#endif // QT_NO_WIDGETPLUGIN +#endif // QWIDGETINTERFACE_H diff --git a/qmake/include/private/qwidgetresizehandler_p.h b/qmake/include/private/qwidgetresizehandler_p.h new file mode 100644 index 0000000..ca229db --- a/dev/null +++ b/qmake/include/private/qwidgetresizehandler_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the QWidgetResizeHandler class +** +** Created : 001010 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the workspace module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QWIDGETRESIZEHANDLER_H +#define QWIDGETRESIZEHANDLER_H + +#ifndef QT_H +#include "qobject.h" +#endif // QT_H +#ifndef QT_NO_RESIZEHANDLER +class QMouseEvent; +class QKeyEvent; + +class Q_EXPORT QWidgetResizeHandler : public QObject +{ + Q_OBJECT + +public: + QWidgetResizeHandler( QWidget *parent, QWidget *cw = 0, const char *name = 0 ); + void setActive( bool b ) { active = b; if ( !active ) setMouseCursor( Nowhere ); } + bool isActive() const { return active; } + void setMovingEnabled( bool b ) { moving = b; } + bool isMovingEnabled() const { return moving; } + + bool isButtonDown() const { return buttonDown; } + + void setExtraHeight( int h ) { extrahei = h; } + void setSizeProtection( bool b ) { sizeprotect = b; } + + void doResize(); + void doMove(); + +signals: + void activate(); + +protected: + bool eventFilter( QObject *o, QEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void keyPressEvent( QKeyEvent *e ); + +private: + enum MousePosition { + Nowhere, + TopLeft, BottomRight, BottomLeft, TopRight, + Top, Bottom, Left, Right, + Center + }; + + QWidget *widget; + QWidget *childWidget; + QPoint moveOffset; + QPoint invertedMoveOffset; + MousePosition mode; + int extrahei; + int range; + uint buttonDown :1; + uint moveResizeMode :1; + uint active :1; + uint sizeprotect :1; + uint moving :1; + + void setMouseCursor( MousePosition m ); + bool isMove() const { + return moveResizeMode && mode == Center; + } + bool isResize() const { + return moveResizeMode && !isMove(); + } + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QWidgetResizeHandler( const QWidgetResizeHandler & ); + QWidgetResizeHandler& operator=( const QWidgetResizeHandler & ); +#endif + +}; + +#endif //QT_NO_RESIZEHANDLER +#endif diff --git a/qmake/include/qasciidict.h b/qmake/include/qasciidict.h new file mode 100644 index 0000000..8f344cd --- a/dev/null +++ b/qmake/include/qasciidict.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QAsciiDict template class +** +** Created : 920821 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QASCIIDICT_H +#define QASCIIDICT_H + +#ifndef QT_H +#include "qgdict.h" +#endif // QT_H + +template<class type> +class QAsciiDict +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGDict +#endif +{ +public: + QAsciiDict(int size=17, bool caseSensitive=TRUE, bool copyKeys=TRUE ) + : QGDict(size,AsciiKey,caseSensitive,copyKeys) {} + QAsciiDict( const QAsciiDict<type> &d ) : QGDict(d) {} + ~QAsciiDict() { clear(); } + QAsciiDict<type> &operator=(const QAsciiDict<type> &d) + { return (QAsciiDict<type>&)QGDict::operator=(d); } + uint count() const { return QGDict::count(); } + uint size() const { return QGDict::size(); } + bool isEmpty() const { return QGDict::count() == 0; } + + void insert( const char *k, const type *d ) + { QGDict::look_ascii(k,(Item)d,1); } + void replace( const char *k, const type *d ) + { QGDict::look_ascii(k,(Item)d,2); } + bool remove( const char *k ) { return QGDict::remove_ascii(k); } + type *take( const char *k ) { return (type *)QGDict::take_ascii(k); } + type *find( const char *k ) const + { return (type *)((QGDict*)this)->QGDict::look_ascii(k,0,0); } + type *operator[]( const char *k ) const + { return (type *)((QGDict*)this)->QGDict::look_ascii(k,0,0); } + + void clear() { QGDict::clear(); } + void resize( uint n ) { QGDict::resize(n); } + void statistics() const { QGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); + virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QAsciiDict<void>::deleteItem( QPtrCollection::Item ) +{ +} +#endif + +template<class type> inline void QAsciiDict<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template<class type> +class QAsciiDictIterator : public QGDictIterator +{ +public: + QAsciiDictIterator(const QAsciiDict<type> &d) + : QGDictIterator((QGDict &)d) {} + ~QAsciiDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)QGDictIterator::toFirst(); } + operator type *() const { return (type *)QGDictIterator::get(); } + type *current() const { return (type *)QGDictIterator::get(); } + const char *currentKey() const { return QGDictIterator::getKeyAscii(); } + type *operator()() { return (type *)QGDictIterator::operator()(); } + type *operator++() { return (type *)QGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j);} +}; + +#endif // QASCIIDICT_H diff --git a/qmake/include/qbitarray.h b/qmake/include/qbitarray.h new file mode 100644 index 0000000..65c5cd3 --- a/dev/null +++ b/qmake/include/qbitarray.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QBitArray class +** +** Created : 940118 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QBITARRAY_H +#define QBITARRAY_H + +#ifndef QT_H +#include "qstring.h" +#endif // QT_H + + +/***************************************************************************** + QBitVal class; a context class for QBitArray::operator[] + *****************************************************************************/ + +class QBitArray; + +class Q_EXPORT QBitVal +{ +private: + QBitArray *array; + uint index; +public: + QBitVal( QBitArray *a, uint i ) : array(a), index(i) {} + operator int(); + QBitVal &operator=( const QBitVal &v ); + QBitVal &operator=( bool v ); +}; + + +/***************************************************************************** + QBitArray class + *****************************************************************************/ + +class Q_EXPORT QBitArray : public QByteArray +{ +public: + QBitArray(); + QBitArray( uint size ); + QBitArray( const QBitArray &a ) : QByteArray( a ) {} + + QBitArray &operator=( const QBitArray & ); + + uint size() const; + bool resize( uint size ); + + bool fill( bool v, int size = -1 ); + + void detach(); + QBitArray copy() const; + + bool testBit( uint index ) const; + void setBit( uint index ); + void setBit( uint index, bool value ); + void clearBit( uint index ); + bool toggleBit( uint index ); + + bool at( uint index ) const; + QBitVal operator[]( int index ); + bool operator[]( int index ) const; + + QBitArray &operator&=( const QBitArray & ); + QBitArray &operator|=( const QBitArray & ); + QBitArray &operator^=( const QBitArray & ); + QBitArray operator~() const; + +protected: + struct bitarr_data : public QGArray::array_data { + uint nbits; + }; + array_data *newData() { return new bitarr_data; } + void deleteData( array_data *d ) { delete (bitarr_data*)d; } +private: + void pad0(); +}; + + +inline QBitArray &QBitArray::operator=( const QBitArray &a ) +{ return (QBitArray&)assign( a ); } + +inline uint QBitArray::size() const +{ return ((bitarr_data*)sharedBlock())->nbits; } + +inline void QBitArray::setBit( uint index, bool value ) +{ if ( value ) setBit(index); else clearBit(index); } + +inline bool QBitArray::at( uint index ) const +{ return testBit(index); } + +inline QBitVal QBitArray::operator[]( int index ) +{ return QBitVal( (QBitArray*)this, index ); } + +inline bool QBitArray::operator[]( int index ) const +{ return testBit( index ); } + + +/***************************************************************************** + Misc. QBitArray operator functions + *****************************************************************************/ + +Q_EXPORT QBitArray operator&( const QBitArray &, const QBitArray & ); +Q_EXPORT QBitArray operator|( const QBitArray &, const QBitArray & ); +Q_EXPORT QBitArray operator^( const QBitArray &, const QBitArray & ); + + +inline QBitVal::operator int() +{ + return array->testBit( index ); +} + +inline QBitVal &QBitVal::operator=( const QBitVal &v ) +{ + array->setBit( index, v.array->testBit(v.index) ); + return *this; +} + +inline QBitVal &QBitVal::operator=( bool v ) +{ + array->setBit( index, v ); + return *this; +} + + +/***************************************************************************** + QBitArray stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QBitArray & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QBitArray & ); +#endif + +#endif // QBITARRAY_H diff --git a/qmake/include/qbuffer.h b/qmake/include/qbuffer.h new file mode 100644 index 0000000..f1b869b --- a/dev/null +++ b/qmake/include/qbuffer.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QBuffer class +** +** Created : 930812 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QBUFFER_H +#define QBUFFER_H + +#ifndef QT_H +#include "qiodevice.h" +#include "qstring.h" +#endif // QT_H + + +class Q_EXPORT QBuffer : public QIODevice +{ +public: + QBuffer(); + QBuffer( QByteArray ); + ~QBuffer(); + + QByteArray buffer() const; + bool setBuffer( QByteArray ); + + bool open( int ); + void close(); + void flush(); + + Offset size() const; + Offset at() const; + bool at( Offset ); + + Q_LONG readBlock( char *p, Q_ULONG ); + Q_LONG writeBlock( const char *p, Q_ULONG ); + Q_LONG writeBlock( const QByteArray& data ) + { return QIODevice::writeBlock(data); } + Q_LONG readLine( char *p, Q_ULONG ); + + int getch(); + int putch( int ); + int ungetch( int ); + +protected: + QByteArray a; + +private: + uint a_len; + uint a_inc; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QBuffer( const QBuffer & ); + QBuffer &operator=( const QBuffer & ); +#endif +}; + + +inline QByteArray QBuffer::buffer() const +{ return a; } + +inline QIODevice::Offset QBuffer::size() const +{ return (Offset)a.size(); } + +inline QIODevice::Offset QBuffer::at() const +{ return ioIndex; } + + +#endif // QBUFFER_H diff --git a/qmake/include/qcache.h b/qmake/include/qcache.h new file mode 100644 index 0000000..94ba323 --- a/dev/null +++ b/qmake/include/qcache.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QCache template class +** +** Created : 950209 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCACHE_H +#define QCACHE_H + +#ifndef QT_H +#include "qgcache.h" +#endif // QT_H + +template<class type> +class QCache +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGCache +#endif +{ +public: + QCache( const QCache<type> &c ) : QGCache(c) {} + QCache( int maxCost=100, int size=17, bool caseSensitive=TRUE ) + : QGCache( maxCost, size, StringKey, caseSensitive, FALSE ) {} + ~QCache() { clear(); } + QCache<type> &operator=( const QCache<type> &c ) + { return (QCache<type>&)QGCache::operator=(c); } + int maxCost() const { return QGCache::maxCost(); } + int totalCost() const { return QGCache::totalCost(); } + void setMaxCost( int m ) { QGCache::setMaxCost(m); } + uint count() const { return QGCache::count(); } + uint size() const { return QGCache::size(); } + bool isEmpty() const { return QGCache::count() == 0; } + void clear() { QGCache::clear(); } + bool insert( const QString &k, const type *d, int c=1, int p=0 ) + { return QGCache::insert_string(k,(Item)d,c,p);} + bool remove( const QString &k ) + { return QGCache::remove_string(k); } + type *take( const QString &k ) + { return (type *)QGCache::take_string(k); } + type *find( const QString &k, bool ref=TRUE ) const + { return (type *)QGCache::find_string(k,ref);} + type *operator[]( const QString &k ) const + { return (type *)QGCache::find_string(k);} + void statistics() const { QGCache::statistics(); } +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QCache<void>::deleteItem( QPtrCollection::Item ) +{ +} +#endif + +template<class type> inline void QCache<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template<class type> +class QCacheIterator : public QGCacheIterator +{ +public: + QCacheIterator( const QCache<type> &c ):QGCacheIterator((QGCache &)c) {} + QCacheIterator( const QCacheIterator<type> &ci) + : QGCacheIterator( (QGCacheIterator &)ci ) {} + QCacheIterator<type> &operator=(const QCacheIterator<type>&ci) + { return ( QCacheIterator<type>&)QGCacheIterator::operator=( ci ); } + uint count() const { return QGCacheIterator::count(); } + bool isEmpty() const { return QGCacheIterator::count() == 0; } + bool atFirst() const { return QGCacheIterator::atFirst(); } + bool atLast() const { return QGCacheIterator::atLast(); } + type *toFirst() { return (type *)QGCacheIterator::toFirst(); } + type *toLast() { return (type *)QGCacheIterator::toLast(); } + operator type *() const { return (type *)QGCacheIterator::get(); } + type *current() const { return (type *)QGCacheIterator::get(); } + QString currentKey() const{ return QGCacheIterator::getKeyString(); } + type *operator()() { return (type *)QGCacheIterator::operator()();} + type *operator++() { return (type *)QGCacheIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGCacheIterator::operator+=(j);} + type *operator--() { return (type *)QGCacheIterator::operator--(); } + type *operator-=(uint j) { return (type *)QGCacheIterator::operator-=(j);} +}; + +#endif // QCACHE_H diff --git a/qmake/include/qcleanuphandler.h b/qmake/include/qcleanuphandler.h new file mode 100644 index 0000000..471dc7b --- a/dev/null +++ b/qmake/include/qcleanuphandler.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** $Id$ +** +** ... +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCLEANUPHANDLER_H +#define QCLEANUPHANDLER_H + +#ifndef QT_H +#include <qptrlist.h> +#endif // QT_H + +template<class Type> +class QCleanupHandler +{ +public: + QCleanupHandler() : cleanupObjects( 0 ) {} + ~QCleanupHandler() { clear(); } + + Type* add( Type **object ) { + if ( !cleanupObjects ) + cleanupObjects = new QPtrList<Type*>; + cleanupObjects->insert( 0, object ); + return *object; + } + + void remove( Type **object ) { + if ( !cleanupObjects ) + return; + if ( cleanupObjects->findRef( object ) >= 0 ) + (void) cleanupObjects->take(); + } + + bool isEmpty() const { + return cleanupObjects ? cleanupObjects->isEmpty() : TRUE; + } + + void clear() { + if ( !cleanupObjects ) + return; + QPtrListIterator<Type*> it( *cleanupObjects ); + Type **object; + while ( ( object = it.current() ) ) { + delete *object; + *object = 0; + cleanupObjects->remove( object ); + } + delete cleanupObjects; + cleanupObjects = 0; + } + +private: + QPtrList<Type*> *cleanupObjects; +}; + +template<class Type> +class QSingleCleanupHandler +{ +public: + QSingleCleanupHandler() : object( 0 ) {} + ~QSingleCleanupHandler() { + if ( object ) { + delete *object; + *object = 0; + } + } + Type* set( Type **o ) { + object = o; + return *object; + } + void reset() { object = 0; } +private: + Type **object; +}; + +template<class Type> +class QSharedCleanupHandler +{ +public: + QSharedCleanupHandler() : object( 0 ) {} + ~QSharedCleanupHandler() { + if ( object ) { + if ( (*object)->deref() ) + delete *object; + *object = 0; + } + } + Type* set( Type **o ) { + object = o; + return *object; + } + void reset() { object = 0; } +private: + Type **object; +}; + +#endif //QCLEANUPHANDLER_H diff --git a/qmake/include/qcstring.h b/qmake/include/qcstring.h new file mode 100644 index 0000000..004bb3b --- a/dev/null +++ b/qmake/include/qcstring.h @@ -0,0 +1,391 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the extended char array operations, +** and QByteArray and QCString classes +** +** Created : 920609 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QCSTRING_H +#define QCSTRING_H + +#ifndef QT_H +#include "qmemarray.h" +#endif // QT_H + +#include <string.h> + + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +Q_EXPORT void *qmemmove( void *dst, const void *src, uint len ); + +Q_EXPORT char *qstrdup( const char * ); + +Q_EXPORT inline uint qstrlen( const char *str ) +{ return str ? (uint)strlen(str) : 0; } + +Q_EXPORT inline char *qstrcpy( char *dst, const char *src ) +{ return src ? strcpy(dst, src) : 0; } + +Q_EXPORT char *qstrncpy( char *dst, const char *src, uint len ); + +Q_EXPORT inline int qstrcmp( const char *str1, const char *str2 ) +{ + return ( str1 && str2 ) ? strcmp( str1, str2 ) + : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); +} + +Q_EXPORT inline int qstrncmp( const char *str1, const char *str2, uint len ) +{ + return ( str1 && str2 ) ? strncmp( str1, str2, len ) + : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); +} + +Q_EXPORT int qstricmp( const char *, const char * ); + +Q_EXPORT int qstrnicmp( const char *, const char *, uint len ); + +#ifndef QT_CLEAN_NAMESPACE +Q_EXPORT inline uint cstrlen( const char *str ) +{ return (uint)strlen(str); } + +Q_EXPORT inline char *cstrcpy( char *dst, const char *src ) +{ return strcpy(dst,src); } + +Q_EXPORT inline int cstrcmp( const char *str1, const char *str2 ) +{ return strcmp(str1,str2); } + +Q_EXPORT inline int cstrncmp( const char *str1, const char *str2, uint len ) +{ return strncmp(str1,str2,len); } +#endif + + +// qChecksum: Internet checksum + +Q_EXPORT Q_UINT16 qChecksum( const char *s, uint len ); + +/***************************************************************************** + QByteArray class + *****************************************************************************/ + +#if defined(Q_TEMPLATEDLL) +Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<char>; +#endif + +#if defined(Q_QDOC) +/* + We want qdoc to document QByteArray as a real class that inherits + QMemArray<char> and that is inherited by QBitArray. +*/ +class QByteArray : public QMemArray<char> +{ +public: + QByteArray(); + QByteArray( int size ); +}; +#else +typedef QMemArray<char> QByteArray; +#endif + +#ifndef QT_NO_COMPRESS +Q_EXPORT QByteArray qCompress( const uchar* data, int nbytes ); +Q_EXPORT QByteArray qUncompress( const uchar* data, int nbytes ); +Q_EXPORT inline QByteArray qCompress( const QByteArray& data) +{ return qCompress( (const uchar*)data.data(), data.size() ); } +Q_EXPORT inline QByteArray qUncompress( const QByteArray& data ) +{ return qUncompress( (const uchar*)data.data(), data.size() ); } +#endif + +/***************************************************************************** + QByteArray stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QByteArray & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QByteArray & ); +#endif + +/***************************************************************************** + QCString class + *****************************************************************************/ + +class QRegExp; + +class Q_EXPORT QCString : public QByteArray // C string class +{ +public: + QCString() {} // make null string + QCString( int size ); // allocate size incl. \0 + QCString( const QCString &s ) : QByteArray( s ) {} + QCString( const char *str ); // deep copy + QCString( const char *str, uint maxlen ); // deep copy, max length + ~QCString(); + + QCString &operator=( const QCString &s );// shallow copy + QCString &operator=( const char *str ); // deep copy + + bool isNull() const; + bool isEmpty() const; + uint length() const; + bool resize( uint newlen ); + bool truncate( uint pos ); + bool fill( char c, int len = -1 ); + + QCString copy() const; + + QCString &sprintf( const char *format, ... ); + + int find( char c, int index=0, bool cs=TRUE ) const; + int find( const char *str, int index=0, bool cs=TRUE ) const; +#ifndef QT_NO_REGEXP + int find( const QRegExp &, int index=0 ) const; +#endif + int findRev( char c, int index=-1, bool cs=TRUE) const; + int findRev( const char *str, int index=-1, bool cs=TRUE) const; +#ifndef QT_NO_REGEXP_CAPTURE + int findRev( const QRegExp &, int index=-1 ) const; +#endif + int contains( char c, bool cs=TRUE ) const; + int contains( const char *str, bool cs=TRUE ) const; +#ifndef QT_NO_REGEXP + int contains( const QRegExp & ) const; +#endif + QCString left( uint len ) const; + QCString right( uint len ) const; + QCString mid( uint index, uint len=0xffffffff) const; + + QCString leftJustify( uint width, char fill=' ', bool trunc=FALSE)const; + QCString rightJustify( uint width, char fill=' ',bool trunc=FALSE)const; + + QCString lower() const; + QCString upper() const; + + QCString stripWhiteSpace() const; + QCString simplifyWhiteSpace() const; + + QCString &insert( uint index, const char * ); + QCString &insert( uint index, char ); + QCString &append( const char * ); + QCString &prepend( const char * ); + QCString &remove( uint index, uint len ); + QCString &replace( uint index, uint len, const char * ); +#ifndef QT_NO_REGEXP + QCString &replace( const QRegExp &, const char * ); +#endif + QCString &replace( char c, const char *after ); + QCString &replace( const char *, const char * ); + QCString &replace( char, char ); + + short toShort( bool *ok=0 ) const; + ushort toUShort( bool *ok=0 ) const; + int toInt( bool *ok=0 ) const; + uint toUInt( bool *ok=0 ) const; + long toLong( bool *ok=0 ) const; + ulong toULong( bool *ok=0 ) const; + float toFloat( bool *ok=0 ) const; + double toDouble( bool *ok=0 ) const; + + QCString &setStr( const char *s ); + QCString &setNum( short ); + QCString &setNum( ushort ); + QCString &setNum( int ); + QCString &setNum( uint ); + QCString &setNum( long ); + QCString &setNum( ulong ); + QCString &setNum( float, char f='g', int prec=6 ); + QCString &setNum( double, char f='g', int prec=6 ); + + bool setExpand( uint index, char c ); + + operator const char *() const; + QCString &operator+=( const char *str ); + QCString &operator+=( char c ); +}; + + +/***************************************************************************** + QCString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QCString & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QCString & ); +#endif + +/***************************************************************************** + QCString inline functions + *****************************************************************************/ + +inline QCString &QCString::operator=( const QCString &s ) +{ return (QCString&)assign( s ); } + +inline QCString &QCString::operator=( const char *str ) +{ return (QCString&)duplicate( str, qstrlen(str)+1 ); } + +inline bool QCString::isNull() const +{ return data() == 0; } + +inline bool QCString::isEmpty() const +{ return data() == 0 || *data() == '\0'; } + +inline uint QCString::length() const +{ return qstrlen( data() ); } + +inline bool QCString::truncate( uint pos ) +{ return resize(pos+1); } + +inline QCString QCString::copy() const +{ return QCString( data() ); } + +inline QCString &QCString::prepend( const char *s ) +{ return insert(0,s); } + +inline QCString &QCString::append( const char *s ) +{ return operator+=(s); } + +inline QCString &QCString::setNum( short n ) +{ return setNum((long)n); } + +inline QCString &QCString::setNum( ushort n ) +{ return setNum((ulong)n); } + +inline QCString &QCString::setNum( int n ) +{ return setNum((long)n); } + +inline QCString &QCString::setNum( uint n ) +{ return setNum((ulong)n); } + +inline QCString &QCString::setNum( float n, char f, int prec ) +{ return setNum((double)n,f,prec); } + +inline QCString::operator const char *() const +{ return (const char *)data(); } + + +/***************************************************************************** + QCString non-member operators + *****************************************************************************/ + +Q_EXPORT inline bool operator==( const QCString &s1, const QCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) == 0; } + +Q_EXPORT inline bool operator==( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) == 0; } + +Q_EXPORT inline bool operator==( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) == 0; } + +Q_EXPORT inline bool operator!=( const QCString &s1, const QCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) != 0; } + +Q_EXPORT inline bool operator!=( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) != 0; } + +Q_EXPORT inline bool operator!=( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) != 0; } + +Q_EXPORT inline bool operator<( const QCString &s1, const QCString& s2 ) +{ return qstrcmp( s1.data(), s2.data() ) < 0; } + +Q_EXPORT inline bool operator<( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) < 0; } + +Q_EXPORT inline bool operator<( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) < 0; } + +Q_EXPORT inline bool operator<=( const QCString &s1, const QCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) <= 0; } + +Q_EXPORT inline bool operator<=( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) <= 0; } + +Q_EXPORT inline bool operator<=( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) <= 0; } + +Q_EXPORT inline bool operator>( const QCString &s1, const QCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) > 0; } + +Q_EXPORT inline bool operator>( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) > 0; } + +Q_EXPORT inline bool operator>( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) > 0; } + +Q_EXPORT inline bool operator>=( const QCString &s1, const QCString& s2 ) +{ return qstrcmp( s1.data(), s2.data() ) >= 0; } + +Q_EXPORT inline bool operator>=( const QCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) >= 0; } + +Q_EXPORT inline bool operator>=( const char *s1, const QCString &s2 ) +{ return qstrcmp( s1, s2.data() ) >= 0; } + +Q_EXPORT inline const QCString operator+( const QCString &s1, + const QCString &s2 ) +{ + QCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline const QCString operator+( const QCString &s1, const char *s2 ) +{ + QCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline const QCString operator+( const char *s1, const QCString &s2 ) +{ + QCString tmp( s1 ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline const QCString operator+( const QCString &s1, char c2 ) +{ + QCString tmp( s1.data() ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline const QCString operator+( char c1, const QCString &s2 ) +{ + QCString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +#endif // QCSTRING_H diff --git a/qmake/include/qdatastream.h b/qmake/include/qdatastream.h new file mode 100644 index 0000000..09d7bef --- a/dev/null +++ b/qmake/include/qdatastream.h @@ -0,0 +1,173 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QDataStream class +** +** Created : 930831 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QDATASTREAM_H +#define QDATASTREAM_H + +#ifndef QT_H +#include "qiodevice.h" +#include "qstring.h" +#endif // QT_H + +#ifndef QT_NO_DATASTREAM +class Q_EXPORT QDataStream // data stream class +{ +public: + QDataStream(); + QDataStream( QIODevice * ); + QDataStream( QByteArray, int mode ); + virtual ~QDataStream(); + + QIODevice *device() const; + void setDevice( QIODevice * ); + void unsetDevice(); + + bool atEnd() const; + bool eof() const; + + enum ByteOrder { BigEndian, LittleEndian }; + int byteOrder() const; + void setByteOrder( int ); + + bool isPrintableData() const; + void setPrintableData( bool ); + + int version() const; + void setVersion( int ); + + QDataStream &operator>>( Q_INT8 &i ); + QDataStream &operator>>( Q_UINT8 &i ); + QDataStream &operator>>( Q_INT16 &i ); + QDataStream &operator>>( Q_UINT16 &i ); + QDataStream &operator>>( Q_INT32 &i ); + QDataStream &operator>>( Q_UINT32 &i ); + QDataStream &operator>>( Q_LONG &i ); + QDataStream &operator>>( Q_ULONG &i ); + + QDataStream &operator>>( float &f ); + QDataStream &operator>>( double &f ); + QDataStream &operator>>( char *&str ); + + QDataStream &operator<<( Q_INT8 i ); + QDataStream &operator<<( Q_UINT8 i ); + QDataStream &operator<<( Q_INT16 i ); + QDataStream &operator<<( Q_UINT16 i ); + QDataStream &operator<<( Q_INT32 i ); + QDataStream &operator<<( Q_UINT32 i ); + QDataStream &operator<<( Q_LONG i ); + QDataStream &operator<<( Q_ULONG i ); + QDataStream &operator<<( float f ); + QDataStream &operator<<( double f ); + QDataStream &operator<<( const char *str ); + + QDataStream &readBytes( char *&, uint &len ); + QDataStream &readRawBytes( char *, uint len ); + + QDataStream &writeBytes( const char *, uint len ); + QDataStream &writeRawBytes( const char *, uint len ); + +private: + QIODevice *dev; + bool owndev; + int byteorder; + bool printable; + bool noswap; + int ver; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QDataStream( const QDataStream & ); + QDataStream &operator=( const QDataStream & ); +#endif +}; + + +/***************************************************************************** + QDataStream inline functions + *****************************************************************************/ + +inline QIODevice *QDataStream::device() const +{ return dev; } + +inline bool QDataStream::atEnd() const +{ return dev ? dev->atEnd() : TRUE; } + +inline bool QDataStream::eof() const +{ return atEnd(); } + +inline int QDataStream::byteOrder() const +{ return byteorder; } + +inline bool QDataStream::isPrintableData() const +{ return printable; } + +inline void QDataStream::setPrintableData( bool p ) +{ printable = p; } + +inline int QDataStream::version() const +{ return ver; } + +inline void QDataStream::setVersion( int v ) +{ ver = v; } + +inline QDataStream &QDataStream::operator>>( Q_UINT8 &i ) +{ return *this >> (Q_INT8&)i; } + +inline QDataStream &QDataStream::operator>>( Q_UINT16 &i ) +{ return *this >> (Q_INT16&)i; } + +inline QDataStream &QDataStream::operator>>( Q_UINT32 &i ) +{ return *this >> (Q_INT32&)i; } + +inline QDataStream &QDataStream::operator>>( Q_ULONG &i ) +{ return *this >> (Q_LONG&)i; } + +inline QDataStream &QDataStream::operator<<( Q_UINT8 i ) +{ return *this << (Q_INT8)i; } + +inline QDataStream &QDataStream::operator<<( Q_UINT16 i ) +{ return *this << (Q_INT16)i; } + +inline QDataStream &QDataStream::operator<<( Q_UINT32 i ) +{ return *this << (Q_INT32)i; } + +inline QDataStream &QDataStream::operator<<( Q_ULONG i ) +{ return *this << (Q_LONG)i; } + + +#endif // QT_NO_DATASTREAM +#endif // QDATASTREAM_H diff --git a/qmake/include/qdatetime.h b/qmake/include/qdatetime.h new file mode 100644 index 0000000..4f01760 --- a/dev/null +++ b/qmake/include/qdatetime.h @@ -0,0 +1,250 @@ +/************************************************************************* +** $Id$ +** +** Definition of date and time classes +** +** Created : 940124 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QDATETIME_H +#define QDATETIME_H + +#ifndef QT_H +#include "qstring.h" +#include "qnamespace.h" +#endif // QT_H + + +/***************************************************************************** + QDate class + *****************************************************************************/ + +class Q_EXPORT QDate +{ +public: + QDate() { jd = 0; } + QDate( int y, int m, int d ); + + bool isNull() const { return jd == 0; } + bool isValid() const; + + int year() const; + int month() const; + int day() const; + int dayOfWeek() const; + int dayOfYear() const; + int daysInMonth() const; + int daysInYear() const; + int weekNumber( int *yearNum = 0 ) const; + +#ifndef QT_NO_TEXTDATE +#ifndef QT_NO_COMPAT + static QString monthName( int month ) { return shortMonthName( month ); } + static QString dayName( int weekday ) { return shortDayName( weekday ); } +#endif + static QString shortMonthName( int month ); + static QString shortDayName( int weekday ); + static QString longMonthName( int month ); + static QString longDayName( int weekday ); +#endif //QT_NO_TEXTDATE +#ifndef QT_NO_TEXTSTRING +#if !defined(QT_NO_SPRINTF) + QString toString( Qt::DateFormat f = Qt::TextDate ) const; +#endif + QString toString( const QString& format ) const; +#endif + bool setYMD( int y, int m, int d ); + + QDate addDays( int days ) const; + QDate addMonths( int months ) const; + QDate addYears( int years ) const; + int daysTo( const QDate & ) const; + + bool operator==( const QDate &d ) const { return jd == d.jd; } + bool operator!=( const QDate &d ) const { return jd != d.jd; } + bool operator<( const QDate &d ) const { return jd < d.jd; } + bool operator<=( const QDate &d ) const { return jd <= d.jd; } + bool operator>( const QDate &d ) const { return jd > d.jd; } + bool operator>=( const QDate &d ) const { return jd >= d.jd; } + + static QDate currentDate(); + static QDate currentDate( Qt::TimeSpec ); +#ifndef QT_NO_DATESTRING + static QDate fromString( const QString& s, Qt::DateFormat f = Qt::TextDate ); +#endif + static bool isValid( int y, int m, int d ); + static bool leapYear( int year ); + + static uint gregorianToJulian( int y, int m, int d ); + static void julianToGregorian( uint jd, int &y, int &m, int &d ); +private: + uint jd; + friend class QDateTime; +#ifndef QT_NO_DATASTREAM + friend Q_EXPORT QDataStream &operator<<( QDataStream &, const QDate & ); + friend Q_EXPORT QDataStream &operator>>( QDataStream &, QDate & ); +#endif +}; + + +/***************************************************************************** + QTime class + *****************************************************************************/ + +class Q_EXPORT QTime +{ +public: + QTime() { ds=0; } // set null time + QTime( int h, int m, int s=0, int ms=0 ); // set time + + bool isNull() const { return ds == 0; } + bool isValid() const; // valid time + + int hour() const; // 0..23 + int minute() const; // 0..59 + int second() const; // 0..59 + int msec() const; // 0..999 +#ifndef QT_NO_DATESTRING +#ifndef QT_NO_SPRINTF + QString toString( Qt::DateFormat f = Qt::TextDate ) const; +#endif + QString toString( const QString& format ) const; +#endif + bool setHMS( int h, int m, int s, int ms=0 ); + + QTime addSecs( int secs ) const; + int secsTo( const QTime & ) const; + QTime addMSecs( int ms ) const; + int msecsTo( const QTime & ) const; + + bool operator==( const QTime &d ) const { return ds == d.ds; } + bool operator!=( const QTime &d ) const { return ds != d.ds; } + bool operator<( const QTime &d ) const { return ds < d.ds; } + bool operator<=( const QTime &d ) const { return ds <= d.ds; } + bool operator>( const QTime &d ) const { return ds > d.ds; } + bool operator>=( const QTime &d ) const { return ds >= d.ds; } + + static QTime currentTime(); + static QTime currentTime( Qt::TimeSpec ); +#ifndef QT_NO_DATESTRING + static QTime fromString( const QString& s, Qt::DateFormat f = Qt::TextDate ); +#endif + static bool isValid( int h, int m, int s, int ms=0 ); + + void start(); + int restart(); + int elapsed() const; + +private: + static bool currentTime( QTime * ); + static bool currentTime( QTime *, Qt::TimeSpec ); + + uint ds; + friend class QDateTime; +#ifndef QT_NO_DATASTREAM + friend Q_EXPORT QDataStream &operator<<( QDataStream &, const QTime & ); + friend Q_EXPORT QDataStream &operator>>( QDataStream &, QTime & ); +#endif +}; + + +/***************************************************************************** + QDateTime class + *****************************************************************************/ + +class Q_EXPORT QDateTime +{ +public: + QDateTime() {} // set null date and null time + QDateTime( const QDate & ); + QDateTime( const QDate &, const QTime & ); + + bool isNull() const { return d.isNull() && t.isNull(); } + bool isValid() const { return d.isValid() && t.isValid(); } + + QDate date() const { return d; } + QTime time() const { return t; } + uint toTime_t() const; + void setDate( const QDate &date ) { d = date; } + void setTime( const QTime &time ) { t = time; } + void setTime_t( uint secsSince1Jan1970UTC ); + void setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec ); +#ifndef QT_NO_DATESTRING +#ifndef QT_NO_SPRINTF + QString toString( Qt::DateFormat f = Qt::TextDate ) const; +#endif + QString toString( const QString& format ) const; +#endif + QDateTime addDays( int days ) const; + QDateTime addMonths( int months ) const; + QDateTime addYears( int years ) const; + QDateTime addSecs( int secs ) const; + int daysTo( const QDateTime & ) const; + int secsTo( const QDateTime & ) const; + + bool operator==( const QDateTime &dt ) const; + bool operator!=( const QDateTime &dt ) const; + bool operator<( const QDateTime &dt ) const; + bool operator<=( const QDateTime &dt ) const; + bool operator>( const QDateTime &dt ) const; + bool operator>=( const QDateTime &dt ) const; + + static QDateTime currentDateTime(); + static QDateTime currentDateTime( Qt::TimeSpec ); +#ifndef QT_NO_DATESTRING + static QDateTime fromString( const QString& s, Qt::DateFormat f = Qt::TextDate ); +#endif +private: + QDate d; + QTime t; +#ifndef QT_NO_DATASTREAM + friend Q_EXPORT QDataStream &operator<<( QDataStream &, const QDateTime &); + friend Q_EXPORT QDataStream &operator>>( QDataStream &, QDateTime & ); +#endif +}; + + +/***************************************************************************** + Date and time stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QDate & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QDate & ); +Q_EXPORT QDataStream &operator<<( QDataStream &, const QTime & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QTime & ); +Q_EXPORT QDataStream &operator<<( QDataStream &, const QDateTime & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QDateTime & ); +#endif // QT_NO_DATASTREAM + +#endif // QDATETIME_H + diff --git a/qmake/include/qdict.h b/qmake/include/qdict.h new file mode 100644 index 0000000..04ae7bf --- a/dev/null +++ b/qmake/include/qdict.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QDict template class +** +** Created : 920821 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QDICT_H +#define QDICT_H + +#ifndef QT_H +#include "qgdict.h" +#endif // QT_H + +template<class type> +class QDict +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGDict +#endif +{ +public: + QDict( int size = 17, bool caseSensitive = TRUE ) + : QGDict( size, StringKey, caseSensitive, FALSE ) { } + QDict( const QDict<type> &d ) : QGDict( d ) { } + ~QDict() { clear(); } + QDict<type> &operator=(const QDict<type> &d) + { return (QDict<type>&)QGDict::operator=(d); } + uint count() const { return QGDict::count(); } + uint size() const { return QGDict::size(); } + bool isEmpty() const { return QGDict::count() == 0; } + + void insert( const QString &k, const type *d ) + { QGDict::look_string(k,(Item)d,1); } + void replace( const QString &k, const type *d ) + { QGDict::look_string(k,(Item)d,2); } + bool remove( const QString &k ) { return QGDict::remove_string(k); } + type *take( const QString &k ) { return (type *)QGDict::take_string(k); } + type *find( const QString &k ) const + { return (type *)((QGDict*)this)->QGDict::look_string(k,0,0); } + type *operator[]( const QString &k ) const + { return (type *)((QGDict*)this)->QGDict::look_string(k,0,0); } + + void clear() { QGDict::clear(); } + void resize( uint n ) { QGDict::resize(n); } + void statistics() const { QGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); + virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QDict<void>::deleteItem( Item ) +{ +} +#endif + +template<class type> inline void QDict<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template<class type> +class QDictIterator : public QGDictIterator +{ +public: + QDictIterator(const QDict<type> &d) : QGDictIterator((QGDict &)d) { } + ~QDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)QGDictIterator::toFirst(); } + operator type *() const { return (type *)QGDictIterator::get(); } + type *operator*() { return (type *)QGDictIterator::get(); } + type *current() const { return (type *)QGDictIterator::get(); } + QString currentKey() const{ return QGDictIterator::getKeyString(); } + type *operator()() { return (type *)QGDictIterator::operator()(); } + type *operator++() { return (type *)QGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j); } +}; + +#endif // QDICT_H diff --git a/qmake/include/qdir.h b/qmake/include/qdir.h new file mode 100644 index 0000000..6e9f1ab --- a/dev/null +++ b/qmake/include/qdir.h @@ -0,0 +1,241 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QDir class +** +** Created : 950427 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QDIR_H +#define QDIR_H + +#ifndef QT_H +#include "qglobal.h" +#include "qstrlist.h" +#include "qfileinfo.h" +#endif // QT_H + + +#ifndef QT_NO_DIR +typedef QPtrList<QFileInfo> QFileInfoList; +typedef QPtrListIterator<QFileInfo> QFileInfoListIterator; +class QStringList; + + +class Q_EXPORT QDir +{ +public: + enum FilterSpec { Dirs = 0x001, + Files = 0x002, + Drives = 0x004, + NoSymLinks = 0x008, + All = 0x007, + TypeMask = 0x00F, + + Readable = 0x010, + Writable = 0x020, + Executable = 0x040, + RWEMask = 0x070, + + Modified = 0x080, + Hidden = 0x100, + System = 0x200, + AccessMask = 0x3F0, + + DefaultFilter = -1 }; + + enum SortSpec { Name = 0x00, + Time = 0x01, + Size = 0x02, + Unsorted = 0x03, + SortByMask = 0x03, + + DirsFirst = 0x04, + Reversed = 0x08, + IgnoreCase = 0x10, + DefaultSort = -1 }; + + QDir(); + QDir( const QString &path, const QString &nameFilter = QString::null, + int sortSpec = Name | IgnoreCase, int filterSpec = All ); + QDir( const QDir & ); + + virtual ~QDir(); + + QDir &operator=( const QDir & ); + QDir &operator=( const QString &path ); + + virtual void setPath( const QString &path ); + virtual QString path() const; + virtual QString absPath() const; + virtual QString canonicalPath() const; + + virtual QString dirName() const; + virtual QString filePath( const QString &fileName, + bool acceptAbsPath = TRUE ) const; + virtual QString absFilePath( const QString &fileName, + bool acceptAbsPath = TRUE ) const; + + static QString convertSeparators( const QString &pathName ); + + virtual bool cd( const QString &dirName, bool acceptAbsPath = TRUE ); + virtual bool cdUp(); + + QString nameFilter() const; + virtual void setNameFilter( const QString &nameFilter ); + FilterSpec filter() const; + virtual void setFilter( int filterSpec ); + SortSpec sorting() const; + virtual void setSorting( int sortSpec ); + + bool matchAllDirs() const; + virtual void setMatchAllDirs( bool ); + + uint count() const; + QString operator[]( int ) const; + + virtual QStrList encodedEntryList( int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + virtual QStrList encodedEntryList( const QString &nameFilter, + int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + virtual QStringList entryList( int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + virtual QStringList entryList( const QString &nameFilter, + int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + + virtual const QFileInfoList *entryInfoList( int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + virtual const QFileInfoList *entryInfoList( const QString &nameFilter, + int filterSpec = DefaultFilter, + int sortSpec = DefaultSort ) const; + + static const QFileInfoList *drives(); + + virtual bool mkdir( const QString &dirName, + bool acceptAbsPath = TRUE ) const; + virtual bool rmdir( const QString &dirName, + bool acceptAbsPath = TRUE ) const; + + virtual bool isReadable() const; + virtual bool exists() const; + virtual bool isRoot() const; + + virtual bool isRelative() const; + virtual void convertToAbs(); + + virtual bool operator==( const QDir & ) const; + virtual bool operator!=( const QDir & ) const; + + virtual bool remove( const QString &fileName, + bool acceptAbsPath = TRUE ); + virtual bool rename( const QString &name, const QString &newName, + bool acceptAbsPaths = TRUE ); + virtual bool exists( const QString &name, + bool acceptAbsPath = TRUE ); + + static char separator(); + + static bool setCurrent( const QString &path ); + static QDir current(); + static QDir home(); + static QDir root(); + static QString currentDirPath(); + static QString homeDirPath(); + static QString rootDirPath(); + + static bool match( const QStringList &filters, const QString &fileName ); + static bool match( const QString &filter, const QString &fileName ); + static QString cleanDirPath( const QString &dirPath ); + static bool isRelativePath( const QString &path ); + +private: +#ifdef Q_OS_MAC + typedef struct FSSpec FSSpec; + static FSSpec *make_spec(const QString &); +#endif + void init(); + virtual bool readDirEntries( const QString &nameFilter, + int FilterSpec, int SortSpec ); + + static void slashify ( QString &); + + QString dPath; + QStringList *fList; + QFileInfoList *fiList; + QString nameFilt; + FilterSpec filtS; + SortSpec sortS; + uint dirty : 1; + uint allDirs : 1; +}; + + +inline QString QDir::path() const +{ + return dPath; +} + +inline QString QDir::nameFilter() const +{ + return nameFilt; +} + +inline QDir::FilterSpec QDir::filter() const +{ + return filtS; +} + +inline QDir::SortSpec QDir::sorting() const +{ + return sortS; +} + +inline bool QDir::matchAllDirs() const +{ + return allDirs; +} + +inline bool QDir::operator!=( const QDir &d ) const +{ + return !(*this == d); +} + + +struct QDirSortItem { + QString filename_cache; + QFileInfo* item; +}; + +#endif // QT_NO_DIR +#endif // QDIR_H diff --git a/qmake/include/qfeatures.h b/qmake/include/qfeatures.h new file mode 100644 index 0000000..57502f9 --- a/dev/null +++ b/qmake/include/qfeatures.h @@ -0,0 +1,959 @@ +// All feature and their dependencies +// +// This list is generated from $QTDIR/src/tools/qfeatures.txt +// +// Asynchronous I/O +//#define QT_NO_ASYNC_IO + +// Bezier curves +//#define QT_NO_BEZIER + +// Buttons +//#define QT_NO_BUTTON + +// Named colors +//#define QT_NO_COLORNAMES + +// Cursors +//#define QT_NO_CURSOR + +// QDataStream +//#define QT_NO_DATASTREAM + +// QDate/QTime/QDateTime toString() and fromString() +//#define QT_NO_DATESTRING + +// Dialogs +//#define QT_NO_DIALOG + +// QDirectPainter +//#define QT_NO_DIRECTPAINTER + +// Special widget effects (fading, scrolling) +//#define QT_NO_EFFECTS + +// Freetype font engine +//#define QT_NO_FREETYPE + +// Dither QImage to 1-bit image +//#define QT_NO_IMAGE_DITHER_TO_1 + +// QImage::createHeuristicMask() +//#define QT_NO_IMAGE_HEURISTIC_MASK + +// QImage mirroring +//#define QT_NO_IMAGE_MIRROR + +// Smooth QImage scaling +//#define QT_NO_IMAGE_SMOOTHSCALE + +// TrueColor QImage +//#define QT_NO_IMAGE_TRUECOLOR + +// Automatic widget layout +//#define QT_NO_LAYOUT + +// Networking +//#define QT_NO_NETWORK + +// Palettes +//#define QT_NO_PALETTE + +// Alpha-blended cursor +//#define QT_NO_QWS_ALPHA_CURSOR + +// 1-bit monochrome +//#define QT_NO_QWS_DEPTH_1 + +// 15 or 16-bit color +//#define QT_NO_QWS_DEPTH_16 + +// 24-bit color +//#define QT_NO_QWS_DEPTH_24 + +// 32-bit color +//#define QT_NO_QWS_DEPTH_32 + +// 4-bit greyscale +//#define QT_NO_QWS_DEPTH_4 + +// 8-bit color +//#define QT_NO_QWS_DEPTH_8 + +// 8-bit grayscale +//#define QT_NO_QWS_DEPTH_8GRAYSCALE + +// Favour code size over graphics speed +//#define QT_NO_QWS_GFX_SPEED + +// Console keyboard +//#define QT_NO_QWS_KEYBOARD + +// Linux framebuffer +//#define QT_NO_QWS_LINUXFB + +// Mach64 acceleration +//#define QT_NO_QWS_MACH64 + +// Window Manager +//#define QT_NO_QWS_MANAGER + +// Matrox MGA acceleration +//#define QT_NO_QWS_MATROX + +// Autodetecting mouse driver +//#define QT_NO_QWS_MOUSE_AUTO + +// Non-autodetecting mouse driver +//#define QT_NO_QWS_MOUSE_MANUAL + +// Qt/Embedded window system properties. +//#define QT_NO_QWS_PROPERTIES + +// Repeater display +//#define QT_NO_QWS_REPEATER + +// Saving of fonts +//#define QT_NO_QWS_SAVEFONTS + +// Shadow frame buffer +//#define QT_NO_QWS_SHADOWFB + +// Virtual frame buffer +//#define QT_NO_QWS_VFB + +// 4-bit VGA +//#define QT_NO_QWS_VGA_16 + +// Voodoo3 acceleration +//#define QT_NO_QWS_VOODOO3 + +// Range-control widgets +//#define QT_NO_RANGECONTROL + +// Regular expression capture +//#define QT_NO_REGEXP + +// QSignalMapper +//#define QT_NO_SIGNALMAPPER + +// Playing sounds +//#define QT_NO_SOUND + +// Standard template library compatiblity +//#define QT_NO_STL + +// QStringList +//#define QT_NO_STRINGLIST + +// Character set conversions +//#define QT_NO_TEXTCODEC + +// QTextStream +//#define QT_NO_TEXTSTREAM + +// Unicode property tables +//#define QT_NO_UNICODETABLES + +// Input validators +//#define QT_NO_VALIDATOR + +// QVariant +//#define QT_NO_VARIANT + +// Wheel-mouse events +//#define QT_NO_WHEELEVENT + +// QWMatrix +//#define QT_NO_WMATRIX + +// Non-Unicode text conversions +#if !defined(QT_NO_CODECS) && (defined(QT_NO_TEXTCODEC)) +#define QT_NO_CODECS +#endif + +// QCop IPC +#if !defined(QT_NO_COP) && (defined(QT_NO_DATASTREAM)) +#define QT_NO_COP +#endif + +// QFontDatabase +#if !defined(QT_NO_FONTDATABASE) && (defined(QT_NO_STRINGLIST)) +#define QT_NO_FONTDATABASE +#endif + +// Image formats +#if !defined(QT_NO_IMAGEIO) && (defined(QT_NO_REGEXP)) +#define QT_NO_IMAGEIO +#endif + +// 16-bit QImage +#if !defined(QT_NO_IMAGE_16_BIT) && (defined(QT_NO_IMAGE_TRUECOLOR)) +#define QT_NO_IMAGE_16_BIT +#endif + +// Image file text strings +#if !defined(QT_NO_IMAGE_TEXT) && (defined(QT_NO_STRINGLIST)) +#define QT_NO_IMAGE_TEXT +#endif + +// Shared library wrapper +#if !defined(QT_NO_LIBRARY) && (defined(QT_NO_REGEXP)) +#define QT_NO_LIBRARY +#endif + +// Pixmap transformations +#if !defined(QT_NO_PIXMAP_TRANSFORMATION) && (defined(QT_NO_WMATRIX)) +#define QT_NO_PIXMAP_TRANSFORMATION +#endif + +// Convert UUID to/from string +#if !defined(QT_NO_QUUID_STRING) && (defined(QT_NO_STRINGLIST)) +#define QT_NO_QUUID_STRING +#endif + +// The "BeOS" style +#if !defined(QT_NO_QWS_BEOS_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) +#define QT_NO_QWS_BEOS_WM_STYLE +#endif + +// Visible cursor +#if !defined(QT_NO_QWS_CURSOR) && (defined(QT_NO_CURSOR)) +#define QT_NO_QWS_CURSOR +#endif + +// 32-bit color, BGR order +#if !defined(QT_NO_QWS_DEPTH_32_BGR) && (defined(QT_NO_QWS_DEPTH_32)) +#define QT_NO_QWS_DEPTH_32_BGR +#endif + +// The "Hydro" style +#if !defined(QT_NO_QWS_HYDRO_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) +#define QT_NO_QWS_HYDRO_WM_STYLE +#endif + +// The "KDE2" style +#if !defined(QT_NO_QWS_KDE2_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) +#define QT_NO_QWS_KDE2_WM_STYLE +#endif + +// The "KDE" style +#if !defined(QT_NO_QWS_KDE_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) +#define QT_NO_QWS_KDE_WM_STYLE +#endif + +// Multi-process architecture +#if !defined(QT_NO_QWS_MULTIPROCESS) && (defined(QT_NO_NETWORK)) +#define QT_NO_QWS_MULTIPROCESS +#endif + +// Transformed frame buffer +#if !defined(QT_NO_QWS_TRANSFORMED) && (defined(QT_NO_QWS_LINUXFB)) +#define QT_NO_QWS_TRANSFORMED +#endif + +// Remote frame buffer (VNC) +#if !defined(QT_NO_QWS_VNC) && (defined(QT_NO_NETWORK)) +#define QT_NO_QWS_VNC +#endif + +// The "Windows" style +#if !defined(QT_NO_QWS_WINDOWS_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) +#define QT_NO_QWS_WINDOWS_WM_STYLE +#endif + +// Regular expression anchors +#if !defined(QT_NO_REGEXP_ANCHOR_ALT) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_ANCHOR_ALT +#endif + +// Regular expression back-reference +#if !defined(QT_NO_REGEXP_BACKREF) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_BACKREF +#endif + +// Regular expression character-class +#if !defined(QT_NO_REGEXP_CCLASS) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_CCLASS +#endif + +// Regular expression escape +#if !defined(QT_NO_REGEXP_ESCAPE) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_ESCAPE +#endif + +// Regular expression interval +#if !defined(QT_NO_REGEXP_INTERVAL) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_INTERVAL +#endif + +// Regular expression lookahead +#if !defined(QT_NO_REGEXP_LOOKAHEAD) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_LOOKAHEAD +#endif + +// Regular expression optimization +#if !defined(QT_NO_REGEXP_OPTIM) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_OPTIM +#endif + +// Regular expression wildcard +#if !defined(QT_NO_REGEXP_WILDCARD) && (defined(QT_NO_REGEXP)) +#define QT_NO_REGEXP_WILDCARD +#endif + +// Semi-modal dialogs +#if !defined(QT_NO_SEMIMODAL) && (defined(QT_NO_DIALOG)) +#define QT_NO_SEMIMODAL +#endif + +// Session management +#if !defined(QT_NO_SESSIONMANAGER) && (defined(QT_NO_STRINGLIST)) +#define QT_NO_SESSIONMANAGER +#endif + +// QString::sprintf() +#if !defined(QT_NO_SPRINTF) && (defined(QT_NO_REGEXP)) +#define QT_NO_SPRINTF +#endif + +// Scaling and rotation +#if !defined(QT_NO_TRANSFORMATIONS) && (defined(QT_NO_WMATRIX)) +#define QT_NO_TRANSFORMATIONS +#endif + +// Translations via QObject::tr() +#if !defined(QT_NO_TRANSLATION) && (defined(QT_NO_DATASTREAM)) +#define QT_NO_TRANSLATION +#endif + +// Window icon and caption +#if !defined(QT_NO_WIDGET_TOPEXTRA) && (defined(QT_NO_IMAGE_HEURISTIC_MASK)) +#define QT_NO_WIDGET_TOPEXTRA +#endif + +// Keyboard accelerators and shortcuts +#if !defined(QT_NO_ACCEL) && (defined(QT_NO_SPRINTF)) +#define QT_NO_ACCEL +#endif + +// Asynchronous image I/O +#if !defined(QT_NO_ASYNC_IMAGE_IO) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_ASYNC_IMAGE_IO +#endif + +// BDF font files +#if !defined(QT_NO_BDF) && (defined(QT_NO_TEXTSTREAM) || defined(QT_NO_STRINGLIST)) +#define QT_NO_BDF +#endif + +// QDir +#if !defined(QT_NO_DIR) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_REGEXP)) +#define QT_NO_DIR +#endif + +// JPEG image I/O +#if !defined(QT_NO_IMAGEIO_JPEG) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEIO_JPEG +#endif + +// MNG image I/O +#if !defined(QT_NO_IMAGEIO_MNG) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEIO_MNG +#endif + +// PNG image I/O +#if !defined(QT_NO_IMAGEIO_PNG) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEIO_PNG +#endif + +// PPM image I/O +#if !defined(QT_NO_IMAGEIO_PPM) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEIO_PPM +#endif + +// XBM image I/O +#if !defined(QT_NO_IMAGEIO_XBM) && (defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEIO_XBM +#endif + +// Image transformations +#if !defined(QT_NO_IMAGE_TRANSFORMATION) && (defined(QT_NO_PIXMAP_TRANSFORMATION)) +#define QT_NO_IMAGE_TRANSFORMATION +#endif + +// External process invocation. +#if !defined(QT_NO_PROCESS) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_REGEXP)) +#define QT_NO_PROCESS +#endif + +// Regular expression capture +#if !defined(QT_NO_REGEXP_CAPTURE) && (defined(QT_NO_REGEXP) || defined(QT_NO_STRINGLIST)) +#define QT_NO_REGEXP_CAPTURE +#endif + +// Template classes in QVariant +#if !defined(QT_NO_TEMPLATE_VARIANT) && (defined(QT_NO_VARIANT) || defined(QT_NO_STRINGLIST)) +#define QT_NO_TEMPLATE_VARIANT +#endif + +// Month and day names in dates +#if !defined(QT_NO_TEXTDATE) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_DATESTRING)) +#define QT_NO_TEXTDATE +#endif + +// Drawing utility functions +#if !defined(QT_NO_DRAWUTIL) && (defined(QT_NO_SPRINTF) || defined(QT_NO_PALETTE)) +#define QT_NO_DRAWUTIL +#endif + +// BMP image I/O +#if !defined(QT_NO_IMAGEIO_BMP) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_DATASTREAM)) +#define QT_NO_IMAGEIO_BMP +#endif + +// QPicture +#if !defined(QT_NO_PICTURE) && (defined(QT_NO_DATASTREAM) || defined(QT_NO_IMAGEIO)) +#define QT_NO_PICTURE +#endif + +// Translations via QObject::trUtf8() +#if !defined(QT_NO_TRANSLATION_UTF8) && (defined(QT_NO_TRANSLATION) || defined(QT_NO_TEXTCODEC)) +#define QT_NO_TRANSLATION_UTF8 +#endif + +// URL parser +#if !defined(QT_NO_URL) && (defined(QT_NO_DIR)) +#define QT_NO_URL +#endif + +// Animated images +#if !defined(QT_NO_MOVIE) && (defined(QT_NO_ASYNC_IO) || defined(QT_NO_ASYNC_IMAGE_IO)) +#define QT_NO_MOVIE +#endif + +// Persistent application settings +#if !defined(QT_NO_SETTINGS) && (defined(QT_NO_DIR) || defined(QT_NO_TEXTSTREAM)) +#define QT_NO_SETTINGS +#endif + +// QStyle +#if !defined(QT_NO_STYLE) && (defined(QT_NO_DRAWUTIL)) +#define QT_NO_STYLE +#endif + +// DNS +#if !defined(QT_NO_DNS) && (defined(QT_NO_NETWORK) || defined(QT_NO_STRINGLIST) || defined(QT_NO_TEXTSTREAM) || defined(QT_NO_SPRINTF)) +#define QT_NO_DNS +#endif + +// Framed widgets +#if !defined(QT_NO_FRAME) && (defined(QT_NO_STYLE)) +#define QT_NO_FRAME +#endif + +// QIconSet +#if !defined(QT_NO_ICONSET) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_IMAGE_SMOOTHSCALE) || defined(QT_NO_PALETTE) || defined(QT_NO_IMAGE_HEURISTIC_MASK)) +#define QT_NO_ICONSET +#endif + +// XPM image I/O +#if !defined(QT_NO_IMAGEIO_XPM) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_SPRINTF) || defined(QT_NO_TEXTSTREAM)) +#define QT_NO_IMAGEIO_XPM +#endif + +// QSizeGrip +#if !defined(QT_NO_SIZEGRIP) && (defined(QT_NO_STYLE)) +#define QT_NO_SIZEGRIP +#endif + +// Motif style +#if !defined(QT_NO_STYLE_MOTIF) && (defined(QT_NO_STYLE)) +#define QT_NO_STYLE_MOTIF +#endif + +// Windows style +#if !defined(QT_NO_STYLE_WINDOWS) && (defined(QT_NO_STYLE)) +#define QT_NO_STYLE_WINDOWS +#endif + +// Internal titlebar widget +#if !defined(QT_NO_TITLEBAR) && (defined(QT_NO_STYLE)) +#define QT_NO_TITLEBAR +#endif + +// XML +#if !defined(QT_NO_XML) && (defined(QT_NO_TEXTSTREAM) || defined(QT_NO_TEXTCODEC) || defined(QT_NO_REGEXP_CAPTURE)) +#define QT_NO_XML +#endif + +// Check-boxes +#if !defined(QT_NO_CHECKBOX) && (defined(QT_NO_BUTTON) || defined(QT_NO_STYLE)) +#define QT_NO_CHECKBOX +#endif + +// Dials +#if !defined(QT_NO_DIAL) && (defined(QT_NO_RANGECONTROL) || defined(QT_NO_STYLE)) +#define QT_NO_DIAL +#endif + +// QLabel +#if !defined(QT_NO_LABEL) && (defined(QT_NO_FRAME)) +#define QT_NO_LABEL +#endif + +// QLCDNumber +#if !defined(QT_NO_LCDNUMBER) && (defined(QT_NO_FRAME)) +#define QT_NO_LCDNUMBER +#endif + +// MIME +#if !defined(QT_NO_MIME) && (defined(QT_NO_DIR) || defined(QT_NO_IMAGEIO) || defined(QT_NO_TEXTCODEC)) +#define QT_NO_MIME +#endif + +// Printing +#if !defined(QT_NO_PRINTER) && (defined(QT_NO_TEXTSTREAM) || defined(QT_NO_SPRINTF) || defined(QT_NO_FONTDATABASE) || defined(QT_NO_DATESTRING)) +#define QT_NO_PRINTER +#endif + +// Progress bars +#if !defined(QT_NO_PROGRESSBAR) && (defined(QT_NO_FRAME)) +#define QT_NO_PROGRESSBAR +#endif + +// Radio-buttons +#if !defined(QT_NO_RADIOBUTTON) && (defined(QT_NO_BUTTON) || defined(QT_NO_STYLE)) +#define QT_NO_RADIOBUTTON +#endif + +// Internal resize handler +#if !defined(QT_NO_RESIZEHANDLER) && (defined(QT_NO_FRAME)) +#define QT_NO_RESIZEHANDLER +#endif + +// Scroll bars +#if !defined(QT_NO_SCROLLBAR) && (defined(QT_NO_RANGECONTROL) || defined(QT_NO_STYLE)) +#define QT_NO_SCROLLBAR +#endif + +// Sliders +#if !defined(QT_NO_SLIDER) && (defined(QT_NO_RANGECONTROL) || defined(QT_NO_STYLE)) +#define QT_NO_SLIDER +#endif + +// Spinbox control widget +#if !defined(QT_NO_SPINWIDGET) && (defined(QT_NO_FRAME)) +#define QT_NO_SPINWIDGET +#endif + +// Status bars +#if !defined(QT_NO_STATUSBAR) && (defined(QT_NO_LAYOUT) || defined(QT_NO_STYLE)) +#define QT_NO_STATUSBAR +#endif + +// Compact Windows style +#if !defined(QT_NO_STYLE_COMPACT) && (defined(QT_NO_STYLE_WINDOWS)) +#define QT_NO_STYLE_COMPACT +#endif + +// Interlace-friendly style +#if !defined(QT_NO_STYLE_INTERLACE) && (defined(QT_NO_STYLE_MOTIF)) +#define QT_NO_STYLE_INTERLACE +#endif + +// Platinum style +#if !defined(QT_NO_STYLE_PLATINUM) && (defined(QT_NO_STYLE_WINDOWS)) +#define QT_NO_STYLE_PLATINUM +#endif + +// Widget stacks +#if !defined(QT_NO_WIDGETSTACK) && (defined(QT_NO_FRAME)) +#define QT_NO_WIDGETSTACK +#endif + +// Grid layout widgets +#if !defined(QT_NO_GRID) && (defined(QT_NO_LAYOUT) || defined(QT_NO_FRAME)) +#define QT_NO_GRID +#endif + +// Group boxes +#if !defined(QT_NO_GROUPBOX) && (defined(QT_NO_FRAME) || defined(QT_NO_LAYOUT)) +#define QT_NO_GROUPBOX +#endif + +// Horizonal box layout widgets +#if !defined(QT_NO_HBOX) && (defined(QT_NO_LAYOUT) || defined(QT_NO_FRAME)) +#define QT_NO_HBOX +#endif + +// Menu-oriented widgets +#if !defined(QT_NO_MENUDATA) && (defined(QT_NO_ICONSET) || defined(QT_NO_VARIANT)) +#define QT_NO_MENUDATA +#endif + +// RichText (HTML) display +#if !defined(QT_NO_RICHTEXT) && (defined(QT_NO_DRAWUTIL) || defined(QT_NO_LAYOUT) || defined(QT_NO_STRINGLIST) || defined(QT_NO_TEXTSTREAM)) +#define QT_NO_RICHTEXT +#endif + +// Splitters +#if !defined(QT_NO_SPLITTER) && (defined(QT_NO_FRAME) || defined(QT_NO_LAYOUT)) +#define QT_NO_SPLITTER +#endif + +// Table-like widgets +#if !defined(QT_NO_TABLEVIEW) && (defined(QT_NO_SCROLLBAR)) +#define QT_NO_TABLEVIEW +#endif + +// Tool tips +#if !defined(QT_NO_TOOLTIP) && (defined(QT_NO_LABEL)) +#define QT_NO_TOOLTIP +#endif + +// Cut and paste +#if !defined(QT_NO_CLIPBOARD) && (defined(QT_NO_QWS_PROPERTIES) || defined(QT_NO_MIME)) +#define QT_NO_CLIPBOARD +#endif + +// Complex scripts (eg. BiDi) +#if !defined(QT_NO_COMPLEXTEXT) && (defined(QT_NO_RICHTEXT)) +#define QT_NO_COMPLEXTEXT +#endif + +// Horizontal group boxes +#if !defined(QT_NO_HGROUPBOX) && (defined(QT_NO_GROUPBOX)) +#define QT_NO_HGROUPBOX +#endif + +// Network file access +#if !defined(QT_NO_NETWORKPROTOCOL) && (defined(QT_NO_DIR) || defined(QT_NO_TEXTCODEC) || defined(QT_NO_URL)) +#define QT_NO_NETWORKPROTOCOL +#endif + +// Properties +#if !defined(QT_NO_PROPERTIES) && (defined(QT_NO_VARIANT) || defined(QT_NO_STRINGLIST) || defined(QT_NO_ICONSET)) +#define QT_NO_PROPERTIES +#endif + +// CDE style +#if !defined(QT_NO_STYLE_CDE) && (defined(QT_NO_STYLE_MOTIF) || defined(QT_NO_TRANSFORMATIONS)) +#define QT_NO_STYLE_CDE +#endif + +// Motif-plus style +#if !defined(QT_NO_STYLE_MOTIFPLUS) && (defined(QT_NO_STYLE_MOTIF) || defined(QT_NO_TRANSFORMATIONS)) +#define QT_NO_STYLE_MOTIFPLUS +#endif + +// SGI style +#if !defined(QT_NO_STYLE_SGI) && (defined(QT_NO_STYLE_MOTIF) || defined(QT_NO_TRANSFORMATIONS)) +#define QT_NO_STYLE_SGI +#endif + +// Vertical box layout widgets +#if !defined(QT_NO_VBOX) && (defined(QT_NO_HBOX)) +#define QT_NO_VBOX +#endif + +// Button groups +#if !defined(QT_NO_BUTTONGROUP) && (defined(QT_NO_GROUPBOX) || defined(QT_NO_BUTTON)) +#define QT_NO_BUTTONGROUP +#endif + +// Cut and paste non-text +#if !defined(QT_NO_MIMECLIPBOARD) && (defined(QT_NO_CLIPBOARD)) +#define QT_NO_MIMECLIPBOARD +#endif + +// Aqua style +#if !defined(QT_NO_STYLE_AQUA) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGE_TRANSFORMATION)) +#define QT_NO_STYLE_AQUA +#endif + +// Vertical group boxes +#if !defined(QT_NO_VGROUPBOX) && (defined(QT_NO_HGROUPBOX)) +#define QT_NO_VGROUPBOX +#endif + +// Horizontal button groups +#if !defined(QT_NO_HBUTTONGROUP) && (defined(QT_NO_BUTTONGROUP)) +#define QT_NO_HBUTTONGROUP +#endif + +// Server to play sound +#if !defined(QT_NO_QWS_SOUNDSERVER) && (defined(QT_NO_SOUND) || defined(QT_NO_DIR) || defined(QT_NO_DNS)) +#define QT_NO_QWS_SOUNDSERVER +#endif + +// Hebrew Codec +#if !defined(QT_NO_CODEC_HEBREW) && (defined(QT_NO_CODECS) || defined(QT_NO_COMPLEXTEXT)) +#define QT_NO_CODEC_HEBREW +#endif + +// Dynamic module linking +#if !defined(QT_NO_COMPONENT) && (defined(QT_NO_QUUID_STRING) || defined(QT_NO_SETTINGS) || defined(QT_NO_SPRINTF) || defined(QT_NO_LIBRARY)) +#define QT_NO_COMPONENT +#endif + +// QHeader +#if !defined(QT_NO_HEADER) && (defined(QT_NO_STYLE) || defined(QT_NO_ICONSET)) +#define QT_NO_HEADER +#endif + +// Vertical button groups +#if !defined(QT_NO_VBUTTONGROUP) && (defined(QT_NO_HBUTTONGROUP)) +#define QT_NO_VBUTTONGROUP +#endif + +// Big Codecs (eg. CJK) +#if !defined(QT_NO_BIG_CODECS) && (defined(QT_NO_CODEC_HEBREW)) +#define QT_NO_BIG_CODECS +#endif + +// Tool-buttons +#if !defined(QT_NO_TOOLBUTTON) && (defined(QT_NO_BUTTON) || defined(QT_NO_ICONSET) || defined(QT_NO_STYLE)) +#define QT_NO_TOOLBUTTON +#endif + +// Document Object Model +#if !defined(QT_NO_DOM) && (defined(QT_NO_XML) || defined(QT_NO_MIME)) +#define QT_NO_DOM +#endif + +// Scrollable view widgets +#if !defined(QT_NO_SCROLLVIEW) && (defined(QT_NO_SCROLLBAR) || defined(QT_NO_FRAME)) +#define QT_NO_SCROLLVIEW +#endif + +// Tab-bars +#if !defined(QT_NO_TABBAR) && (defined(QT_NO_TOOLBUTTON)) +#define QT_NO_TABBAR +#endif + +// QTextCodecPlugin +#if !defined(QT_NO_TEXTCODECPLUGIN) && (defined(QT_NO_COMPONENT) || defined(QT_NO_TEXTCODEC)) +#define QT_NO_TEXTCODECPLUGIN +#endif + +// Drag and drop +#if !defined(QT_NO_DRAGANDDROP) && (defined(QT_NO_MIME) || defined(QT_NO_QWS_PROPERTIES) || defined(QT_NO_IMAGEIO_XPM)) +#define QT_NO_DRAGANDDROP +#endif + +// QGridView +#if !defined(QT_NO_GRIDVIEW) && (defined(QT_NO_SCROLLVIEW)) +#define QT_NO_GRIDVIEW +#endif + +// QImageFormatPlugin +#if !defined(QT_NO_IMAGEFORMATPLUGIN) && (defined(QT_NO_COMPONENT) || defined(QT_NO_IMAGEIO)) +#define QT_NO_IMAGEFORMATPLUGIN +#endif + +// Single-line edits +#if !defined(QT_NO_LINEEDIT) && (defined(QT_NO_FRAME) || defined(QT_NO_RICHTEXT)) +#define QT_NO_LINEEDIT +#endif + +// Popup-menus +#if !defined(QT_NO_POPUPMENU) && (defined(QT_NO_MENUDATA) || defined(QT_NO_FRAME)) +#define QT_NO_POPUPMENU +#endif + +// QCanvas +#if !defined(QT_NO_CANVAS) && (defined(QT_NO_SCROLLVIEW) || defined(QT_NO_BEZIER)) +#define QT_NO_CANVAS +#endif + +// QListBox +#if !defined(QT_NO_LISTBOX) && (defined(QT_NO_SCROLLVIEW) || defined(QT_NO_STRINGLIST)) +#define QT_NO_LISTBOX +#endif + +// Menu bars +#if !defined(QT_NO_MENUBAR) && (defined(QT_NO_POPUPMENU)) +#define QT_NO_MENUBAR +#endif + +// HTTP file access +#if !defined(QT_NO_NETWORKPROTOCOL_HTTP) && (defined(QT_NO_NETWORKPROTOCOL) || defined(QT_NO_DNS)) +#define QT_NO_NETWORKPROTOCOL_HTTP +#endif + +// RichText (HTML) tables and images +#if !defined(QT_NO_TEXTCUSTOMITEM) && (defined(QT_NO_RICHTEXT) || defined(QT_NO_MIME)) +#define QT_NO_TEXTCUSTOMITEM +#endif + +// QDateTimeEdit +#if !defined(QT_NO_DATETIMEEDIT) && (defined(QT_NO_RICHTEXT) || defined(QT_NO_SPINWIDGET) || defined(QT_NO_DATESTRING)) +#define QT_NO_DATETIMEEDIT +#endif + +// Push-buttons +#if !defined(QT_NO_PUSHBUTTON) && (defined(QT_NO_BUTTON) || defined(QT_NO_POPUPMENU)) +#define QT_NO_PUSHBUTTON +#endif + +// FTP file access +#if !defined(QT_NO_NETWORKPROTOCOL_FTP) && (defined(QT_NO_NETWORKPROTOCOL) || defined(QT_NO_DNS) || defined(QT_NO_TEXTDATE)) +#define QT_NO_NETWORKPROTOCOL_FTP +#endif + +// Scalable Vector Graphics (SVG) +#if !defined(QT_NO_SVG) && (defined(QT_NO_DOM) || defined(QT_NO_TRANSFORMATIONS) || defined(QT_NO_SPRINTF)) +#define QT_NO_SVG +#endif + +// QWidgetPlugin +#if !defined(QT_NO_WIDGETPLUGIN) && (defined(QT_NO_COMPONENT) || defined(QT_NO_ICONSET)) +#define QT_NO_WIDGETPLUGIN +#endif + +// QIconView +#if !defined(QT_NO_ICONVIEW) && (defined(QT_NO_SCROLLVIEW) || defined(QT_NO_IMAGEIO_XPM) || defined(QT_NO_IMAGE_HEURISTIC_MASK)) +#define QT_NO_ICONVIEW +#endif + +// Tab widgets +#if !defined(QT_NO_TABWIDGET) && (defined(QT_NO_TABBAR) || defined(QT_NO_WIDGETSTACK)) +#define QT_NO_TABWIDGET +#endif + +// "What's this" help +#if !defined(QT_NO_WHATSTHIS) && (defined(QT_NO_TOOLTIP) || defined(QT_NO_TOOLBUTTON)) +#define QT_NO_WHATSTHIS +#endif + +// Rich text edit +#if !defined(QT_NO_TEXTEDIT) && (defined(QT_NO_RICHTEXT) || defined(QT_NO_SCROLLVIEW)) +#define QT_NO_TEXTEDIT +#endif + +// Multi-line edits +#if !defined(QT_NO_MULTILINEEDIT) && (defined(QT_NO_TEXTEDIT)) +#define QT_NO_MULTILINEEDIT +#endif + +// QTextView +#if !defined(QT_NO_TEXTVIEW) && (defined(QT_NO_TEXTEDIT)) +#define QT_NO_TEXTVIEW +#endif + +// Spin boxes +#if !defined(QT_NO_SPINBOX) && (defined(QT_NO_RANGECONTROL) || defined(QT_NO_SPINWIDGET) || defined(QT_NO_LINEEDIT) || defined(QT_NO_VALIDATOR)) +#define QT_NO_SPINBOX +#endif + +// QMessageBox +#if !defined(QT_NO_MESSAGEBOX) && (defined(QT_NO_DIALOG) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_LABEL)) +#define QT_NO_MESSAGEBOX +#endif + +// SQL classes +#if !defined(QT_NO_SQL) && (defined(QT_NO_MESSAGEBOX)) +#define QT_NO_SQL +#endif + +// QTextBrowser +#if !defined(QT_NO_TEXTBROWSER) && (defined(QT_NO_TEXTVIEW) || defined(QT_NO_MIME)) +#define QT_NO_TEXTBROWSER +#endif + +// QProgressDialog +#if !defined(QT_NO_PROGRESSDIALOG) && (defined(QT_NO_SEMIMODAL) || defined(QT_NO_LABEL) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_PROGRESSBAR)) +#define QT_NO_PROGRESSDIALOG +#endif + +// QWizard +#if !defined(QT_NO_WIZARD) && (defined(QT_NO_DIALOG) || defined(QT_NO_WIDGETSTACK) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_LAYOUT) || defined(QT_NO_LABEL)) +#define QT_NO_WIZARD +#endif + +// QSqlForm +#if !defined(QT_NO_SQL_FORM) && (defined(QT_NO_SQL) || defined(QT_NO_PROPERTIES)) +#define QT_NO_SQL_FORM +#endif + +// QListView +#if !defined(QT_NO_LISTVIEW) && (defined(QT_NO_SCROLLVIEW) || defined(QT_NO_HEADER) || defined(QT_NO_LINEEDIT)) +#define QT_NO_LISTVIEW +#endif + +// QTabDialog +#if !defined(QT_NO_TABDIALOG) && (defined(QT_NO_DIALOG) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_LAYOUT) || defined(QT_NO_TABWIDGET)) +#define QT_NO_TABDIALOG +#endif + +// QComboBox +#if !defined(QT_NO_COMBOBOX) && (defined(QT_NO_LISTBOX) || defined(QT_NO_LINEEDIT) || defined(QT_NO_POPUPMENU)) +#define QT_NO_COMBOBOX +#endif + +// Main-windows +#if !defined(QT_NO_MAINWINDOW) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_POPUPMENU) || defined(QT_NO_TITLEBAR) || defined(QT_NO_RESIZEHANDLER) || defined(QT_NO_TOOLBUTTON) || defined(QT_NO_STATUSBAR)) +#define QT_NO_MAINWINDOW +#endif + +// Toolbars +#if !defined(QT_NO_TOOLBAR) && (defined(QT_NO_MAINWINDOW)) +#define QT_NO_TOOLBAR +#endif + +// QColorDialog +#if !defined(QT_NO_COLORDIALOG) && (defined(QT_NO_DIALOG) || defined(QT_NO_LABEL) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_LINEEDIT) || defined(QT_NO_VALIDATOR) || defined(QT_NO_GRIDVIEW)) +#define QT_NO_COLORDIALOG +#endif + +// QErrorMessage +#if !defined(QT_NO_ERRORMESSAGE) && (defined(QT_NO_DIALOG) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_LABEL) || defined(QT_NO_CHECKBOX) || defined(QT_NO_TEXTVIEW)) +#define QT_NO_ERRORMESSAGE +#endif + +// QAction +#if !defined(QT_NO_ACTION) && (defined(QT_NO_TOOLBUTTON) || defined(QT_NO_COMBOBOX)) +#define QT_NO_ACTION +#endif + +// QWorkSpace +#if !defined(QT_NO_WORKSPACE) && (defined(QT_NO_SCROLLBAR) || defined(QT_NO_VBOX) || defined(QT_NO_TITLEBAR) || defined(QT_NO_RESIZEHANDLER) || defined(QT_NO_POPUPMENU) || defined(QT_NO_LABEL) || defined(QT_NO_TOOLBUTTON)) +#define QT_NO_WORKSPACE +#endif + +// QTable +#if !defined(QT_NO_TABLE) && (defined(QT_NO_COMBOBOX) || defined(QT_NO_HEADER) || defined(QT_NO_CHECKBOX)) +#define QT_NO_TABLE +#endif + +// QFontDialog +#if !defined(QT_NO_FONTDIALOG) && (defined(QT_NO_DIALOG) || defined(QT_NO_FONTDATABASE) || defined(QT_NO_COMBOBOX) || defined(QT_NO_LABEL) || defined(QT_NO_CHECKBOX) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_VGROUPBOX)) +#define QT_NO_FONTDIALOG +#endif + +// QInputDialog +#if !defined(QT_NO_INPUTDIALOG) && (defined(QT_NO_DIALOG) || defined(QT_NO_COMBOBOX) || defined(QT_NO_LABEL) || defined(QT_NO_PUSHBUTTON) || defined(QT_NO_SPINBOX) || defined(QT_NO_WIDGETSTACK)) +#define QT_NO_INPUTDIALOG +#endif + +// SQL value editor widgets +#if !defined(QT_NO_SQL_EDIT_WIDGETS) && (defined(QT_NO_SQL) || defined(QT_NO_SPINBOX) || defined(QT_NO_COMBOBOX) || defined(QT_NO_CHECKBOX) || defined(QT_NO_DATETIMEEDIT)) +#define QT_NO_SQL_EDIT_WIDGETS +#endif + +// QPrintDialog +#if !defined(QT_NO_PRINTDIALOG) && (defined(QT_NO_DIALOG) || defined(QT_NO_LISTVIEW) || defined(QT_NO_PRINTER) || defined(QT_NO_COMBOBOX) || defined(QT_NO_LABEL) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_SPINBOX) || defined(QT_NO_RADIOBUTTON) || defined(QT_NO_PUSHBUTTON)) +#define QT_NO_PRINTDIALOG +#endif + +// QFileDialog +#if !defined(QT_NO_FILEDIALOG) && (defined(QT_NO_MESSAGEBOX) || defined(QT_NO_LISTVIEW) || defined(QT_NO_NETWORKPROTOCOL) || defined(QT_NO_COMBOBOX) || defined(QT_NO_SEMIMODAL) || defined(QT_NO_REGEXP_CAPTURE) || defined(QT_NO_TOOLBUTTON) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_VBOX) || defined(QT_NO_SPLITTER) || defined(QT_NO_PROGRESSBAR) || defined(QT_NO_WIDGETSTACK) || defined(QT_NO_DATESTRING)) +#define QT_NO_FILEDIALOG +#endif + +// SQL table widgets +#if !defined(QT_NO_SQL_VIEW_WIDGETS) && (defined(QT_NO_SQL_FORM) || defined(QT_NO_SQL_EDIT_WIDGETS) || defined(QT_NO_TABLE)) +#define QT_NO_SQL_VIEW_WIDGETS +#endif + diff --git a/qmake/include/qfile.h b/qmake/include/qfile.h new file mode 100644 index 0000000..14a917b --- a/dev/null +++ b/qmake/include/qfile.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QFile class +** +** Created : 930831 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QFILE_H +#define QFILE_H + +#ifndef QT_H +#include "qiodevice.h" +#include "qstring.h" +#include <stdio.h> +#endif // QT_H + +class QDir; + + +class Q_EXPORT QFile : public QIODevice // file I/O device class +{ +public: + QFile(); + QFile( const QString &name ); + ~QFile(); + + QString name() const; + void setName( const QString &name ); + + typedef QCString (*EncoderFn)( const QString &fileName ); + typedef QString (*DecoderFn)( const QCString &localfileName ); + static QCString encodeName( const QString &fileName ); + static QString decodeName( const QCString &localFileName ); + static void setEncodingFunction( EncoderFn ); + static void setDecodingFunction( DecoderFn ); + + bool exists() const; + static bool exists( const QString &fileName ); + + bool remove(); + static bool remove( const QString &fileName ); + + bool open( int ); + bool open( int, FILE * ); + bool open( int, int ); + void close(); + void flush(); + + Offset size() const; + Offset at() const; + bool at( Offset ); + bool atEnd() const; + + Q_LONG readBlock( char *data, Q_ULONG len ); + Q_LONG writeBlock( const char *data, Q_ULONG len ); + Q_LONG writeBlock( const QByteArray& data ) + { return QIODevice::writeBlock(data); } + Q_LONG readLine( char *data, Q_ULONG maxlen ); + Q_LONG readLine( QString &, Q_ULONG maxlen ); + + int getch(); + int putch( int ); + int ungetch( int ); + + int handle() const; + +protected: + QString fn; + FILE *fh; + int fd; + Offset length; + bool ext_f; + void * d; + +private: + void init(); + QCString ungetchBuffer; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QFile( const QFile & ); + QFile &operator=( const QFile & ); +#endif +}; + + +inline QString QFile::name() const +{ return fn; } + +inline QIODevice::Offset QFile::at() const +{ return ioIndex; } + + +#endif // QFILE_H diff --git a/qmake/include/qfileinfo.h b/qmake/include/qfileinfo.h new file mode 100644 index 0000000..d6605b6 --- a/dev/null +++ b/qmake/include/qfileinfo.h @@ -0,0 +1,150 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QFileInfo class +** +** Created : 950628 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QFILEINFO_H +#define QFILEINFO_H + +#ifndef QT_H +#include "qfile.h" +#include "qdatetime.h" +#endif // QT_H + + +class QDir; +struct QFileInfoCache; + + +class Q_EXPORT QFileInfo +{ +public: + enum PermissionSpec { + ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, + ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, + ReadOther = 0004, WriteOther = 0002, ExeOther = 0001 }; + + QFileInfo(); + QFileInfo( const QString &file ); + QFileInfo( const QFile & ); +#ifndef QT_NO_DIR + QFileInfo( const QDir &, const QString &fileName ); +#endif + QFileInfo( const QFileInfo & ); + ~QFileInfo(); + + QFileInfo &operator=( const QFileInfo & ); + + void setFile( const QString &file ); + void setFile( const QFile & ); +#ifndef QT_NO_DIR + void setFile( const QDir &, const QString &fileName ); +#endif + bool exists() const; + void refresh() const; + bool caching() const; + void setCaching( bool ); + + QString filePath() const; + QString fileName() const; +#ifndef QT_NO_DIR //### + QString absFilePath() const; +#endif + QString baseName( bool complete = FALSE ) const; + QString extension( bool complete = TRUE ) const; + +#ifndef QT_NO_DIR //### + QString dirPath( bool absPath = FALSE ) const; +#endif +#ifndef QT_NO_DIR + QDir dir( bool absPath = FALSE ) const; +#endif + bool isReadable() const; + bool isWritable() const; + bool isExecutable() const; + bool isHidden() const; + +#ifndef QT_NO_DIR //### + bool isRelative() const; + bool convertToAbs(); +#endif + + bool isFile() const; + bool isDir() const; + bool isSymLink() const; + + QString readLink() const; + + QString owner() const; + uint ownerId() const; + QString group() const; + uint groupId() const; + + bool permission( int permissionSpec ) const; + +#if (QT_VERSION-0 >= 0x040000) +#error "QFileInfo::size() should return QIODevice::Offset instead of uint" +#elif defined(QT_ABI_QT4) + QIODevice::Offset size() const; +#else + uint size() const; +#endif + + QDateTime created() const; + QDateTime lastModified() const; + QDateTime lastRead() const; + +private: + void doStat() const; + static void slashify( QString & ); + static void makeAbs( QString & ); + + QString fn; + QFileInfoCache *fic; + bool cache; +#if defined(Q_OS_UNIX) + bool symLink; +#endif + +}; + + +inline bool QFileInfo::caching() const +{ + return cache; +} + + +#endif // QFILEINFO_H diff --git a/qmake/include/qgarray.h b/qmake/include/qgarray.h new file mode 100644 index 0000000..12edea6 --- a/dev/null +++ b/qmake/include/qgarray.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QGArray class +** +** Created : 930906 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGARRAY_H +#define QGARRAY_H + +#ifndef QT_H +#include "qshared.h" +#endif // QT_H + + +class Q_EXPORT QGArray // generic array +{ +friend class QBuffer; +public: + //### DO NOT USE THIS. IT IS PUBLIC BUT DO NOT USE IT IN NEW CODE. + struct array_data : public QShared { // shared array + array_data() { data=0; len=0; } + char *data; // actual array data + uint len; + }; + QGArray(); +protected: + QGArray( int, int ); // dummy; does not alloc + QGArray( int size ); // allocate 'size' bytes + QGArray( const QGArray &a ); // shallow copy + virtual ~QGArray(); + + QGArray &operator=( const QGArray &a ) { return assign( a ); } + + virtual void detach() { duplicate(*this); } + + // ### Qt 4.0: maybe provide two versions of data(), at(), etc. + char *data() const { return shd->data; } + uint nrefs() const { return shd->count; } + uint size() const { return shd->len; } + bool isEqual( const QGArray &a ) const; + + bool resize( uint newsize ); + + bool fill( const char *d, int len, uint sz ); + + QGArray &assign( const QGArray &a ); + QGArray &assign( const char *d, uint len ); + QGArray &duplicate( const QGArray &a ); + QGArray &duplicate( const char *d, uint len ); + void store( const char *d, uint len ); + + array_data *sharedBlock() const { return shd; } + void setSharedBlock( array_data *p ) { shd=(array_data*)p; } + + QGArray &setRawData( const char *d, uint len ); + void resetRawData( const char *d, uint len ); + + int find( const char *d, uint index, uint sz ) const; + int contains( const char *d, uint sz ) const; + + void sort( uint sz ); + int bsearch( const char *d, uint sz ) const; + + char *at( uint index ) const; + + bool setExpand( uint index, const char *d, uint sz ); + +protected: + virtual array_data *newData(); + virtual void deleteData( array_data *p ); + +private: + static void msg_index( uint ); + array_data *shd; +}; + + +inline char *QGArray::at( uint index ) const +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + msg_index( index ); + index = 0; + } +#endif + return &shd->data[index]; +} + + +#endif // QGARRAY_H diff --git a/qmake/include/qgcache.h b/qmake/include/qgcache.h new file mode 100644 index 0000000..093f7a7 --- a/dev/null +++ b/qmake/include/qgcache.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QGCache and QGCacheIterator classes +** +** Created : 950208 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGCACHE_H +#define QGCACHE_H + +#ifndef QT_H +#include "qptrcollection.h" +#include "qglist.h" +#include "qgdict.h" +#endif // QT_H + + +class QCList; // internal classes +class QCListIt; +class QCDict; + + +class Q_EXPORT QGCache : public QPtrCollection // generic LRU cache +{ +friend class QGCacheIterator; +protected: + enum KeyType { StringKey, AsciiKey, IntKey, PtrKey }; + // identical to QGDict's, but PtrKey is not used at the moment + + QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive, + bool copyKeys ); + QGCache( const QGCache & ); // not allowed, calls fatal() + ~QGCache(); + QGCache &operator=( const QGCache & ); // not allowed, calls fatal() + + uint count() const; + uint size() const; + int maxCost() const { return mCost; } + int totalCost() const { return tCost; } + void setMaxCost( int maxCost ); + void clear(); + + bool insert_string( const QString &key, QPtrCollection::Item, + int cost, int priority ); + bool insert_other( const char *key, QPtrCollection::Item, + int cost, int priority ); + bool remove_string( const QString &key ); + bool remove_other( const char *key ); + QPtrCollection::Item take_string( const QString &key ); + QPtrCollection::Item take_other( const char *key ); + + QPtrCollection::Item find_string( const QString &key, bool ref=TRUE ) const; + QPtrCollection::Item find_other( const char *key, bool ref=TRUE ) const; + + void statistics() const; + +private: + bool makeRoomFor( int cost, int priority = -1 ); + KeyType keytype; + QCList *lruList; + QCDict *dict; + int mCost; + int tCost; + bool copyk; +}; + + +class Q_EXPORT QGCacheIterator // generic cache iterator +{ +protected: + QGCacheIterator( const QGCache & ); + QGCacheIterator( const QGCacheIterator & ); + ~QGCacheIterator(); + QGCacheIterator &operator=( const QGCacheIterator & ); + + uint count() const; + bool atFirst() const; + bool atLast() const; + QPtrCollection::Item toFirst(); + QPtrCollection::Item toLast(); + + QPtrCollection::Item get() const; + QString getKeyString() const; + const char *getKeyAscii() const; + long getKeyInt() const; + + QPtrCollection::Item operator()(); + QPtrCollection::Item operator++(); + QPtrCollection::Item operator+=( uint ); + QPtrCollection::Item operator--(); + QPtrCollection::Item operator-=( uint ); + +protected: + QCListIt *it; // iterator on cache list +}; + + +#endif // QGCACHE_H diff --git a/qmake/include/qgdict.h b/qmake/include/qgdict.h new file mode 100644 index 0000000..40b4568 --- a/dev/null +++ b/qmake/include/qgdict.h @@ -0,0 +1,222 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QGDict and QGDictIterator classes +** +** Created : 920529 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGDICT_H +#define QGDICT_H + +#ifndef QT_H +#include "qptrcollection.h" +#include "qstring.h" +#endif // QT_H + +class QGDictIterator; +class QGDItList; + + +class QBaseBucket // internal dict node +{ +public: + QPtrCollection::Item getData() { return data; } + QPtrCollection::Item setData( QPtrCollection::Item d ) { return data = d; } + QBaseBucket *getNext() { return next; } + void setNext( QBaseBucket *n) { next = n; } +protected: + QBaseBucket( QPtrCollection::Item d, QBaseBucket *n ) : data(d), next(n) {} + QPtrCollection::Item data; + QBaseBucket *next; +}; + +class QStringBucket : public QBaseBucket +{ +public: + QStringBucket( const QString &k, QPtrCollection::Item d, QBaseBucket *n ) + : QBaseBucket(d,n), key(k) {} + const QString &getKey() const { return key; } +private: + QString key; +}; + +class QAsciiBucket : public QBaseBucket +{ +public: + QAsciiBucket( const char *k, QPtrCollection::Item d, QBaseBucket *n ) + : QBaseBucket(d,n), key(k) {} + const char *getKey() const { return key; } +private: + const char *key; +}; + +class QIntBucket : public QBaseBucket +{ +public: + QIntBucket( long k, QPtrCollection::Item d, QBaseBucket *n ) + : QBaseBucket(d,n), key(k) {} + long getKey() const { return key; } +private: + long key; +}; + +class QPtrBucket : public QBaseBucket +{ +public: + QPtrBucket( void *k, QPtrCollection::Item d, QBaseBucket *n ) + : QBaseBucket(d,n), key(k) {} + void *getKey() const { return key; } +private: + void *key; +}; + + +class Q_EXPORT QGDict : public QPtrCollection // generic dictionary class +{ +public: + uint count() const { return numItems; } + uint size() const { return vlen; } + QPtrCollection::Item look_string( const QString& key, QPtrCollection::Item, + int ); + QPtrCollection::Item look_ascii( const char *key, QPtrCollection::Item, int ); + QPtrCollection::Item look_int( long key, QPtrCollection::Item, int ); + QPtrCollection::Item look_ptr( void *key, QPtrCollection::Item, int ); +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream & ); + QDataStream &write( QDataStream & ) const; +#endif +protected: + enum KeyType { StringKey, AsciiKey, IntKey, PtrKey }; + + QGDict( uint len, KeyType kt, bool cs, bool ck ); + QGDict( const QGDict & ); + ~QGDict(); + + QGDict &operator=( const QGDict & ); + + bool remove_string( const QString &key, QPtrCollection::Item item=0 ); + bool remove_ascii( const char *key, QPtrCollection::Item item=0 ); + bool remove_int( long key, QPtrCollection::Item item=0 ); + bool remove_ptr( void *key, QPtrCollection::Item item=0 ); + QPtrCollection::Item take_string( const QString &key ); + QPtrCollection::Item take_ascii( const char *key ); + QPtrCollection::Item take_int( long key ); + QPtrCollection::Item take_ptr( void *key ); + + void clear(); + void resize( uint ); + + int hashKeyString( const QString & ); + int hashKeyAscii( const char * ); + + void statistics() const; + +#ifndef QT_NO_DATASTREAM + virtual QDataStream &read( QDataStream &, QPtrCollection::Item & ); + virtual QDataStream &write( QDataStream &, QPtrCollection::Item ) const; +#endif +private: + QBaseBucket **vec; + uint vlen; + uint numItems; + uint keytype : 2; + uint cases : 1; + uint copyk : 1; + QGDItList *iterators; + void unlink_common( int, QBaseBucket *, QBaseBucket * ); + QStringBucket *unlink_string( const QString &, + QPtrCollection::Item item = 0 ); + QAsciiBucket *unlink_ascii( const char *, QPtrCollection::Item item = 0 ); + QIntBucket *unlink_int( long, QPtrCollection::Item item = 0 ); + QPtrBucket *unlink_ptr( void *, QPtrCollection::Item item = 0 ); + void init( uint, KeyType, bool, bool ); + friend class QGDictIterator; +}; + + +class Q_EXPORT QGDictIterator // generic dictionary iterator +{ +friend class QGDict; +public: + QGDictIterator( const QGDict & ); + QGDictIterator( const QGDictIterator & ); + QGDictIterator &operator=( const QGDictIterator & ); + ~QGDictIterator(); + + QPtrCollection::Item toFirst(); + + QPtrCollection::Item get() const; + QString getKeyString() const; + const char *getKeyAscii() const; + long getKeyInt() const; + void *getKeyPtr() const; + + QPtrCollection::Item operator()(); + QPtrCollection::Item operator++(); + QPtrCollection::Item operator+=(uint); + +protected: + QGDict *dict; + +private: + QBaseBucket *curNode; + uint curIndex; +}; + +inline QPtrCollection::Item QGDictIterator::get() const +{ + return curNode ? curNode->getData() : 0; +} + +inline QString QGDictIterator::getKeyString() const +{ + return curNode ? ((QStringBucket*)curNode)->getKey() : QString::null; +} + +inline const char *QGDictIterator::getKeyAscii() const +{ + return curNode ? ((QAsciiBucket*)curNode)->getKey() : 0; +} + +inline long QGDictIterator::getKeyInt() const +{ + return curNode ? ((QIntBucket*)curNode)->getKey() : 0; +} + +inline void *QGDictIterator::getKeyPtr() const +{ + return curNode ? ((QPtrBucket*)curNode)->getKey() : 0; +} + + +#endif // QGDICT_H diff --git a/qmake/include/qglist.h b/qmake/include/qglist.h new file mode 100644 index 0000000..d6db3ed --- a/dev/null +++ b/qmake/include/qglist.h @@ -0,0 +1,252 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QGList and QGListIterator classes +** +** Created : 920624 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGLIST_H +#define QGLIST_H + +#ifndef QT_H +#include "qptrcollection.h" +#endif // QT_H + +class Q_EXPORT QLNode +{ +friend class QGList; +friend class QGListIterator; +public: + QPtrCollection::Item getData() { return data; } +private: + QPtrCollection::Item data; + QLNode *prev; + QLNode *next; + QLNode( QPtrCollection::Item d ) { data = d; } +}; + +class QGListIteratorList; // internal helper class + +class Q_EXPORT QGList : public QPtrCollection // doubly linked generic list +{ +friend class QGListIterator; +friend class QGListIteratorList; +friend class QGVector; // needed by QGVector::toList +public: + uint count() const; // return number of nodes + +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream & ); // read list from stream + QDataStream &write( QDataStream & ) const; // write list to stream +#endif +protected: + QGList(); // create empty list + QGList( const QGList & ); // make copy of other list + virtual ~QGList(); + + QGList &operator=( const QGList & ); // assign from other list + bool operator==( const QGList& ) const; + + void inSort( QPtrCollection::Item ); // add item sorted in list + void append( QPtrCollection::Item ); // add item at end of list + bool insertAt( uint index, QPtrCollection::Item ); // add item at i'th position + void relinkNode( QLNode * ); // relink as first item + bool removeNode( QLNode * ); // remove node + bool remove( QPtrCollection::Item = 0 ); // remove item (0=current) + bool removeRef( QPtrCollection::Item = 0 ); // remove item (0=current) + bool removeFirst(); // remove first item + bool removeLast(); // remove last item + bool removeAt( uint ); // remove item at i'th position + bool replaceAt( uint, QPtrCollection::Item ); // replace item at position i with item + QPtrCollection::Item takeNode( QLNode * ); // take out node + QPtrCollection::Item take(); // take out current item + QPtrCollection::Item takeAt( uint index ); // take out item at i'th pos + QPtrCollection::Item takeFirst(); // take out first item + QPtrCollection::Item takeLast(); // take out last item + + void sort(); // sort all items; + void clear(); // remove all items + + int findRef( QPtrCollection::Item, bool = TRUE ); // find exact item in list + int find( QPtrCollection::Item, bool = TRUE ); // find equal item in list + + uint containsRef( QPtrCollection::Item ) const; // get number of exact matches + uint contains( QPtrCollection::Item ) const; // get number of equal matches + + QPtrCollection::Item at( uint index ); // access item at i'th pos + int at() const; // get current index + QLNode *currentNode() const; // get current node + + QPtrCollection::Item get() const; // get current item + + QPtrCollection::Item cfirst() const; // get ptr to first list item + QPtrCollection::Item clast() const; // get ptr to last list item + QPtrCollection::Item first(); // set first item in list curr + QPtrCollection::Item last(); // set last item in list curr + QPtrCollection::Item next(); // set next item in list curr + QPtrCollection::Item prev(); // set prev item in list curr + + void toVector( QGVector * ) const; // put items in vector + + virtual int compareItems( QPtrCollection::Item, QPtrCollection::Item ); + +#ifndef QT_NO_DATASTREAM + virtual QDataStream &read( QDataStream &, QPtrCollection::Item & ); + virtual QDataStream &write( QDataStream &, QPtrCollection::Item ) const; +#endif +private: + void prepend( QPtrCollection::Item ); // add item at start of list + + void heapSortPushDown( QPtrCollection::Item* heap, int first, int last ); + + QLNode *firstNode; // first node + QLNode *lastNode; // last node + QLNode *curNode; // current node + int curIndex; // current index + uint numNodes; // number of nodes + QGListIteratorList *iterators; // list of iterators + + QLNode *locate( uint ); // get node at i'th pos + QLNode *unlink(); // unlink node +}; + + +inline uint QGList::count() const +{ + return numNodes; +} + +inline bool QGList::removeFirst() +{ + first(); + return remove(); +} + +inline bool QGList::removeLast() +{ + last(); + return remove(); +} + +inline int QGList::at() const +{ + return curIndex; +} + +inline QPtrCollection::Item QGList::at( uint index ) +{ + QLNode *n = locate( index ); + return n ? n->data : 0; +} + +inline QLNode *QGList::currentNode() const +{ + return curNode; +} + +inline QPtrCollection::Item QGList::get() const +{ + return curNode ? curNode->data : 0; +} + +inline QPtrCollection::Item QGList::cfirst() const +{ + return firstNode ? firstNode->data : 0; +} + +inline QPtrCollection::Item QGList::clast() const +{ + return lastNode ? lastNode->data : 0; +} + + +/***************************************************************************** + QGList stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator>>( QDataStream &, QGList & ); +Q_EXPORT QDataStream &operator<<( QDataStream &, const QGList & ); +#endif + +/***************************************************************************** + QGListIterator class + *****************************************************************************/ + +class Q_EXPORT QGListIterator // QGList iterator +{ +friend class QGList; +friend class QGListIteratorList; +protected: + QGListIterator( const QGList & ); + QGListIterator( const QGListIterator & ); + QGListIterator &operator=( const QGListIterator & ); + ~QGListIterator(); + + bool atFirst() const; // test if at first item + bool atLast() const; // test if at last item + QPtrCollection::Item toFirst(); // move to first item + QPtrCollection::Item toLast(); // move to last item + + QPtrCollection::Item get() const; // get current item + QPtrCollection::Item operator()(); // get current and move to next + QPtrCollection::Item operator++(); // move to next item (prefix) + QPtrCollection::Item operator+=(uint); // move n positions forward + QPtrCollection::Item operator--(); // move to prev item (prefix) + QPtrCollection::Item operator-=(uint); // move n positions backward + +protected: + QGList *list; // reference to list + +private: + QLNode *curNode; // current node in list +}; + + +inline bool QGListIterator::atFirst() const +{ + return curNode == list->firstNode; +} + +inline bool QGListIterator::atLast() const +{ + return curNode == list->lastNode; +} + +inline QPtrCollection::Item QGListIterator::get() const +{ + return curNode ? curNode->data : 0; +} + + +#endif // QGLIST_H diff --git a/qmake/include/qglobal.h b/qmake/include/qglobal.h new file mode 100644 index 0000000..13cff64 --- a/dev/null +++ b/qmake/include/qglobal.h @@ -0,0 +1,1006 @@ +/**************************************************************************** +** $Id$ +** +** Global type declarations and definitions +** +** Created : 920529 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGLOBAL_H +#define QGLOBAL_H + +#define QT_VERSION_STR "3.1.0-b2" +/* + QT_VERSION is (major << 16) + (minor << 8) + patch. + */ +#define QT_VERSION 0x030100 + +/* + The operating system, must be one of: (Q_OS_x) + + MACX - Mac OS X + MAC9 - Mac OS 9 + MSDOS - MS-DOS and Windows + OS2 - OS/2 + OS2EMX - XFree86 on OS/2 (not PM) + WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) + CYGWIN - Cygwin + SOLARIS - Sun Solaris + HPUX - HP-UX + ULTRIX - DEC Ultrix + LINUX - Linux + FREEBSD - FreeBSD + NETBSD - NetBSD + OPENBSD - OpenBSD + BSDI - BSD/OS + IRIX - SGI Irix + OSF - HP Tru64 UNIX + SCO - SCO OpenServer 5 + UNIXWARE - UnixWare 7, Open UNIX 8 + AIX - AIX + HURD - GNU Hurd + DGUX - DG/UX + RELIANT - Reliant UNIX + DYNIX - DYNIX/ptx + QNX - QNX + QNX6 - QNX RTP 6.1 + LYNX - LynxOS + BSD4 - Any BSD 4.4 system + UNIX - Any UNIX BSD/SYSV system +*/ + +#if defined(__APPLE__) && defined(__GNUC__) +# define Q_OS_MACX +#elif defined(__MACOSX__) +# define Q_OS_MACX +#elif defined(macintosh) +# define Q_OS_MAC9 +#elif defined(__CYGWIN__) +# define Q_OS_CYGWIN +#elif defined(MSDOS) || defined(_MSDOS) +# define Q_OS_MSDOS +#elif defined(__OS2__) +# if defined(__EMX__) +# define Q_OS_OS2EMX +# else +# define Q_OS_OS2 +# endif +#elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) +# define Q_OS_WIN32 +# define Q_OS_WIN64 +#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) +# define Q_OS_WIN32 +#elif defined(__MWERKS__) && defined(__INTEL__) +# define Q_OS_WIN32 +#elif defined(__sun) || defined(sun) +# define Q_OS_SOLARIS +#elif defined(hpux) || defined(__hpux) +# define Q_OS_HPUX +#elif defined(__ultrix) || defined(ultrix) +# define Q_OS_ULTRIX +#elif defined(sinix) +# define Q_OS_RELIANT +#elif defined(__linux__) || defined(__linux) +# define Q_OS_LINUX +#elif defined(__FreeBSD__) +# define Q_OS_FREEBSD +# define Q_OS_BSD4 +#elif defined(__NetBSD__) +# define Q_OS_NETBSD +# define Q_OS_BSD4 +#elif defined(__OpenBSD__) +# define Q_OS_OPENBSD +# define Q_OS_BSD4 +#elif defined(__bsdi__) +# define Q_OS_BSDI +# define Q_OS_BSD4 +#elif defined(__sgi) +# define Q_OS_IRIX +#elif defined(__osf__) +# define Q_OS_OSF +#elif defined(_AIX) +# define Q_OS_AIX +#elif defined(__Lynx__) +# define Q_OS_LYNX +#elif defined(__GNU_HURD__) +# define Q_OS_HURD +#elif defined(__DGUX__) +# define Q_OS_DGUX +#elif defined(__QNXNTO__) +# define Q_OS_QNX6 +#elif defined(__QNX__) +# define Q_OS_QNX +#elif defined(_SEQUENT_) +# define Q_OS_DYNIX +#elif defined(_SCO_DS) /* SCO OpenServer 5 */ +# define Q_OS_SCO +#elif defined(__UNIXWARE__) /* UnixWare 7 + GCC, Open UNIX 8 + GCC */ +# define Q_OS_UNIXWARE +# define Q_OS_UNIXWARE7 +#elif defined(__USLC__) /* UnixWare 7 + UDK, Open UNIX 8 + OUDK */ +# define Q_OS_UNIXWARE +# define Q_OS_UNIXWARE7 +#else +# error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" +#endif + +#if defined(Q_OS_MAC9) || defined(Q_OS_MACX) +# define Q_OS_MAC +#endif + +#if defined(Q_OS_MAC9) || defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) +# undef Q_OS_UNIX +#elif !defined(Q_OS_UNIX) +# define Q_OS_UNIX +#endif + + +/* + The compiler, must be one of: (Q_CC_x) + + SYM - Symantec C++ for both PC and Macintosh + MPW - MPW C++ + MWERKS - Metrowerks CodeWarrior + MSVC - Microsoft Visual C/C++ + BOR - Borland/Turbo C++ + WAT - Watcom C++ + GNU - GNU C++ + COMEAU - Comeau C++ + EDG - Edison Design Group C++ + OC - CenterLine C++ + SUN - Sun WorkShop, Forte Developer, or Sun ONE Studio C++ + MIPS - MIPSpro C++ + DEC - DEC C++ + HP - HPUX C++ + HPACC - HPUX ANSI C++ + USLC - SCO OUDK, UDK, and UnixWare 2.X C++ + CDS - Reliant C++ + KAI - KAI C++ + INTEL - Intel C++ + HIGHC - MetaWare High C/C++ + PGI - Portland Group C++ + GHS - Green Hills Optimizing C++ Compilers + + Should be sorted most to least authoritative. +*/ + +/* Symantec C++ is now Digital Mars */ +#if defined(__DMC__) || defined(__SC__) +# define Q_CC_SYM +/* "explicit" semantics implemented in 8.1e but keyword recognized since 7.5 */ +# if defined(__SC__) && __SC__ < 0x750 +# define Q_NO_EXPLICIT_KEYWORD +# endif +# define Q_NO_USING_KEYWORD +# if !defined(_CPPUNWIND) +# define Q_NO_EXCEPTIONS +# endif + +#elif defined(applec) +# define Q_CC_MPW +# define Q_NO_BOOL_TYPE +# define Q_NO_EXPLICIT_KEYWORD +# define Q_NO_USING_KEYWORD + +#elif defined(__MWERKS__) +# define Q_CC_MWERKS +/* "explicit" recognized since 4.0d1 */ +# define QMAC_PASCAL pascal +# define Q_NO_USING_KEYWORD /* ### check "using" status */ + +#elif defined(_MSC_VER) +# define Q_CC_MSVC +/* proper support of bool for _MSC_VER >= 1100 */ +# define Q_CANNOT_DELETE_CONSTANT +# define Q_INLINE_TEMPLATES inline +/* Visual C++.Net issues for _MSC_VER >= 1300 */ +# if _MSC_VER >= 1300 +# define Q_CC_MSVC_NET +# define Q_TYPENAME +# endif +# define Q_NO_USING_KEYWORD /* ### check "using" status */ + +#elif defined(__BORLANDC__) || defined(__TURBOC__) +# define Q_CC_BOR +# if __BORLANDC__ < 0x502 +# define Q_NO_BOOL_TYPE +# define Q_NO_EXPLICIT_KEYWORD +# endif +# define Q_NO_USING_KEYWORD /* ### check "using" status */ + +#elif defined(__WATCOMC__) +# define Q_CC_WAT +# if defined(Q_OS_QNX4) +/* compiler flags */ +# define Q_TYPENAME +# define Q_NO_BOOL_TYPE +# define Q_CANNOT_DELETE_CONSTANT +# define mutable +/* ??? */ +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +/* no template classes in QVariant */ +# define QT_NO_TEMPLATE_VARIANT +/* Wcc does not fill in functions needed by valuelists, maps, and + valuestacks implicitly */ +# define Q_FULL_TEMPLATE_INSTANTIATION +/* can we just compare the structures? */ +# define Q_FULL_TEMPLATE_INSTANTIATION_MEMCMP +/* these are not useful to our customers */ +# define QT_QWS_NO_SHM +# define QT_NO_QWS_MULTIPROCESS +# define QT_NO_SQL +# define QT_NO_QWS_CURSOR +# endif + +#elif defined(__GNUC__) +# define Q_CC_GNU +# define Q_C_CALLBACKS +# if __GNUC__ == 2 && __GNUC_MINOR__ <= 7 +# define Q_FULL_TEMPLATE_INSTANTIATION +# endif +/* GCC 2.95 knows "using" but does not support it correctly */ +# if __GNUC__ == 2 && __GNUC_MINOR__ <= 95 +# define Q_NO_USING_KEYWORD +# endif +# if (defined(__arm__) || defined(__ARMEL__)) && !defined(QT_MOC_CPP) +# define Q_PACKED __attribute__ ((packed)) +# endif +# if !defined(__EXCEPTIONS) +# define Q_NO_EXCEPTIONS +# endif + +/* IBM compiler versions are a bit messy. There are actually two products: + the C product, and the C++ product. The C++ compiler is always packaged + with the latest version of the C compiler. Version numbers do not always + match. This little table (I'm not sure it's accurate) should be helpful: + + C++ product C product + + C Set 3.1 C Compiler 3.0 + ... ... + C++ Compiler 3.6.6 C Compiler 4.3 + ... ... + Visual Age C++ 4.0 ... + ... ... + Visual Age C++ 5.0 C Compiler 5.0 + + Now: + __xlC__ is the version of the C compiler in hexadecimal notation + is only an approximation of the C++ compiler version + __IBMCPP__ is the version of the C++ compiler in decimal notation + but it is not defined on older compilers like C Set 3.1 */ +#elif defined(__xlC__) +# define Q_CC_XLC +# define Q_FULL_TEMPLATE_INSTANTIATION +# if __xlC__ < 0x400 +# define Q_NO_BOOL_TYPE +# define Q_NO_EXPLICIT_KEYWORD +# define Q_NO_USING_KEYWORD +# define Q_TYPENAME +# define Q_INLINE_TEMPLATES inline +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +# define Q_CANNOT_DELETE_CONSTANT +# endif + +/* Older versions of DEC C++ do not define __EDG__ or __EDG - observed + on DEC C++ V5.5-004. New versions do define __EDG__ - observed on + Compaq C++ V6.3-002. + This compiler is different enough from other EDG compilers to handle + it separately anyway. */ +#elif defined(__DECCXX) +# define Q_CC_DEC +/* Compaq C++ V6 compilers are EDG-based but I'm not sure about older + DEC C++ V5 compilers. */ +# if defined(__EDG__) +# define Q_CC_EDG +# endif +/* Compaq have disabled EDG's _BOOL macro and use _BOOL_EXISTS instead + - observed on Compaq C++ V6.3-002. + In any case versions prior to Compaq C++ V6.0-005 do not have bool. */ +# if !defined(_BOOL_EXISTS) +# define Q_NO_BOOL_TYPE +# endif +/* Spurious (?) error messages observed on Compaq C++ V6.5-014. */ +# define Q_NO_USING_KEYWORD +/* Apply to all versions prior to Compaq C++ V6.0-000 - observed on + DEC C++ V5.5-004. */ +# if __DECCXX_VER < 60060000 +# define Q_TYPENAME +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +# define Q_CANNOT_DELETE_CONSTANT +# endif +/* avoid undefined symbol problems with out-of-line template members */ +# define Q_INLINE_TEMPLATES inline + +/* Compilers with EDG front end are similar. To detect them we test: + __EDG documented by SGI, observed on MIPSpro 7.3.1.1 and KAI C++ 4.0b + __EDG__ documented in EDG online docs, observed on Compaq C++ V6.3-002 */ +#elif defined(__EDG) || defined(__EDG__) +# define Q_CC_EDG +/* From the EDG documentation (does not seem to apply to Compaq C++): + _BOOL + Defined in C++ mode when bool is a keyword. The name of this + predefined macro is specified by a configuration flag. _BOOL + is the default. + __BOOL_DEFINED + Defined in Microsoft C++ mode when bool is a keyword. */ +# if !defined(_BOOL) && !defined(__BOOL_DEFINED) +# define Q_NO_BOOL_TYPE +# endif + +/* The Portland Group compiler is based on EDG and does define __EDG__ */ +# if defined(__COMO__) +# define Q_CC_COMEAU +# define Q_C_CALLBACKS + +/* Using the `using' keyword avoids KAI C++ warnings */ +# elif defined(__KCC) +# define Q_CC_KAI +# if !defined(_EXCEPTIONS) +# define Q_NO_EXCEPTIONS +# endif + +/* Using the `using' keyword avoids Intel C++ warnings */ +# elif defined(__INTEL_COMPILER) +# define Q_CC_INTEL +# if !defined(__EXCEPTIONS) +# define Q_NO_EXCEPTIONS +# endif + +/* The Portland Group compiler is based on EDG and does define __EDG__ */ +# elif defined(__PGI) +# define Q_CC_PGI +# if !defined(__EXCEPTIONS) +# define Q_NO_EXCEPTIONS +# endif + +/* Never tested! */ +# elif defined(__ghs) +# define Q_CC_GHS + +/* The UnixWare 7 UDK compiler is based on EDG and does define __EDG__ */ +# elif defined(__USLC__) && defined(__SCO_VERSION__) +# define Q_CC_USLC +# define Q_NO_USING_KEYWORD /* ### check "using" status */ + +/* Never tested! */ +# elif defined(CENTERLINE_CLPP) || defined(OBJECTCENTER) +# define Q_CC_OC +# define Q_NO_USING_KEYWORD + +/* CDS++ is not documented to define __EDG__ or __EDG in the Reliant + documentation but we suppose it does, in any case it does follow + conventions like _BOOL */ +# elif defined(sinix) +# define Q_CC_CDS +# define Q_NO_USING_KEYWORD +# if defined(__cplusplus) && (__cplusplus < 2) /* Cfront C++ mode */ +# define Q_NO_EXCEPTIONS +# endif + +/* The MIPSpro compiler in o32 mode is based on EDG but disables features + such as template specialization nevertheless */ +# elif defined(__sgi) +# define Q_CC_MIPS +# if defined(_MIPS_SIM) && (_MIPS_SIM == _ABIO32) /* o32 ABI */ +# define Q_TYPENAME +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +# define Q_STRICT_INLINING_RULES +# elif defined(_COMPILER_VERSION) && (_COMPILER_VERSION < 730) /* 7.2 */ +# define Q_TYPENAME +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +# endif +# define Q_NO_USING_KEYWORD /* ### check "using" status */ +# endif + +/* The older UnixWare 2.X compiler? */ +#elif defined(__USLC__) && !defined(__SCO_VERSION__) +# define Q_CC_USLC +# define Q_NO_BOOL_TYPE +# define Q_NO_EXPLICIT_KEYWORD +# define Q_NO_USING_KEYWORD + +/* Never tested! */ +#elif defined(__HIGHC__) +# define Q_CC_HIGHC + +#elif defined(__SUNPRO_CC) +# define Q_CC_SUN +/* 5.0 compiler or better + 'bool' is enabled by default but can be disabled using -features=nobool + in which case _BOOL is not defined + this is the default in 4.2 compatibility mode triggered by -compat=4 */ +# if __SUNPRO_CC >= 0x500 +# if !defined(_BOOL) +# define Q_NO_BOOL_TYPE +# endif +# if defined(__SUNPRO_CC_COMPAT) && (__SUNPRO_CC_COMPAT <= 4) +# define Q_NO_USING_KEYWORD +# endif +# define Q_C_CALLBACKS +/* 4.2 compiler or older */ +# else +# define Q_NO_BOOL_TYPE +# define Q_NO_EXPLICIT_KEYWORD +# define Q_NO_USING_KEYWORD +# endif + +#elif defined(Q_OS_HPUX) +/* __HP_aCC was not defined in first aCC releases */ +# if defined(__HP_aCC) || __cplusplus >= 199707L +# define Q_CC_HPACC +# else +# define Q_CC_HP +# define Q_NO_BOOL_TYPE +# define Q_FULL_TEMPLATE_INSTANTIATION +# define Q_BROKEN_TEMPLATE_SPECIALIZATION +# define Q_NO_EXPLICIT_KEYWORD +# endif +# define Q_NO_USING_KEYWORD /* ### check "using" status */ + +#else +# error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com" +#endif + +#ifndef Q_PACKED +# define Q_PACKED +#endif + + +/* + The window system, must be one of: (Q_WS_x) + + MACX - Mac OS X + MAC9 - Mac OS 9 + QWS - Qt/Embedded + WIN32 - Windows + X11 - X Window System + PM - unsupported + WIN16 - unsupported +*/ + +#if defined(Q_OS_MAC9) +# define Q_WS_MAC9 +#elif defined(Q_OS_MSDOS) +# define Q_WS_WIN16 +# error "Qt requires Win32 and does not work with Windows 3.x" +#elif defined(_WIN32_X11_) +# define Q_WS_X11 +#elif defined(Q_OS_WIN32) +# define Q_WS_WIN32 +# if defined(Q_OS_WIN64) +# define Q_WS_WIN64 +# endif +#elif defined(Q_OS_OS2) +# define Q_WS_PM +# error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" +#elif defined(Q_OS_UNIX) +# if defined(QWS) +# define Q_WS_QWS +# elif defined(Q_OS_MACX) +# define Q_WS_MACX +# else +# define Q_WS_X11 +# endif +#endif +#if defined(Q_OS_MAC) && !defined(QMAC_PASCAL) +# define QMAC_PASCAL +#endif + +#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32) +# define Q_WS_WIN +#endif + +#if (defined(Q_WS_MAC9) || defined(Q_WS_MACX)) && !defined(Q_WS_QWS) && !defined(Q_WS_X11) +# define Q_WS_MAC +#endif + + +/* + Some classes do not permit copies to be made of an object. + These classes contains a private copy constructor and operator= + to disable copying (the compiler gives an error message). + Undefine Q_DISABLE_COPY to turn off this checking. +*/ + +#define Q_DISABLE_COPY + +#if defined(__cplusplus) + + +// +// Useful type definitions for Qt +// + +#if defined(Q_NO_BOOL_TYPE) +#if defined(Q_CC_HP) +// bool is an unsupported reserved keyword in later versions +#define bool int +#else +typedef int bool; +#endif +#endif + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned uint; +typedef unsigned long ulong; +typedef char *pchar; +typedef uchar *puchar; +typedef const char *pcchar; + + +// +// Constant bool values +// + +#ifndef TRUE +const bool FALSE = 0; +const bool TRUE = !0; +#endif +#if defined(__WATCOMC__) +# if defined(Q_OS_QNX4) +const bool false = FALSE; +const bool true = TRUE; +# endif +#endif + + +// +// Use the "explicit" keyword on platforms that support it. +// + +#if !defined(Q_NO_EXPLICIT_KEYWORD) +# define Q_EXPLICIT explicit +#else +# define Q_EXPLICIT +#endif + + +// +// Workaround for static const members on MSVC++. +// + +#if defined(Q_CC_MSVC) +# define QT_STATIC_CONST static +# define QT_STATIC_CONST_IMPL +#else +# define QT_STATIC_CONST static const +# define QT_STATIC_CONST_IMPL const +#endif + + +// +// Utility macros and inline functions +// + +#define QMAX(a, b) ((b) < (a) ? (a) : (b)) +#define QMIN(a, b) ((a) < (b) ? (a) : (b)) +#define QABS(a) ((a) >= 0 ? (a) : -(a)) + +inline int qRound( double d ) +{ + return d >= 0.0 ? int(d + 0.5) : int( d - ((int)d-1) + 0.5 ) + ((int)d-1); +} + + +// +// Size-dependent types (architechture-dependent byte order) +// + +#if !defined(QT_CLEAN_NAMESPACE) +// source compatibility with Qt 1.x +typedef signed char INT8; // 8 bit signed +typedef unsigned char UINT8; // 8 bit unsigned +typedef short INT16; // 16 bit signed +typedef unsigned short UINT16; // 16 bit unsigned +typedef int INT32; // 32 bit signed +typedef unsigned int UINT32; // 32 bit unsigned +#endif + +typedef signed char Q_INT8; // 8 bit signed +typedef unsigned char Q_UINT8; // 8 bit unsigned +typedef short Q_INT16; // 16 bit signed +typedef unsigned short Q_UINT16; // 16 bit unsigned +typedef int Q_INT32; // 32 bit signed +typedef unsigned int Q_UINT32; // 32 bit unsigned +#if defined(Q_OS_WIN64) +// LLP64 64-bit model on Windows +typedef __int64 Q_LONG; // word up to 64 bit signed +typedef unsigned __int64 Q_ULONG; // word up to 64 bit unsigned +#else +// LP64 64-bit model on Linux +typedef long Q_LONG; +typedef unsigned long Q_ULONG; +#endif + +#if !defined(QT_CLEAN_NAMESPACE) +// mininum size of 64 bits is not guaranteed +#define Q_INT64 Q_LONG +#define Q_UINT64 Q_ULONG +#endif + +#if defined(Q_OS_MACX) && !defined(QT_LARGEFILE_SUPPORT) +# define QT_LARGEFILE_SUPPORT 64 +#endif +#if defined(QT_LARGEFILE_SUPPORT) + typedef unsigned long long QtOffset; +#else + typedef Q_ULONG QtOffset; +#endif + + +// +// Data stream functions is provided by many classes (defined in qdatastream.h) +// + +class QDataStream; + + +// +// Feature subsetting +// +// Note that disabling some features will produce a libqt that is not +// compatible with other libqt builds. Such modifications are only +// supported on Qt/Embedded where reducing the library size is important +// and where the application-suite is often a fixed set. +// + +#if !defined(QT_MOC) +#if defined(QCONFIG_LOCAL) +#include <qconfig-local.h> +#elif defined(QCONFIG_MINIMAL) +#include <qconfig-minimal.h> +#elif defined(QCONFIG_SMALL) +#include <qconfig-small.h> +#elif defined(QCONFIG_MEDIUM) +#include <qconfig-medium.h> +#elif defined(QCONFIG_LARGE) +#include <qconfig-large.h> +#else // everything... +#include <qconfig.h> +#endif +#endif + + +#ifndef QT_BUILD_KEY +#define QT_BUILD_KEY "unspecified" +#endif + +// prune to local config +#include "qmodules.h" +#ifndef QT_MODULE_ICONVIEW +# define QT_NO_ICONVIEW +#endif +#ifndef QT_MODULE_WORKSPACE +# define QT_NO_WORKSPACE +#endif +#ifndef QT_MODULE_NETWORK +#define QT_NO_NETWORK +#endif +#ifndef QT_MODULE_CANVAS +# define QT_NO_CANVAS +#endif +#ifndef QT_MODULE_TABLE +#define QT_NO_TABLE +#endif +#ifndef QT_MODULE_XML +# define QT_NO_XML +#endif +#ifndef QT_MODULE_OPENGL +# define QT_NO_OPENGL +#endif +#if !defined(QT_MODULE_SQL) +# define QT_NO_SQL +#endif + +#if defined(Q_WS_MAC9) +//No need for menu merging +# ifndef QMAC_QMENUBAR_NO_MERGE +# define QMAC_QMENUBAR_NO_MERGE +# endif +//Mac9 does not use quartz +# ifndef QMAC_NO_QUARTZ +# define QMAC_NO_QUARTZ +# endif +# ifndef QMAC_QMENUBAR_NO_EVENT +# define QMAC_QMENUBAR_NO_EVENT +# endif +#endif +#if defined(Q_WS_MACX) //for no nobody uses quartz, just putting in first level hooks +# ifndef QMAC_NO_QUARTZ +# define QMAC_NO_QUARTZ +# endif +# ifndef QMAC_QMENUBAR_NO_EVENT +# define QMAC_QMENUBAR_NO_EVENT +# endif +#endif + +#ifndef QT_H +#include <qfeatures.h> +#endif // QT_H + + +// +// Create Qt DLL if QT_DLL is defined (Windows only) +// + +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) +# if defined(QT_NODLL) +# undef QT_MAKEDLL +# undef QT_DLL +# elif defined(QT_MAKEDLL) /* create a Qt DLL library */ +# if defined(QT_DLL) +# undef QT_DLL +# endif +# define Q_EXPORT __declspec(dllexport) +# define Q_TEMPLATEDLL +# define Q_TEMPLATE_EXTERN +# undef Q_DISABLE_COPY /* avoid unresolved externals */ +# elif defined(QT_DLL) /* use a Qt DLL library */ +# define Q_EXPORT __declspec(dllimport) +# define Q_TEMPLATEDLL +# ifndef Q_TEMPLATE_EXTERN +# if defined(Q_CC_MSVC) +# define Q_TEMPLATE_EXTERN /*extern*/ //### too many warnings, even though disabled +# else +# define Q_TEMPLATE_EXTERN +# endif +# endif +# undef Q_DISABLE_COPY /* avoid unresolved externals */ +# endif +#else +# undef QT_MAKEDLL /* ignore these for other platforms */ +# undef QT_DLL +#endif + +#ifndef Q_EXPORT +# define Q_EXPORT +#endif + + +// +// Some platform specific stuff +// + +#if defined(Q_WS_WIN) +extern Q_EXPORT bool qt_winunicode; +#endif + + +// +// System information +// + +Q_EXPORT const char *qVersion(); +Q_EXPORT bool qSysInfo( int *wordSize, bool *bigEndian ); +#if defined(Q_WS_WIN) +Q_EXPORT int qWinVersion(); +#if defined(UNICODE) +#define QT_WA( uni, ansi ) if ( qt_winunicode ) { uni } else { ansi } +#define QT_WA_INLINE( uni, ansi ) ( qt_winunicode ? uni : ansi ) +#else +#define QT_WA( uni, ansi ) ansi +#define QT_WA_INLINE( uni, ansi ) ansi +#endif +#endif + +#ifdef Q_OS_TEMP +#ifdef QT_WA +#undef QT_WA +#undef QT_WA_INLINE +#endif +#define QT_WA( uni, ansi ) uni +#define QT_WA_INLINE( uni, ansi ) ( uni ) +#endif + +#ifndef Q_INLINE_TEMPLATES +# define Q_INLINE_TEMPLATES +#endif + +#ifndef Q_TYPENAME +# define Q_TYPENAME typename +#endif + +// +// Use to avoid "unused parameter" warnings +// + +#define Q_UNUSED(x) (void)x; + +// +// Debugging and error handling +// + +#if !defined(QT_NO_CHECK) +# define QT_CHECK_STATE // check state of objects etc. +# define QT_CHECK_RANGE // check range of indexes etc. +# define QT_CHECK_NULL // check null pointers +# define QT_CHECK_MATH // check math functions +#endif + +#if !defined(QT_NO_DEBUG) && !defined(QT_DEBUG) +# define QT_DEBUG // display debug messages +# if !defined(QT_NO_COMPAT) // compatibility with Qt 2 +# if !defined(NO_DEBUG) && !defined(DEBUG) +# if !defined(Q_OS_MACX) // clash with MacOS X headers +# define DEBUG +# endif +# endif +# endif +#endif + + +Q_EXPORT void qDebug( const char *, ... ) // print debug message +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void qWarning( const char *, ... ) // print warning message +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void qFatal( const char *, ... ) // print fatal message and exit +#if defined(Q_CC_GNU) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void qSystemWarning( const char *, int code = -1 ); + +#if !defined(QT_CLEAN_NAMESPACE) // compatibility with Qt 1 + +Q_EXPORT void debug( const char *, ... ) // print debug message +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void warning( const char *, ... ) // print warning message +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void fatal( const char *, ... ) // print fatal message and exit +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +#endif // QT_CLEAN_NAMESPACE + + +#if !defined(Q_ASSERT) +# if defined(QT_CHECK_STATE) +# if defined(QT_FATAL_ASSERT) +# define Q_ASSERT(x) ((x) ? (void)0 : qFatal("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__)) +# else +# define Q_ASSERT(x) ((x) ? (void)0 : qWarning("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__)) +# endif +# else +# define Q_ASSERT(x) +# endif +#endif + +#if !defined(QT_NO_COMPAT) // compatibility with Qt 2 +# if !defined(ASSERT) +# if !defined(Q_OS_TEMP) +# define ASSERT(x) Q_ASSERT(x) +# endif +# endif +#endif // QT_NO_COMPAT + + +Q_EXPORT bool qt_check_pointer( bool c, const char *, int ); + +#if defined(QT_CHECK_NULL) +# define Q_CHECK_PTR(p) (qt_check_pointer((p)==0,__FILE__,__LINE__)) +#else +# define Q_CHECK_PTR(p) +#endif + +#if !defined(QT_NO_COMPAT) // compatibility with Qt 2 +# if !defined(CHECK_PTR) +# define CHECK_PTR(x) Q_CHECK_PTR(x) +# endif +#endif // QT_NO_COMPAT + +enum QtMsgType { QtDebugMsg, QtWarningMsg, QtFatalMsg }; + +typedef void (*QtMsgHandler)(QtMsgType, const char *); +Q_EXPORT QtMsgHandler qInstallMsgHandler( QtMsgHandler ); + +#if !defined(QT_NO_COMPAT) // compatibility with Qt 2 +typedef QtMsgHandler msg_handler; +#endif // QT_NO_COMPAT + +Q_EXPORT void qSuppressObsoleteWarnings( bool = TRUE ); + +Q_EXPORT void qObsolete( const char *obj, const char *oldfunc, + const char *newfunc ); +Q_EXPORT void qObsolete( const char *obj, const char *oldfunc ); +Q_EXPORT void qObsolete( const char *message ); + + +// +// Install paths from configure +// + +Q_EXPORT const char *qInstallPath(); +Q_EXPORT const char *qInstallPathDocs(); +Q_EXPORT const char *qInstallPathHeaders(); +Q_EXPORT const char *qInstallPathLibs(); +Q_EXPORT const char *qInstallPathBins(); +Q_EXPORT const char *qInstallPathPlugins(); +Q_EXPORT const char *qInstallPathData(); + +#endif // __cplusplus + +#endif // QGLOBAL_H + +// +// Avoid some particularly useless warnings from some stupid compilers. +// To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out +// the line "#define QT_NO_WARNINGS" +// + +#if !defined(QT_CC_WARNINGS) +# define QT_NO_WARNINGS +#endif +#if defined(QT_NO_WARNINGS) +# if defined(Q_CC_MSVC) +# pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data +# pragma warning(disable: 4275) // non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' +# pragma warning(disable: 4514) // unreferenced inline/local function has been removed +# pragma warning(disable: 4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning) +# pragma warning(disable: 4097) // typedef-name 'identifier1' used as synonym for class-name 'identifier2' +# pragma warning(disable: 4706) // assignment within conditional expression +# pragma warning(disable: 4786) // truncating debug info after 255 characters +# pragma warning(disable: 4660) // template-class specialization 'identifier' is already instantiated +# pragma warning(disable: 4355) // 'this' : used in base member initializer list +# pragma warning(disable: 4231) // nonstandard extension used : 'extern' before template explicit instantiation +# elif defined(Q_CC_BOR) +# pragma option -w-inl +# pragma option -w-aus +# pragma warn -inl +# pragma warn -pia +# pragma warn -ccc +# pragma warn -rch +# pragma warn -sig +# elif defined(Q_CC_MWERKS) +# pragma warn_possunwant off +# endif +#endif diff --git a/qmake/include/qgvector.h b/qmake/include/qgvector.h new file mode 100644 index 0000000..6e8bdfc --- a/dev/null +++ b/qmake/include/qgvector.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QGVector class +** +** Created : 930907 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QGVECTOR_H +#define QGVECTOR_H + +#ifndef QT_H +#include "qptrcollection.h" +#endif // QT_H + + +class Q_EXPORT QGVector : public QPtrCollection // generic vector +{ +friend class QGList; // needed by QGList::toVector +public: +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream & ); // read vector from stream + QDataStream &write( QDataStream & ) const; // write vector to stream +#endif + virtual int compareItems( Item, Item ); + +protected: + QGVector(); // create empty vector + QGVector( uint size ); // create vector with nullptrs + QGVector( const QGVector &v ); // make copy of other vector + ~QGVector(); + + QGVector &operator=( const QGVector &v ); // assign from other vector + bool operator==( const QGVector &v ) const; + + Item *data() const { return vec; } + uint size() const { return len; } + uint count() const { return numItems; } + + bool insert( uint index, Item ); // insert item at index + bool remove( uint index ); // remove item + Item take( uint index ); // take out item + + void clear(); // clear vector + bool resize( uint newsize ); // resize vector + + bool fill( Item, int flen ); // resize and fill vector + + void sort(); // sort vector + int bsearch( Item ) const; // binary search (when sorted) + + int findRef( Item, uint index ) const; // find exact item in vector + int find( Item, uint index ) const; // find equal item in vector + uint containsRef( Item ) const; // get number of exact matches + uint contains( Item ) const; // get number of equal matches + + Item at( uint index ) const // return indexed item + { +#if defined(QT_CHECK_RANGE) + if ( index >= len ) + warningIndexRange( index ); +#endif + return vec[index]; + } + + bool insertExpand( uint index, Item ); // insert, expand if necessary + + void toList( QGList * ) const; // put items in list + +#ifndef QT_NO_DATASTREAM + virtual QDataStream &read( QDataStream &, Item & ); + virtual QDataStream &write( QDataStream &, Item ) const; +#endif +private: + Item *vec; + uint len; + uint numItems; + + static void warningIndexRange( uint ); +}; + + +/***************************************************************************** + QGVector stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator>>( QDataStream &, QGVector & ); +Q_EXPORT QDataStream &operator<<( QDataStream &, const QGVector & ); +#endif + +#endif // QGVECTOR_H diff --git a/qmake/include/qintdict.h b/qmake/include/qintdict.h new file mode 100644 index 0000000..b4cb223 --- a/dev/null +++ b/qmake/include/qintdict.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QIntDict template class +** +** Created : 940624 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QINTDICT_H +#define QINTDICT_H + +#ifndef QT_H +#include "qgdict.h" +#endif // QT_H + +template<class type> +class QIntDict +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGDict +#endif +{ +public: + QIntDict(int size=17) : QGDict(size,IntKey,0,0) {} + QIntDict( const QIntDict<type> &d ) : QGDict(d) {} + ~QIntDict() { clear(); } + QIntDict<type> &operator=(const QIntDict<type> &d) + { return (QIntDict<type>&)QGDict::operator=(d); } + uint count() const { return QGDict::count(); } + uint size() const { return QGDict::size(); } + bool isEmpty() const { return QGDict::count() == 0; } + void insert( long k, const type *d ) + { QGDict::look_int(k,(Item)d,1); } + void replace( long k, const type *d ) + { QGDict::look_int(k,(Item)d,2); } + bool remove( long k ) { return QGDict::remove_int(k); } + type *take( long k ) { return (type*)QGDict::take_int(k); } + type *find( long k ) const + { return (type *)((QGDict*)this)->QGDict::look_int(k,0,0); } + type *operator[]( long k ) const + { return (type *)((QGDict*)this)->QGDict::look_int(k,0,0); } + void clear() { QGDict::clear(); } + void resize( uint n ) { QGDict::resize(n); } + void statistics() const { QGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); + virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QIntDict<void>::deleteItem( QPtrCollection::Item ) +{ +} +#endif + +template<class type> inline void QIntDict<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type*)d; +} + +template<class type> +class QIntDictIterator : public QGDictIterator +{ +public: + QIntDictIterator(const QIntDict<type> &d) :QGDictIterator((QGDict &)d) {} + ~QIntDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)QGDictIterator::toFirst(); } + operator type *() const { return (type *)QGDictIterator::get(); } + type *current() const { return (type *)QGDictIterator::get(); } + long currentKey() const { return QGDictIterator::getKeyInt(); } + type *operator()() { return (type *)QGDictIterator::operator()(); } + type *operator++() { return (type *)QGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j);} +}; + +#endif // QINTDICT_H diff --git a/qmake/include/qiodevice.h b/qmake/include/qiodevice.h new file mode 100644 index 0000000..cb83463 --- a/dev/null +++ b/qmake/include/qiodevice.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QIODevice class +** +** Created : 940913 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QIODEVICE_H +#define QIODEVICE_H + +#ifndef QT_H +#include "qglobal.h" +#include "qcstring.h" +#endif // QT_H + + +// IO device access types + +#define IO_Direct 0x0100 // direct access device +#define IO_Sequential 0x0200 // sequential access device +#define IO_Combined 0x0300 // combined direct/sequential +#define IO_TypeMask 0x0f00 + +// IO handling modes + +#define IO_Raw 0x0040 // raw access (not buffered) +#define IO_Async 0x0080 // asynchronous mode + +// IO device open modes + +#define IO_ReadOnly 0x0001 // readable device +#define IO_WriteOnly 0x0002 // writable device +#define IO_ReadWrite 0x0003 // read+write device +#define IO_Append 0x0004 // append +#define IO_Truncate 0x0008 // truncate device +#define IO_Translate 0x0010 // translate CR+LF +#define IO_ModeMask 0x00ff + +// IO device state + +#define IO_Open 0x1000 // device is open +#define IO_StateMask 0xf000 + +// IO device status + +#define IO_Ok 0 +#define IO_ReadError 1 // read error +#define IO_WriteError 2 // write error +#define IO_FatalError 3 // fatal unrecoverable error +#define IO_ResourceError 4 // resource limitation +#define IO_OpenError 5 // cannot open device +#define IO_ConnectError 5 // cannot connect to device +#define IO_AbortError 6 // abort error +#define IO_TimeOutError 7 // time out +#define IO_UnspecifiedError 8 // unspecified error + + +class Q_EXPORT QIODevice +{ +public: +#if defined(QT_ABI_64BITOFFSET) + typedef QtOffset Offset; +#else + typedef Q_ULONG Offset; +#endif + + QIODevice(); + virtual ~QIODevice(); + + int flags() const { return ioMode; } + int mode() const { return ioMode & IO_ModeMask; } + int state() const { return ioMode & IO_StateMask; } + + bool isDirectAccess() const { return ((ioMode & IO_Direct) == IO_Direct); } + bool isSequentialAccess() const { return ((ioMode & IO_Sequential) == IO_Sequential); } + bool isCombinedAccess() const { return ((ioMode & IO_Combined) == IO_Combined); } + bool isBuffered() const { return ((ioMode & IO_Raw) != IO_Raw); } + bool isRaw() const { return ((ioMode & IO_Raw) == IO_Raw); } + bool isSynchronous() const { return ((ioMode & IO_Async) != IO_Async); } + bool isAsynchronous() const { return ((ioMode & IO_Async) == IO_Async); } + bool isTranslated() const { return ((ioMode & IO_Translate) == IO_Translate); } + bool isReadable() const { return ((ioMode & IO_ReadOnly) == IO_ReadOnly); } + bool isWritable() const { return ((ioMode & IO_WriteOnly) == IO_WriteOnly); } + bool isReadWrite() const { return ((ioMode & IO_ReadWrite) == IO_ReadWrite); } + bool isInactive() const { return state() == 0; } + bool isOpen() const { return state() == IO_Open; } + + int status() const { return ioSt; } + void resetStatus() { ioSt = IO_Ok; } + + virtual bool open( int mode ) = 0; + virtual void close() = 0; + virtual void flush() = 0; + + virtual Offset size() const = 0; + virtual Offset at() const; + virtual bool at( Offset ); + virtual bool atEnd() const; + bool reset() { return at(0); } + + virtual Q_LONG readBlock( char *data, Q_ULONG maxlen ) = 0; + virtual Q_LONG writeBlock( const char *data, Q_ULONG len ) = 0; + virtual Q_LONG readLine( char *data, Q_ULONG maxlen ); + Q_LONG writeBlock( const QByteArray& data ); + virtual QByteArray readAll(); + + virtual int getch() = 0; + virtual int putch( int ) = 0; + virtual int ungetch( int ) = 0; + +protected: + void setFlags( int f ) { ioMode = f; } + void setType( int ); + void setMode( int ); + void setState( int ); + void setStatus( int ); + Offset ioIndex; + +private: + int ioMode; + int ioSt; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QIODevice( const QIODevice & ); + QIODevice &operator=( const QIODevice & ); +#endif +}; + + +#endif // QIODEVICE_H diff --git a/qmake/include/qmap.h b/qmake/include/qmap.h new file mode 100644 index 0000000..269bd6b --- a/dev/null +++ b/qmake/include/qmap.h @@ -0,0 +1,883 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QMap class +** +** Created : 990406 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QMAP_H +#define QMAP_H + +#ifndef QT_H +#include "qglobal.h" +#include "qshared.h" +#include "qdatastream.h" +#include "qpair.h" +#include "qvaluelist.h" +#endif // QT_H + +#ifndef QT_NO_STL +#include <iterator> +#include <map> +#endif + +//#define QT_CHECK_MAP_RANGE + +struct Q_EXPORT QMapNodeBase +{ + enum Color { Red, Black }; + + QMapNodeBase* left; + QMapNodeBase* right; + QMapNodeBase* parent; + + Color color; + + QMapNodeBase* minimum() { + QMapNodeBase* x = this; + while ( x->left ) + x = x->left; + return x; + } + + QMapNodeBase* maximum() { + QMapNodeBase* x = this; + while ( x->right ) + x = x->right; + return x; + } +}; + + +template <class K, class T> +struct QMapNode : public QMapNodeBase +{ + QMapNode( const K& _key, const T& _data ) { data = _data; key = _key; } + QMapNode( const K& _key ) { key = _key; } + QMapNode( const QMapNode<K,T>& _n ) { key = _n.key; data = _n.data; } + QMapNode() { } + T data; + K key; +}; + + +template<class K, class T> +class QMapIterator +{ + public: + /** + * Typedefs + */ + typedef QMapNode< K, T >* NodePtr; +#ifndef QT_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; +#endif + typedef T value_type; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef T* pointer; + typedef T& reference; + + /** + * Variables + */ + QMapNode<K,T>* node; + + /** + * Functions + */ + QMapIterator() : node( 0 ) {} + QMapIterator( QMapNode<K,T>* p ) : node( p ) {} + QMapIterator( const QMapIterator<K,T>& it ) : node( it.node ) {} + + bool operator==( const QMapIterator<K,T>& it ) const { return node == it.node; } + bool operator!=( const QMapIterator<K,T>& it ) const { return node != it.node; } + T& operator*() { return node->data; } + const T& operator*() const { return node->data; } + // UDT for T = x* + // T* operator->() const { return &node->data; } + + const K& key() const { return node->key; } + T& data() { return node->data; } + const T& data() const { return node->data; } + +private: + int inc(); + int dec(); + +public: + QMapIterator<K,T>& operator++() { + inc(); + return *this; + } + + QMapIterator<K,T> operator++(int) { + QMapIterator<K,T> tmp = *this; + inc(); + return tmp; + } + + QMapIterator<K,T>& operator--() { + dec(); + return *this; + } + + QMapIterator<K,T> operator--(int) { + QMapIterator<K,T> tmp = *this; + dec(); + return tmp; + } +}; + +template <class K, class T> +Q_INLINE_TEMPLATES int QMapIterator<K,T>::inc() +{ + QMapNodeBase* tmp = node; + if ( tmp->right ) { + tmp = tmp->right; + while ( tmp->left ) + tmp = tmp->left; + } else { + QMapNodeBase* y = tmp->parent; + while (tmp == y->right) { + tmp = y; + y = y->parent; + } + if (tmp->right != y) + tmp = y; + } + node = (NodePtr)tmp; + return 0; +} + +template <class K, class T> +Q_INLINE_TEMPLATES int QMapIterator<K,T>::dec() +{ + QMapNodeBase* tmp = node; + if (tmp->color == QMapNodeBase::Red && + tmp->parent->parent == tmp ) { + tmp = tmp->right; + } else if (tmp->left != 0) { + QMapNodeBase* y = tmp->left; + while ( y->right ) + y = y->right; + tmp = y; + } else { + QMapNodeBase* y = tmp->parent; + while (tmp == y->left) { + tmp = y; + y = y->parent; + } + tmp = y; + } + node = (NodePtr)tmp; + return 0; +} + +template<class K, class T> +class QMapConstIterator +{ + public: + /** + * Typedefs + */ + typedef QMapNode< K, T >* NodePtr; +#ifndef QT_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; +#endif + typedef T value_type; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef const T* pointer; + typedef const T& reference; + + + /** + * Variables + */ + QMapNode<K,T>* node; + + /** + * Functions + */ + QMapConstIterator() : node( 0 ) {} + QMapConstIterator( QMapNode<K,T>* p ) : node( p ) {} + QMapConstIterator( const QMapConstIterator<K,T>& it ) : node( it.node ) {} + QMapConstIterator( const QMapIterator<K,T>& it ) : node( it.node ) {} + + bool operator==( const QMapConstIterator<K,T>& it ) const { return node == it.node; } + bool operator!=( const QMapConstIterator<K,T>& it ) const { return node != it.node; } + const T& operator*() const { return node->data; } + // UDT for T = x* + // const T* operator->() const { return &node->data; } + + const K& key() const { return node->key; } + const T& data() const { return node->data; } + +private: + int inc(); + int dec(); + +public: + QMapConstIterator<K,T>& operator++() { + inc(); + return *this; + } + + QMapConstIterator<K,T> operator++(int) { + QMapConstIterator<K,T> tmp = *this; + inc(); + return tmp; + } + + QMapConstIterator<K,T>& operator--() { + dec(); + return *this; + } + + QMapConstIterator<K,T> operator--(int) { + QMapConstIterator<K,T> tmp = *this; + dec(); + return tmp; + } +}; + +template <class K, class T> +Q_INLINE_TEMPLATES int QMapConstIterator<K,T>::inc() +{ + QMapNodeBase* tmp = node; + if ( tmp->right ) { + tmp = tmp->right; + while ( tmp->left ) + tmp = tmp->left; + } else { + QMapNodeBase* y = tmp->parent; + while (tmp == y->right) { + tmp = y; + y = y->parent; + } + if (tmp->right != y) + tmp = y; + } + node = (NodePtr)tmp; + return 0; +} + +template <class K, class T> +Q_INLINE_TEMPLATES int QMapConstIterator<K,T>::dec() +{ + QMapNodeBase* tmp = node; + if (tmp->color == QMapNodeBase::Red && + tmp->parent->parent == tmp ) { + tmp = tmp->right; + } else if (tmp->left != 0) { + QMapNodeBase* y = tmp->left; + while ( y->right ) + y = y->right; + tmp = y; + } else { + QMapNodeBase* y = tmp->parent; + while (tmp == y->left) { + tmp = y; + y = y->parent; + } + tmp = y; + } + node = (NodePtr)tmp; + return 0; +} + +class Q_EXPORT QMapPrivateBase : public QShared +{ +public: + QMapPrivateBase() { + node_count = 0; + } + QMapPrivateBase( const QMapPrivateBase* _map) { + node_count = _map->node_count; + } + + /** + * Implementations of basic tree algorithms + */ + void rotateLeft( QMapNodeBase* x, QMapNodeBase*& root); + void rotateRight( QMapNodeBase* x, QMapNodeBase*& root ); + void rebalance( QMapNodeBase* x, QMapNodeBase*& root ); + QMapNodeBase* removeAndRebalance( QMapNodeBase* z, QMapNodeBase*& root, + QMapNodeBase*& leftmost, + QMapNodeBase*& rightmost ); + + /** + * Variables + */ + int node_count; +}; + + +template <class Key, class T> +class QMapPrivate : public QMapPrivateBase +{ +public: + /** + * Typedefs + */ + typedef QMapIterator< Key, T > Iterator; + typedef QMapConstIterator< Key, T > ConstIterator; + typedef QMapNode< Key, T > Node; + typedef QMapNode< Key, T >* NodePtr; + + /** + * Functions + */ + QMapPrivate(); + QMapPrivate( const QMapPrivate< Key, T >* _map ); + ~QMapPrivate() { clear(); delete header; } + + NodePtr copy( NodePtr p ); + void clear(); + void clear( NodePtr p ); + + Iterator begin() { return Iterator( (NodePtr)(header->left ) ); } + Iterator end() { return Iterator( header ); } + ConstIterator begin() const { return ConstIterator( (NodePtr)(header->left ) ); } + ConstIterator end() const { return ConstIterator( header ); } + + ConstIterator find(const Key& k) const; + + void remove( Iterator it ) { + NodePtr del = (NodePtr) removeAndRebalance( it.node, header->parent, header->left, header->right ); + delete del; + --node_count; + } + +#ifdef QT_QMAP_DEBUG + void inorder( QMapNodeBase* x = 0, int level = 0 ){ + if ( !x ) + x = header->parent; + if ( x->left ) + inorder( x->left, level + 1 ); + //cout << level << " Key=" << key(x) << " Value=" << ((NodePtr)x)->data << endl; + if ( x->right ) + inorder( x->right, level + 1 ); + } +#endif + +#if 0 + Iterator insertMulti(const Key& v){ + QMapNodeBase* y = header; + QMapNodeBase* x = header->parent; + while (x != 0){ + y = x; + x = ( v < key(x) ) ? x->left : x->right; + } + return insert(x, y, v); + } +#endif + + Iterator insertSingle( const Key& k ); + Iterator insert( QMapNodeBase* x, QMapNodeBase* y, const Key& k ); + +protected: + /** + * Helpers + */ + const Key& key( QMapNodeBase* b ) const { return ((NodePtr)b)->key; } + + /** + * Variables + */ + NodePtr header; +}; + + +template <class Key, class T> +Q_INLINE_TEMPLATES QMapPrivate<Key,T>::QMapPrivate() { + header = new Node; + header->color = QMapNodeBase::Red; // Mark the header + header->parent = 0; + header->left = header->right = header; +} +template <class Key, class T> +Q_INLINE_TEMPLATES QMapPrivate<Key,T>::QMapPrivate( const QMapPrivate< Key, T >* _map ) : QMapPrivateBase( _map ) { + header = new Node; + header->color = QMapNodeBase::Red; // Mark the header + if ( _map->header->parent == 0 ) { + header->parent = 0; + header->left = header->right = header; + } else { + header->parent = copy( (NodePtr)(_map->header->parent) ); + header->parent->parent = header; + header->left = header->parent->minimum(); + header->right = header->parent->maximum(); + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::NodePtr QMapPrivate<Key,T>::copy( Q_TYPENAME QMapPrivate<Key,T>::NodePtr p ) +{ + if ( !p ) + return 0; + NodePtr n = new Node( *p ); + n->color = p->color; + if ( p->left ) { + n->left = copy( (NodePtr)(p->left) ); + n->left->parent = n; + } else { + n->left = 0; + } + if ( p->right ) { + n->right = copy( (NodePtr)(p->right) ); + n->right->parent = n; + } else { + n->right = 0; + } + return n; +} + +template <class Key, class T> +Q_INLINE_TEMPLATES void QMapPrivate<Key,T>::clear() +{ + clear( (NodePtr)(header->parent) ); + header->color = QMapNodeBase::Red; + header->parent = 0; + header->left = header->right = header; + node_count = 0; +} + +template <class Key, class T> +Q_INLINE_TEMPLATES void QMapPrivate<Key,T>::clear( Q_TYPENAME QMapPrivate<Key,T>::NodePtr p ) +{ + while ( p != 0 ) { + clear( (NodePtr)p->right ); + NodePtr y = (NodePtr)p->left; + delete p; + p = y; + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::ConstIterator QMapPrivate<Key,T>::find(const Key& k) const +{ + QMapNodeBase* y = header; // Last node + QMapNodeBase* x = header->parent; // Root node. + + while ( x != 0 ) { + // If as k <= key(x) go left + if ( !( key(x) < k ) ) { + y = x; + x = x->left; + } else { + x = x->right; + } + } + + // Was k bigger/smaller then the biggest/smallest + // element of the tree ? Return end() + if ( y == header || k < key(y) ) + return ConstIterator( header ); + return ConstIterator( (NodePtr)y ); +} + +template <class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::Iterator QMapPrivate<Key,T>::insertSingle( const Key& k ) +{ + // Search correct position in the tree + QMapNodeBase* y = header; + QMapNodeBase* x = header->parent; + bool result = TRUE; + while ( x != 0 ) { + result = ( k < key(x) ); + y = x; + x = result ? x->left : x->right; + } + // Get iterator on the last not empty one + Iterator j( (NodePtr)y ); + if ( result ) { + // Smaller then the leftmost one ? + if ( j == begin() ) { + return insert(x, y, k ); + } else { + // Perhaps daddy is the right one ? + --j; + } + } + // Really bigger ? + if ( (j.node->key) < k ) + return insert(x, y, k ); + // We are going to replace a node + return j; +} + + +template <class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::Iterator QMapPrivate<Key,T>::insert( QMapNodeBase* x, QMapNodeBase* y, const Key& k ) +{ + NodePtr z = new Node( k ); + if (y == header || x != 0 || k < key(y) ) { + y->left = z; // also makes leftmost = z when y == header + if ( y == header ) { + header->parent = z; + header->right = z; + } else if ( y == header->left ) + header->left = z; // maintain leftmost pointing to min node + } else { + y->right = z; + if ( y == header->right ) + header->right = z; // maintain rightmost pointing to max node + } + z->parent = y; + z->left = 0; + z->right = 0; + rebalance( z, header->parent ); + ++node_count; + return Iterator(z); +} + + +#ifdef QT_CHECK_RANGE +# if !defined( QT_NO_DEBUG ) && defined( QT_CHECK_MAP_RANGE ) +# define QT_CHECK_INVALID_MAP_ELEMENT if ( empty() ) qWarning( "QMap: Warning invalid element" ) +# define QT_CHECK_INVALID_MAP_ELEMENT_FATAL Q_ASSERT( !empty() ); +# else +# define QT_CHECK_INVALID_MAP_ELEMENT +# define QT_CHECK_INVALID_MAP_ELEMENT_FATAL +# endif +#else +# define QT_CHECK_INVALID_MAP_ELEMENT +# define QT_CHECK_INVALID_MAP_ELEMENT_FATAL +#endif + +template <class T> class QDeepCopy; + +template<class Key, class T> +class QMap +{ +public: + /** + * Typedefs + */ + typedef Key key_type; + typedef T mapped_type; + typedef QPair<const key_type, mapped_type> value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef size_t size_type; + typedef QMapIterator<Key,T> iterator; + typedef QMapConstIterator<Key,T> const_iterator; + typedef QPair<iterator,bool> insert_pair; + + typedef QMapIterator< Key, T > Iterator; + typedef QMapConstIterator< Key, T > ConstIterator; + typedef T ValueType; + typedef QMapPrivate< Key, T > Priv; + + /** + * API + */ + QMap() + { + sh = new QMapPrivate< Key, T >; + } + QMap( const QMap<Key,T>& m ) + { + sh = m.sh; sh->ref(); + } + +#ifndef QT_NO_STL +# ifdef Q_CC_HPACC // HP-UX aCC does require typename in some place +# undef Q_TYPENAME // but not accept them at others. +# define Q_TYPENAME // also doesn't like re-defines ... +# endif + QMap( const Q_TYPENAME std::map<Key,T>& m ) + { + sh = new QMapPrivate<Key,T>; +#if defined(Q_OS_WIN32) + std::map<Key,T>::const_iterator it = m.begin(); +#else + QMapConstIterator<Key,T> it = m.begin(); +#endif + for ( ; it != m.end(); ++it ) { + value_type p( (*it).first, (*it).second ); + insert( p ); + } + } +#endif + ~QMap() + { + if ( sh->deref() ) + delete sh; + } + QMap<Key,T>& operator= ( const QMap<Key,T>& m ); +#ifndef QT_NO_STL + QMap<Key,T>& operator= ( const Q_TYPENAME std::map<Key,T>& m ) + { + clear(); +#if defined(Q_OS_WIN32) + std::map<Key,T>::const_iterator it = m.begin(); +#else + QMapConstIterator<Key,T> it = m.begin(); +#endif + for ( ; it != m.end(); ++it ) { + value_type p( (*it).first, (*it).second ); + insert( p ); + } + return *this; + } +# ifdef Q_CC_HPACC // undo the HP-UX aCC hackery done above +# undef Q_TYPENAME +# define Q_TYPENAME typename +# endif +#endif + + iterator begin() { detach(); return sh->begin(); } + iterator end() { detach(); return sh->end(); } + const_iterator begin() const { return ((const Priv*)sh)->begin(); } + const_iterator end() const { return ((const Priv*)sh)->end(); } + iterator replace( const Key& k, const T& v ) + { + remove( k ); + return insert( k, v ); + } + + size_type size() const + { + return sh->node_count; + } + bool empty() const + { + return sh->node_count == 0; + } + QPair<iterator,bool> insert( const value_type& x ); + + void erase( iterator it ) + { + detach(); + sh->remove( it ); + } + void erase( const key_type& k ); + size_type count( const key_type& k ) const; + T& operator[] ( const Key& k ); + void clear(); + + iterator find ( const Key& k ) + { + detach(); + return iterator( sh->find( k ).node ); + } + const_iterator find ( const Key& k ) const { return sh->find( k ); } + + const T& operator[] ( const Key& k ) const + { QT_CHECK_INVALID_MAP_ELEMENT; return sh->find( k ).data(); } + bool contains ( const Key& k ) const + { return find( k ) != end(); } + //{ return sh->find( k ) != ((const Priv*)sh)->end(); } + + size_type count() const { return sh->node_count; } + + QValueList<Key> keys() const { + QValueList<Key> r; + for (const_iterator i=begin(); i!=end(); ++i) + r.append(i.key()); + return r; + } + + QValueList<T> values() const { + QValueList<T> r; + for (const_iterator i=begin(); i!=end(); ++i) + r.append(*i); + return r; + } + + bool isEmpty() const { return sh->node_count == 0; } + + iterator insert( const Key& key, const T& value, bool overwrite = TRUE ); + void remove( iterator it ) { detach(); sh->remove( it ); } + void remove( const Key& k ); + +#if defined(Q_FULL_TEMPLATE_INSTANTIATION) + bool operator==( const QMap<Key,T>& ) const { return FALSE; } +#ifndef QT_NO_STL + bool operator==( const Q_TYPENAME std::map<Key,T>& ) const { return FALSE; } +#endif +#endif + +protected: + /** + * Helpers + */ + void detach() { if ( sh->count > 1 ) detachInternal(); } + + Priv* sh; +private: + void detachInternal(); + + friend class QDeepCopy< QMap<Key,T> >; +}; + +template<class Key, class T> +Q_INLINE_TEMPLATES QMap<Key,T>& QMap<Key,T>::operator= ( const QMap<Key,T>& m ) +{ + m.sh->ref(); + if ( sh->deref() ) + delete sh; + sh = m.sh; + return *this; +} + +template<class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::insert_pair QMap<Key,T>::insert( const Q_TYPENAME QMap<Key,T>::value_type& x ) +{ + detach(); + size_type n = size(); + iterator it = sh->insertSingle( x.first ); + bool inserted = FALSE; + if ( n < size() ) { + inserted = TRUE; + it.data() = x.second; + } + return QPair<iterator,bool>( it, inserted ); +} + +template<class Key, class T> +Q_INLINE_TEMPLATES void QMap<Key,T>::erase( const Key& k ) +{ + detach(); + iterator it( sh->find( k ).node ); + if ( it != end() ) + sh->remove( it ); +} + +template<class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::size_type QMap<Key,T>::count( const Key& k ) const +{ + const_iterator it( sh->find( k ).node ); + if ( it != end() ) { + size_type c = 0; + while ( it != end() ) { + ++it; + ++c; + } + return c; + } + return 0; +} + +template<class Key, class T> +Q_INLINE_TEMPLATES T& QMap<Key,T>::operator[] ( const Key& k ) +{ + detach(); + QMapNode<Key,T>* p = sh->find( k ).node; + if ( p != sh->end().node ) + return p->data; + return insert( k, T() ).data(); +} + +template<class Key, class T> +Q_INLINE_TEMPLATES void QMap<Key,T>::clear() +{ + if ( sh->count == 1 ) + sh->clear(); + else { + sh->deref(); + sh = new QMapPrivate<Key,T>; + } +} + +template<class Key, class T> +Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::iterator QMap<Key,T>::insert( const Key& key, const T& value, bool overwrite ) +{ + detach(); + size_type n = size(); + iterator it = sh->insertSingle( key ); + if ( overwrite || n < size() ) + it.data() = value; + return it; +} + +template<class Key, class T> +Q_INLINE_TEMPLATES void QMap<Key,T>::remove( const Key& k ) +{ + detach(); + iterator it( sh->find( k ).node ); + if ( it != end() ) + sh->remove( it ); +} + +template<class Key, class T> +Q_INLINE_TEMPLATES void QMap<Key,T>::detachInternal() +{ + sh->deref(); sh = new QMapPrivate<Key,T>( sh ); +} + + +#ifndef QT_NO_DATASTREAM +template<class Key, class T> +Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QMap<Key,T>& m ) { + m.clear(); + Q_UINT32 c; + s >> c; + for( Q_UINT32 i = 0; i < c; ++i ) { + Key k; T t; + s >> k >> t; + m.insert( k, t ); + if ( s.atEnd() ) + break; + } + return s; +} + + +template<class Key, class T> +Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QMap<Key,T>& m ) { + s << (Q_UINT32)m.size(); + QMapConstIterator<Key,T> it = m.begin(); + for( ; it != m.end(); ++it ) + s << it.key() << it.data(); + return s; +} +#endif + +#endif // QMAP_H diff --git a/qmake/include/qmemarray.h b/qmake/include/qmemarray.h new file mode 100644 index 0000000..a5baf99 --- a/dev/null +++ b/qmake/include/qmemarray.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QMemArray template/macro class +** +** Created : 930906 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QMEMARRAY_H +#define QMEMARRAY_H + +#ifndef QT_H +#include "qgarray.h" +#endif // QT_H + + +template<class type> +class QMemArray : public QGArray +{ +public: + typedef type* Iterator; + typedef const type* ConstIterator; + typedef type ValueType; + +protected: + QMemArray( int, int ) : QGArray( 0, 0 ) {} + +public: + QMemArray() {} + QMemArray( int size ) : QGArray(size*sizeof(type)) {} + QMemArray( const QMemArray<type> &a ) : QGArray(a) {} + ~QMemArray() {} + QMemArray<type> &operator=(const QMemArray<type> &a) + { return (QMemArray<type>&)QGArray::assign(a); } + type *data() const { return (type *)QGArray::data(); } + uint nrefs() const { return QGArray::nrefs(); } + uint size() const { return QGArray::size()/sizeof(type); } + uint count() const { return size(); } + bool isEmpty() const { return QGArray::size() == 0; } + bool isNull() const { return QGArray::data() == 0; } + bool resize( uint size ) { return QGArray::resize(size*sizeof(type)); } + bool truncate( uint pos ) { return QGArray::resize(pos*sizeof(type)); } + bool fill( const type &d, int size = -1 ) + { return QGArray::fill((char*)&d,size,sizeof(type) ); } + void detach() { QGArray::detach(); } + QMemArray<type> copy() const + { QMemArray<type> tmp; return tmp.duplicate(*this); } + QMemArray<type>& assign( const QMemArray<type>& a ) + { return (QMemArray<type>&)QGArray::assign(a); } + QMemArray<type>& assign( const type *a, uint n ) + { return (QMemArray<type>&)QGArray::assign((char*)a,n*sizeof(type)); } + QMemArray<type>& duplicate( const QMemArray<type>& a ) + { return (QMemArray<type>&)QGArray::duplicate(a); } + QMemArray<type>& duplicate( const type *a, uint n ) + { return (QMemArray<type>&)QGArray::duplicate((char*)a,n*sizeof(type)); } + QMemArray<type>& setRawData( const type *a, uint n ) + { return (QMemArray<type>&)QGArray::setRawData((char*)a, + n*sizeof(type)); } + void resetRawData( const type *a, uint n ) + { QGArray::resetRawData((char*)a,n*sizeof(type)); } + int find( const type &d, uint i=0 ) const + { return QGArray::find((char*)&d,i,sizeof(type)); } + int contains( const type &d ) const + { return QGArray::contains((char*)&d,sizeof(type)); } + void sort() { QGArray::sort(sizeof(type)); } + int bsearch( const type &d ) const + { return QGArray::bsearch((const char*)&d,sizeof(type)); } + // ### Qt 4.0: maybe provide uint overload as work-around for MSVC bug + type& operator[]( int i ) const + { return (type &)(*(type *)QGArray::at(i*sizeof(type))); } + type& at( uint i ) const + { return (type &)(*(type *)QGArray::at(i*sizeof(type))); } + operator const type*() const { return (const type *)QGArray::data(); } + bool operator==( const QMemArray<type> &a ) const { return isEqual(a); } + bool operator!=( const QMemArray<type> &a ) const { return !isEqual(a); } + Iterator begin() { return data(); } + Iterator end() { return data() + size(); } + ConstIterator begin() const { return data(); } + ConstIterator end() const { return data() + size(); } +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<int>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<bool>; +// MOC_SKIP_END +#endif + +#ifndef QT_NO_COMPAT +#define QArray QMemArray +#endif + +#endif // QARRAY_H diff --git a/qmake/include/qnamespace.h b/qmake/include/qnamespace.h new file mode 100644 index 0000000..58b485f --- a/dev/null +++ b/qmake/include/qnamespace.h @@ -0,0 +1,843 @@ +/**************************************************************************** +** $Id$ +** +** Definition of Qt namespace (as class for compiler compatibility) +** +** Created : 980927 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QNAMESPACE_H +#define QNAMESPACE_H + +#ifndef QT_H +#include "qglobal.h" +#endif // QT_H + + +class QColor; +class QCursor; + + +class Q_EXPORT Qt { +public: + QT_STATIC_CONST QColor & color0; + QT_STATIC_CONST QColor & color1; + QT_STATIC_CONST QColor & black; + QT_STATIC_CONST QColor & white; + QT_STATIC_CONST QColor & darkGray; + QT_STATIC_CONST QColor & gray; + QT_STATIC_CONST QColor & lightGray; + QT_STATIC_CONST QColor & red; + QT_STATIC_CONST QColor & green; + QT_STATIC_CONST QColor & blue; + QT_STATIC_CONST QColor & cyan; + QT_STATIC_CONST QColor & magenta; + QT_STATIC_CONST QColor & yellow; + QT_STATIC_CONST QColor & darkRed; + QT_STATIC_CONST QColor & darkGreen; + QT_STATIC_CONST QColor & darkBlue; + QT_STATIC_CONST QColor & darkCyan; + QT_STATIC_CONST QColor & darkMagenta; + QT_STATIC_CONST QColor & darkYellow; + + // documented in qevent.cpp + enum ButtonState { // mouse/keyboard state values + NoButton = 0x0000, + LeftButton = 0x0001, + RightButton = 0x0002, + MidButton = 0x0004, + MouseButtonMask = 0x0007, + ShiftButton = 0x0100, + ControlButton = 0x0200, + AltButton = 0x0400, + MetaButton = 0x0800, + KeyButtonMask = 0x0f00, + Keypad = 0x4000 + }; + + // documented in qobject.cpp + // ideally would start at 1, as in QSizePolicy, but that breaks other things + enum Orientation { + Horizontal = 0, + Vertical + }; + + // Text formatting flags for QPainter::drawText and QLabel + // the following four enums can be combined to one integer which + // is passed as textflag to drawText and qt_format_text. + + // documented in qpainter.cpp + enum AlignmentFlags { + AlignAuto = 0x0000, // text alignment + AlignLeft = 0x0001, + AlignRight = 0x0002, + AlignHCenter = 0x0004, + AlignJustify = 0x0008, + AlignHorizontal_Mask = AlignLeft | AlignRight | AlignHCenter | AlignJustify, + AlignTop = 0x0010, + AlignBottom = 0x0020, + AlignVCenter = 0x0040, + AlignVertical_Mask = AlignTop | AlignBottom | AlignVCenter, + AlignCenter = AlignVCenter | AlignHCenter + }; + + // documented in qpainter.cpp + enum TextFlags { + SingleLine = 0x0080, // misc. flags + DontClip = 0x0100, + ExpandTabs = 0x0200, + ShowPrefix = 0x0400, + WordBreak = 0x0800, + BreakAnywhere = 0x1000, + DontPrint = 0x2000, // internal + NoAccel = 0x4000 + }; + + // Widget flags; documented in qwidget.cpp + typedef uint WState; + + // QWidget state flags (internal, barely documented in qwidget.cpp) + enum WidgetState { + WState_Created = 0x00000001, + WState_Disabled = 0x00000002, + WState_Visible = 0x00000004, + WState_ForceHide = 0x00000008, + WState_OwnCursor = 0x00000010, + WState_MouseTracking = 0x00000020, + WState_CompressKeys = 0x00000040, + WState_BlockUpdates = 0x00000080, + WState_InPaintEvent = 0x00000100, + WState_Reparented = 0x00000200, + WState_ConfigPending = 0x00000400, + WState_Resized = 0x00000800, + WState_AutoMask = 0x00001000, + WState_Polished = 0x00002000, + WState_DND = 0x00004000, + WState_Reserved0 = 0x00008000, + WState_Reserved1 = 0x00010000, + WState_Reserved2 = 0x00020000, + WState_CreatedHidden = 0x00040000, + WState_Maximized = 0x00080000, + WState_Minimized = 0x00100000, + WState_ForceDisabled = 0x00200000, + WState_Exposed = 0x00400000, + WState_HasMouse = 0x00800000 + }; + + // Widget flags2; documented in qwidget.cpp + typedef uint WFlags; + + // documented in qwidget.cpp + enum WidgetFlags { + WType_TopLevel = 0x00000001, // widget type flags + WType_Dialog = 0x00000002, + WType_Popup = 0x00000004, + WType_Desktop = 0x00000008, + WType_Mask = 0x0000000f, + + WStyle_Customize = 0x00000010, // window style flags + WStyle_NormalBorder = 0x00000020, + WStyle_DialogBorder = 0x00000040, // MS-Windows only + WStyle_NoBorder = 0x00002000, + WStyle_Title = 0x00000080, + WStyle_SysMenu = 0x00000100, + WStyle_Minimize = 0x00000200, + WStyle_Maximize = 0x00000400, + WStyle_MinMax = WStyle_Minimize | WStyle_Maximize, + WStyle_Tool = 0x00000800, + WStyle_StaysOnTop = 0x00001000, + WStyle_ContextHelp = 0x00004000, + WStyle_Reserved = 0x00008000, + WStyle_Mask = 0x0000fff0, + + WDestructiveClose = 0x00010000, // misc flags + WPaintDesktop = 0x00020000, + WPaintUnclipped = 0x00040000, + WPaintClever = 0x00080000, + WResizeNoErase = 0x00100000, + WMouseNoMask = 0x00200000, + WStaticContents = 0x00400000, + WRepaintNoErase = 0x00800000, +#ifdef Q_WS_X11 + WX11BypassWM = 0x01000000, + WWinOwnDC = 0x00000000, +#else + WX11BypassWM = 0x00000000, + WWinOwnDC = 0x01000000, +#endif + WGroupLeader = 0x02000000, + WShowModal = 0x04000000, + WNoMousePropagation = 0x08000000, + WSubWindow = 0x10000000 +#ifndef QT_NO_COMPAT + , + WNorthWestGravity = WStaticContents, + WType_Modal = WType_Dialog | WShowModal, + WStyle_Dialog = WType_Dialog, + WStyle_NoBorderEx = WStyle_NoBorder +#endif + }; + + // Image conversion flags. The unusual ordering is caused by + // compatibility and default requirements. + // Documented in qimage.cpp + + enum ImageConversionFlags { + ColorMode_Mask = 0x00000003, + AutoColor = 0x00000000, + ColorOnly = 0x00000003, + MonoOnly = 0x00000002, + // Reserved = 0x00000001, + + AlphaDither_Mask = 0x0000000c, + ThresholdAlphaDither = 0x00000000, + OrderedAlphaDither = 0x00000004, + DiffuseAlphaDither = 0x00000008, + NoAlpha = 0x0000000c, // Not supported + + Dither_Mask = 0x00000030, + DiffuseDither = 0x00000000, + OrderedDither = 0x00000010, + ThresholdDither = 0x00000020, + // ReservedDither= 0x00000030, + + DitherMode_Mask = 0x000000c0, + AutoDither = 0x00000000, + PreferDither = 0x00000040, + AvoidDither = 0x00000080 + }; + + // documented in qpainter.cpp + enum BGMode { // background mode + TransparentMode, + OpaqueMode + }; + +#ifndef QT_NO_COMPAT + // documented in qpainter.cpp + enum PaintUnit { // paint unit + PixelUnit, + LoMetricUnit, // OBSOLETE + HiMetricUnit, // OBSOLETE + LoEnglishUnit, // OBSOLETE + HiEnglishUnit, // OBSOLETE + TwipsUnit // OBSOLETE + }; +#endif + + // documented in qstyle.cpp +#ifdef QT_NO_COMPAT + enum GUIStyle { + WindowsStyle = 1, // ### Qt 4.0: either remove the obsolete enums or clean up compat vs. + MotifStyle = 4 // ### QT_NO_COMPAT by reordering or combination into one enum. + }; +#else + enum GUIStyle { + MacStyle, // OBSOLETE + WindowsStyle, + Win3Style, // OBSOLETE + PMStyle, // OBSOLETE + MotifStyle + }; +#endif + + // documented in qkeysequence.cpp + enum SequenceMatch { + NoMatch, + PartialMatch, + Identical + }; + + // documented in qevent.cpp + enum Modifier { // accelerator modifiers + META = 0x00100000, + SHIFT = 0x00200000, + CTRL = 0x00400000, + ALT = 0x00800000, + MODIFIER_MASK = 0x00f00000, + UNICODE_ACCEL = 0x10000000, + + ASCII_ACCEL = UNICODE_ACCEL // 1.x compat + }; + + // documented in qevent.cpp + enum Key { + Key_Escape = 0x1000, // misc keys + Key_Tab = 0x1001, + Key_Backtab = 0x1002, Key_BackTab = Key_Backtab, + Key_Backspace = 0x1003, Key_BackSpace = Key_Backspace, + Key_Return = 0x1004, + Key_Enter = 0x1005, + Key_Insert = 0x1006, + Key_Delete = 0x1007, + Key_Pause = 0x1008, + Key_Print = 0x1009, + Key_SysReq = 0x100a, + Key_Clear = 0x100b, + Key_Home = 0x1010, // cursor movement + Key_End = 0x1011, + Key_Left = 0x1012, + Key_Up = 0x1013, + Key_Right = 0x1014, + Key_Down = 0x1015, + Key_Prior = 0x1016, Key_PageUp = Key_Prior, + Key_Next = 0x1017, Key_PageDown = Key_Next, + Key_Shift = 0x1020, // modifiers + Key_Control = 0x1021, + Key_Meta = 0x1022, + Key_Alt = 0x1023, + Key_CapsLock = 0x1024, + Key_NumLock = 0x1025, + Key_ScrollLock = 0x1026, + Key_F1 = 0x1030, // function keys + Key_F2 = 0x1031, + Key_F3 = 0x1032, + Key_F4 = 0x1033, + Key_F5 = 0x1034, + Key_F6 = 0x1035, + Key_F7 = 0x1036, + Key_F8 = 0x1037, + Key_F9 = 0x1038, + Key_F10 = 0x1039, + Key_F11 = 0x103a, + Key_F12 = 0x103b, + Key_F13 = 0x103c, + Key_F14 = 0x103d, + Key_F15 = 0x103e, + Key_F16 = 0x103f, + Key_F17 = 0x1040, + Key_F18 = 0x1041, + Key_F19 = 0x1042, + Key_F20 = 0x1043, + Key_F21 = 0x1044, + Key_F22 = 0x1045, + Key_F23 = 0x1046, + Key_F24 = 0x1047, + Key_F25 = 0x1048, // F25 .. F35 only on X11 + Key_F26 = 0x1049, + Key_F27 = 0x104a, + Key_F28 = 0x104b, + Key_F29 = 0x104c, + Key_F30 = 0x104d, + Key_F31 = 0x104e, + Key_F32 = 0x104f, + Key_F33 = 0x1050, + Key_F34 = 0x1051, + Key_F35 = 0x1052, + Key_Super_L = 0x1053, // extra keys + Key_Super_R = 0x1054, + Key_Menu = 0x1055, + Key_Hyper_L = 0x1056, + Key_Hyper_R = 0x1057, + Key_Help = 0x1058, + Key_Direction_L = 0x1059, + Key_Direction_R = 0x1060, + Key_Space = 0x20, // 7 bit printable ASCII + Key_Any = Key_Space, + Key_Exclam = 0x21, + Key_QuoteDbl = 0x22, + Key_NumberSign = 0x23, + Key_Dollar = 0x24, + Key_Percent = 0x25, + Key_Ampersand = 0x26, + Key_Apostrophe = 0x27, + Key_ParenLeft = 0x28, + Key_ParenRight = 0x29, + Key_Asterisk = 0x2a, + Key_Plus = 0x2b, + Key_Comma = 0x2c, + Key_Minus = 0x2d, + Key_Period = 0x2e, + Key_Slash = 0x2f, + Key_0 = 0x30, + Key_1 = 0x31, + Key_2 = 0x32, + Key_3 = 0x33, + Key_4 = 0x34, + Key_5 = 0x35, + Key_6 = 0x36, + Key_7 = 0x37, + Key_8 = 0x38, + Key_9 = 0x39, + Key_Colon = 0x3a, + Key_Semicolon = 0x3b, + Key_Less = 0x3c, + Key_Equal = 0x3d, + Key_Greater = 0x3e, + Key_Question = 0x3f, + Key_At = 0x40, + Key_A = 0x41, + Key_B = 0x42, + Key_C = 0x43, + Key_D = 0x44, + Key_E = 0x45, + Key_F = 0x46, + Key_G = 0x47, + Key_H = 0x48, + Key_I = 0x49, + Key_J = 0x4a, + Key_K = 0x4b, + Key_L = 0x4c, + Key_M = 0x4d, + Key_N = 0x4e, + Key_O = 0x4f, + Key_P = 0x50, + Key_Q = 0x51, + Key_R = 0x52, + Key_S = 0x53, + Key_T = 0x54, + Key_U = 0x55, + Key_V = 0x56, + Key_W = 0x57, + Key_X = 0x58, + Key_Y = 0x59, + Key_Z = 0x5a, + Key_BracketLeft = 0x5b, + Key_Backslash = 0x5c, + Key_BracketRight = 0x5d, + Key_AsciiCircum = 0x5e, + Key_Underscore = 0x5f, + Key_QuoteLeft = 0x60, + Key_BraceLeft = 0x7b, + Key_Bar = 0x7c, + Key_BraceRight = 0x7d, + Key_AsciiTilde = 0x7e, + + // Latin 1 codes adapted from X: keysymdef.h,v 1.21 94/08/28 16:17:06 + + Key_nobreakspace = 0x0a0, + Key_exclamdown = 0x0a1, + Key_cent = 0x0a2, + Key_sterling = 0x0a3, + Key_currency = 0x0a4, + Key_yen = 0x0a5, + Key_brokenbar = 0x0a6, + Key_section = 0x0a7, + Key_diaeresis = 0x0a8, + Key_copyright = 0x0a9, + Key_ordfeminine = 0x0aa, + Key_guillemotleft = 0x0ab, // left angle quotation mark + Key_notsign = 0x0ac, + Key_hyphen = 0x0ad, + Key_registered = 0x0ae, + Key_macron = 0x0af, + Key_degree = 0x0b0, + Key_plusminus = 0x0b1, + Key_twosuperior = 0x0b2, + Key_threesuperior = 0x0b3, + Key_acute = 0x0b4, + Key_mu = 0x0b5, + Key_paragraph = 0x0b6, + Key_periodcentered = 0x0b7, + Key_cedilla = 0x0b8, + Key_onesuperior = 0x0b9, + Key_masculine = 0x0ba, + Key_guillemotright = 0x0bb, // right angle quotation mark + Key_onequarter = 0x0bc, + Key_onehalf = 0x0bd, + Key_threequarters = 0x0be, + Key_questiondown = 0x0bf, + Key_Agrave = 0x0c0, + Key_Aacute = 0x0c1, + Key_Acircumflex = 0x0c2, + Key_Atilde = 0x0c3, + Key_Adiaeresis = 0x0c4, + Key_Aring = 0x0c5, + Key_AE = 0x0c6, + Key_Ccedilla = 0x0c7, + Key_Egrave = 0x0c8, + Key_Eacute = 0x0c9, + Key_Ecircumflex = 0x0ca, + Key_Ediaeresis = 0x0cb, + Key_Igrave = 0x0cc, + Key_Iacute = 0x0cd, + Key_Icircumflex = 0x0ce, + Key_Idiaeresis = 0x0cf, + Key_ETH = 0x0d0, + Key_Ntilde = 0x0d1, + Key_Ograve = 0x0d2, + Key_Oacute = 0x0d3, + Key_Ocircumflex = 0x0d4, + Key_Otilde = 0x0d5, + Key_Odiaeresis = 0x0d6, + Key_multiply = 0x0d7, + Key_Ooblique = 0x0d8, + Key_Ugrave = 0x0d9, + Key_Uacute = 0x0da, + Key_Ucircumflex = 0x0db, + Key_Udiaeresis = 0x0dc, + Key_Yacute = 0x0dd, + Key_THORN = 0x0de, + Key_ssharp = 0x0df, + Key_agrave = 0x0e0, + Key_aacute = 0x0e1, + Key_acircumflex = 0x0e2, + Key_atilde = 0x0e3, + Key_adiaeresis = 0x0e4, + Key_aring = 0x0e5, + Key_ae = 0x0e6, + Key_ccedilla = 0x0e7, + Key_egrave = 0x0e8, + Key_eacute = 0x0e9, + Key_ecircumflex = 0x0ea, + Key_ediaeresis = 0x0eb, + Key_igrave = 0x0ec, + Key_iacute = 0x0ed, + Key_icircumflex = 0x0ee, + Key_idiaeresis = 0x0ef, + Key_eth = 0x0f0, + Key_ntilde = 0x0f1, + Key_ograve = 0x0f2, + Key_oacute = 0x0f3, + Key_ocircumflex = 0x0f4, + Key_otilde = 0x0f5, + Key_odiaeresis = 0x0f6, + Key_division = 0x0f7, + Key_oslash = 0x0f8, + Key_ugrave = 0x0f9, + Key_uacute = 0x0fa, + Key_ucircumflex = 0x0fb, + Key_udiaeresis = 0x0fc, + Key_yacute = 0x0fd, + Key_thorn = 0x0fe, + Key_ydiaeresis = 0x0ff, + + // multimedia/internet keys - ignored by default - see QKeyEvent c'tor + + Key_Back = 0x1061, + Key_Forward = 0x1062, + Key_Stop = 0x1063, + Key_Refresh = 0x1064, + + Key_VolumeDown = 0x1070, + Key_VolumeMute = 0x1071, + Key_VolumeUp = 0x1072, + Key_BassBoost = 0x1073, + Key_BassUp = 0x1074, + Key_BassDown = 0x1075, + Key_TrebleUp = 0x1076, + Key_TrebleDown = 0x1077, + + Key_MediaPlay = 0x1080, + Key_MediaStop = 0x1081, + Key_MediaPrev = 0x1082, + Key_MediaNext = 0x1083, + Key_MediaRecord = 0x1084, + + Key_HomePage = 0x1090, + Key_Favorites = 0x1091, + Key_Search = 0x1092, + Key_Standby = 0x1093, + Key_OpenUrl = 0x1094, + + Key_LaunchMail = 0x10a0, + Key_LaunchMedia = 0x10a1, + Key_Launch0 = 0x10a2, + Key_Launch1 = 0x10a3, + Key_Launch2 = 0x10a4, + Key_Launch3 = 0x10a5, + Key_Launch4 = 0x10a6, + Key_Launch5 = 0x10a7, + Key_Launch6 = 0x10a8, + Key_Launch7 = 0x10a9, + Key_Launch8 = 0x10aa, + Key_Launch9 = 0x10ab, + Key_LaunchA = 0x10ac, + Key_LaunchB = 0x10ad, + Key_LaunchC = 0x10ae, + Key_LaunchD = 0x10af, + Key_LaunchE = 0x10b0, + Key_LaunchF = 0x10b1, + + Key_MediaLast = 0x1fff, + + Key_unknown = 0xffff + }; + + // documented in qcommonstyle.cpp + enum ArrowType { + UpArrow, + DownArrow, + LeftArrow, + RightArrow + }; + + // documented in qpainter.cpp + enum RasterOp { // raster op mode + CopyROP, + OrROP, + XorROP, + NotAndROP, EraseROP=NotAndROP, + NotCopyROP, + NotOrROP, + NotXorROP, + AndROP, NotEraseROP=AndROP, + NotROP, + ClearROP, + SetROP, + NopROP, + AndNotROP, + OrNotROP, + NandROP, + NorROP, LastROP=NorROP + }; + + // documented in qpainter.cpp + enum PenStyle { // pen style + NoPen, + SolidLine, + DashLine, + DotLine, + DashDotLine, + DashDotDotLine, + MPenStyle = 0x0f + }; + + // documented in qpainter.cpp + enum PenCapStyle { // line endcap style + FlatCap = 0x00, + SquareCap = 0x10, + RoundCap = 0x20, + MPenCapStyle = 0x30 + }; + + // documented in qpainter.cpp + enum PenJoinStyle { // line join style + MiterJoin = 0x00, + BevelJoin = 0x40, + RoundJoin = 0x80, + MPenJoinStyle = 0xc0 + }; + + // documented in qpainter.cpp + enum BrushStyle { // brush style + NoBrush, + SolidPattern, + Dense1Pattern, + Dense2Pattern, + Dense3Pattern, + Dense4Pattern, + Dense5Pattern, + Dense6Pattern, + Dense7Pattern, + HorPattern, + VerPattern, + CrossPattern, + BDiagPattern, + FDiagPattern, + DiagCrossPattern, + CustomPattern=24 + }; + + // documented in qapplication_win.cpp + enum WindowsVersion { + WV_32s = 0x0001, + WV_95 = 0x0002, + WV_98 = 0x0003, + WV_Me = 0x0004, + WV_DOS_based = 0x000f, + + WV_NT = 0x0010, + WV_2000 = 0x0020, + WV_XP = 0x0030, + WV_NT_based = 0x00f0 + }; + + // documented in qstyle.cpp + enum UIEffect { + UI_General, + UI_AnimateMenu, + UI_FadeMenu, + UI_AnimateCombo, + UI_AnimateTooltip, + UI_FadeTooltip + }; + + // documented in qcursor.cpp + enum CursorShape { + ArrowCursor, + UpArrowCursor, + CrossCursor, + WaitCursor, + IbeamCursor, + SizeVerCursor, + SizeHorCursor, + SizeBDiagCursor, + SizeFDiagCursor, + SizeAllCursor, + BlankCursor, + SplitVCursor, + SplitHCursor, + PointingHandCursor, + ForbiddenCursor, + WhatsThisCursor, + LastCursor = WhatsThisCursor, + BitmapCursor = 24 + }; + + // Global cursors + + QT_STATIC_CONST QCursor & arrowCursor; // standard arrow cursor + QT_STATIC_CONST QCursor & upArrowCursor; // upwards arrow + QT_STATIC_CONST QCursor & crossCursor; // crosshair + QT_STATIC_CONST QCursor & waitCursor; // hourglass/watch + QT_STATIC_CONST QCursor & ibeamCursor; // ibeam/text entry + QT_STATIC_CONST QCursor & sizeVerCursor; // vertical resize + QT_STATIC_CONST QCursor & sizeHorCursor; // horizontal resize + QT_STATIC_CONST QCursor & sizeBDiagCursor; // diagonal resize (/) + QT_STATIC_CONST QCursor & sizeFDiagCursor; // diagonal resize (\) + QT_STATIC_CONST QCursor & sizeAllCursor; // all directions resize + QT_STATIC_CONST QCursor & blankCursor; // blank/invisible cursor + QT_STATIC_CONST QCursor & splitVCursor; // vertical bar with left-right + // arrows + QT_STATIC_CONST QCursor & splitHCursor; // horizontal bar with up-down + // arrows + QT_STATIC_CONST QCursor & pointingHandCursor; // pointing hand + QT_STATIC_CONST QCursor & forbiddenCursor; // forbidden cursor (slashed circle) + QT_STATIC_CONST QCursor & whatsThisCursor; // arrow with a question mark + + + enum TextFormat { + PlainText, + RichText, + AutoText, + LogText + }; + + // Documented in qtextedit.cpp + enum AnchorAttribute { + AnchorName, + AnchorHref + }; + + // Documented in qmainwindow.cpp + enum Dock { + DockUnmanaged, + DockTornOff, + DockTop, + DockBottom, + DockRight, + DockLeft, + DockMinimized +#ifndef QT_NO_COMPAT + , + Unmanaged = DockUnmanaged, + TornOff = DockTornOff, + Top = DockTop, + Bottom = DockBottom, + Right = DockRight, + Left = DockLeft, + Minimized = DockMinimized +#endif + }; + // compatibility + typedef Dock ToolBarDock; + + // documented in qdatetime.cpp + enum DateFormat { + TextDate, // default Qt + ISODate, // ISO 8601 + LocalDate // locale dependant + }; + + // documented in qdatetime.cpp + enum TimeSpec { + LocalTime, + UTC + }; + + // documented in qwidget.cpp + enum BackgroundMode { + FixedColor, + FixedPixmap, + NoBackground, + PaletteForeground, + PaletteButton, + PaletteLight, + PaletteMidlight, + PaletteDark, + PaletteMid, + PaletteText, + PaletteBrightText, + PaletteBase, + PaletteBackground, + PaletteShadow, + PaletteHighlight, + PaletteHighlightedText, + PaletteButtonText, + PaletteLink, + PaletteLinkVisited, + X11ParentRelative + }; + + typedef uint ComparisonFlags; + + // Documented in qstring.cpp + enum StringComparisonMode { + CaseSensitive = 0x00001, // 0 0001 + BeginsWith = 0x00002, // 0 0010 + EndsWith = 0x00004, // 0 0100 + Contains = 0x00008, // 0 1000 + ExactMatch = 0x00010 // 1 0000 + }; + + // "handle" type for system objects. Documented as \internal in + // qapplication.cpp +#if defined(Q_WS_MAC) + typedef void * HANDLE; +#elif defined(Q_WS_WIN) + typedef void *HANDLE; +#elif defined(Q_WS_X11) + typedef unsigned long HANDLE; +#elif defined(Q_WS_QWS) + typedef void * HANDLE; +#endif +}; + + +class Q_EXPORT QInternal { +public: + enum PaintDeviceFlags { + UndefinedDevice = 0x00, + Widget = 0x01, + Pixmap = 0x02, + Printer = 0x03, + Picture = 0x04, + System = 0x05, + DeviceTypeMask = 0x0f, + ExternalDevice = 0x10, + // used to emulate some of the behaviour different between Qt2 and Qt3 (mainly for printing) + CompatibilityMode = 0x20 + }; +}; + +#endif // QNAMESPACE_H diff --git a/qmake/include/qpair.h b/qmake/include/qpair.h new file mode 100644 index 0000000..e7cd70e --- a/dev/null +++ b/qmake/include/qpair.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Definition of QPair class +** +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPAIR_H +#define QPAIR_H + +#ifndef QT_H +#include "qglobal.h" +#include "qdatastream.h" +#endif // QT_H + +template <class T1, class T2> +struct QPair +{ + typedef T1 first_type; + typedef T2 second_type; + + QPair() + : first( T1() ), second( T2() ) + {} + QPair( const T1& t1, const T2& t2 ) + : first( t1 ), second( t2 ) + {} + + T1 first; + T2 second; +}; + +template <class T1, class T2> +Q_INLINE_TEMPLATES bool operator==( const QPair<T1, T2>& x, const QPair<T1, T2>& y ) +{ + return x.first == y.first && x.second == y.second; +} + +template <class T1, class T2> +Q_INLINE_TEMPLATES bool operator<( const QPair<T1, T2>& x, const QPair<T1, T2>& y ) +{ + return x.first < y.first || + ( !( y.first < x.first ) && x.second < y.second ); +} + +template <class T1, class T2> +Q_INLINE_TEMPLATES QPair<T1, T2> qMakePair( const T1& x, const T2& y ) +{ + return QPair<T1, T2>( x, y ); +} + +#ifndef QT_NO_DATASTREAM +template <class T1, class T2> +inline QDataStream& operator>>( QDataStream& s, QPair<T1, T2>& p ) +{ + s >> p.first >> p.second; + return s; +} + +template <class T1, class T2> +inline QDataStream& operator<<( QDataStream& s, const QPair<T1, T2>& p ) +{ + s << p.first << p.second; + return s; +} +#endif + +#endif diff --git a/qmake/include/qptrcollection.h b/qmake/include/qptrcollection.h new file mode 100644 index 0000000..4f121fa --- a/dev/null +++ b/qmake/include/qptrcollection.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Definition of base class for all pointer based collection classes +** +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPTRCOLLECTION_H +#define QPTRCOLLECTION_H + +#ifndef QT_H +#include "qglobal.h" +#endif // QT_H + + +class QGVector; +class QGList; +class QGDict; + + +class Q_EXPORT QPtrCollection // inherited by all collections +{ +public: + bool autoDelete() const { return del_item; } + void setAutoDelete( bool enable ) { del_item = enable; } + + virtual uint count() const = 0; + virtual void clear() = 0; // delete all objects + + typedef void *Item; // generic collection item + +protected: + QPtrCollection() { del_item = FALSE; } // no deletion of objects + QPtrCollection(const QPtrCollection &) { del_item = FALSE; } + virtual ~QPtrCollection() {} + + bool del_item; // default FALSE + + virtual Item newItem( Item ); // create object + virtual void deleteItem( Item ) = 0; // delete object +}; + + +#ifndef QT_NO_COMPAT +#define QCollection QPtrCollection +#endif + +#endif // QPTRCOLLECTION_H diff --git a/qmake/include/qptrlist.h b/qmake/include/qptrlist.h new file mode 100644 index 0000000..53fb605 --- a/dev/null +++ b/qmake/include/qptrlist.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QPtrList template/macro class +** +** Created : +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPTRLIST_H +#define QPTRLIST_H + +#ifndef QT_H +#include "qglist.h" +#endif // QT_H + + +template<class type> +class QPtrList +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGList +#endif +{ +public: + QPtrList() {} + QPtrList( const QPtrList<type> &l ) : QGList(l) {} + ~QPtrList() { clear(); } + QPtrList<type> &operator=(const QPtrList<type> &l) + { return (QPtrList<type>&)QGList::operator=(l); } + bool operator==( const QPtrList<type> &list ) const + { return QGList::operator==( list ); } + bool operator!=( const QPtrList<type> &list ) const + { return !QGList::operator==( list ); } + uint count() const { return QGList::count(); } + bool isEmpty() const { return QGList::count() == 0; } + bool insert( uint i, const type *d){ return QGList::insertAt(i,(QPtrCollection::Item)d); } + void inSort( const type *d ) { QGList::inSort((QPtrCollection::Item)d); } + void prepend( const type *d ) { QGList::insertAt(0,(QPtrCollection::Item)d); } + void append( const type *d ) { QGList::append((QPtrCollection::Item)d); } + bool remove( uint i ) { return QGList::removeAt(i); } + bool remove() { return QGList::remove((QPtrCollection::Item)0); } + bool remove( const type *d ) { return QGList::remove((QPtrCollection::Item)d); } + bool removeRef( const type *d ) { return QGList::removeRef((QPtrCollection::Item)d); } + void removeNode( QLNode *n ) { QGList::removeNode(n); } + bool removeFirst() { return QGList::removeFirst(); } + bool removeLast() { return QGList::removeLast(); } + type *take( uint i ) { return (type *)QGList::takeAt(i); } + type *take() { return (type *)QGList::take(); } + type *takeNode( QLNode *n ) { return (type *)QGList::takeNode(n); } + void clear() { QGList::clear(); } + void sort() { QGList::sort(); } + int find( const type *d ) { return QGList::find((QPtrCollection::Item)d); } + int findNext( const type *d ) { return QGList::find((QPtrCollection::Item)d,FALSE); } + int findRef( const type *d ) { return QGList::findRef((QPtrCollection::Item)d); } + int findNextRef( const type *d ){ return QGList::findRef((QPtrCollection::Item)d,FALSE);} + uint contains( const type *d ) const { return QGList::contains((QPtrCollection::Item)d); } + uint containsRef( const type *d ) const + { return QGList::containsRef((QPtrCollection::Item)d); } + bool replace( uint i, const type *d ) { return QGList::replaceAt( i, (QPtrCollection::Item)d ); } + type *at( uint i ) { return (type *)QGList::at(i); } + int at() const { return QGList::at(); } + type *current() const { return (type *)QGList::get(); } + QLNode *currentNode() const { return QGList::currentNode(); } + type *getFirst() const { return (type *)QGList::cfirst(); } + type *getLast() const { return (type *)QGList::clast(); } + type *first() { return (type *)QGList::first(); } + type *last() { return (type *)QGList::last(); } + type *next() { return (type *)QGList::next(); } + type *prev() { return (type *)QGList::prev(); } + void toVector( QGVector *vec )const{ QGList::toVector(vec); } + +#ifdef Q_QDOC +protected: + virtual int compareItems( QPtrCollection::Item, QPtrCollection::Item ); + virtual QDataStream& read( QDataStream&, QPtrCollection::Item& ); + virtual QDataStream& write( QDataStream&, QPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QPtrList<void>::deleteItem( QPtrCollection::Item ) +{ +} +#endif + +template<class type> inline void QPtrList<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template<class type> +class QPtrListIterator : public QGListIterator +{ +public: + QPtrListIterator(const QPtrList<type> &l) :QGListIterator((QGList &)l) {} + ~QPtrListIterator() {} + uint count() const { return list->count(); } + bool isEmpty() const { return list->count() == 0; } + bool atFirst() const { return QGListIterator::atFirst(); } + bool atLast() const { return QGListIterator::atLast(); } + type *toFirst() { return (type *)QGListIterator::toFirst(); } + type *toLast() { return (type *)QGListIterator::toLast(); } + operator type *() const { return (type *)QGListIterator::get(); } + type *operator*() { return (type *)QGListIterator::get(); } + + // No good, since QPtrList<char> (ie. QStrList fails... + // + // MSVC++ gives warning + // Sunpro C++ 4.1 gives error + // type *operator->() { return (type *)QGListIterator::get(); } + + type *current() const { return (type *)QGListIterator::get(); } + type *operator()() { return (type *)QGListIterator::operator()();} + type *operator++() { return (type *)QGListIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGListIterator::operator+=(j);} + type *operator--() { return (type *)QGListIterator::operator--(); } + type *operator-=(uint j) { return (type *)QGListIterator::operator-=(j);} + QPtrListIterator<type>& operator=(const QPtrListIterator<type>&it) + { QGListIterator::operator=(it); return *this; } +}; + +#ifndef QT_NO_COMPAT +#define QList QPtrList +#define QListIterator QPtrListIterator +#endif + +#endif // QPTRLIST_H diff --git a/qmake/include/qptrvector.h b/qmake/include/qptrvector.h new file mode 100644 index 0000000..f6d9623 --- a/dev/null +++ b/qmake/include/qptrvector.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QPtrVector pointer based template class +** +** Created : 930907 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QPTRVECTOR_H +#define QPTRVECTOR_H + +#ifndef QT_H +#include "qgvector.h" +#endif // QT_H + +template<class type> +class QPtrVector +#ifdef Q_QDOC + : public QPtrCollection +#else + : public QGVector +#endif +{ +public: + QPtrVector() { } + QPtrVector( uint size ) : QGVector(size) { } + QPtrVector( const QPtrVector<type> &v ) : QGVector( v ) { } + ~QPtrVector() { clear(); } + QPtrVector<type> &operator=(const QPtrVector<type> &v) + { return (QPtrVector<type>&)QGVector::operator=(v); } + bool operator==( const QPtrVector<type> &v ) const { return QGVector::operator==(v); } + type **data() const { return (type **)QGVector::data(); } + uint size() const { return QGVector::size(); } + uint count() const { return QGVector::count(); } + bool isEmpty() const { return QGVector::count() == 0; } + bool isNull() const { return QGVector::size() == 0; } + bool resize( uint size ) { return QGVector::resize(size); } + bool insert( uint i, const type *d){ return QGVector::insert(i,(Item)d); } + bool remove( uint i ) { return QGVector::remove(i); } + type *take( uint i ) { return (type *)QGVector::take(i); } + void clear() { QGVector::clear(); } + bool fill( const type *d, int size=-1 ) + { return QGVector::fill((Item)d,size);} + void sort() { QGVector::sort(); } + int bsearch( const type *d ) const{ return QGVector::bsearch((Item)d); } + int findRef( const type *d, uint i=0 ) const + { return QGVector::findRef((Item)d,i);} + int find( const type *d, uint i= 0 ) const + { return QGVector::find((Item)d,i); } + uint containsRef( const type *d ) const + { return QGVector::containsRef((Item)d); } + uint contains( const type *d ) const + { return QGVector::contains((Item)d); } + type *operator[]( int i ) const { return (type *)QGVector::at(i); } + type *at( uint i ) const { return (type *)QGVector::at(i); } + void toList( QGList *list ) const { QGVector::toList(list); } + +#ifdef Q_QDOC +protected: + virtual int compareItems( QPtrCollection::Item d1, QPtrCollection::Item d2 ); + virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &d ); + virtual QDataStream& write( QDataStream &s, QPtrCollection::Item d ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void QPtrVector<void>::deleteItem( QPtrCollection::Item ) +{ +} +#endif + +template<class type> inline void QPtrVector<type>::deleteItem( QPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +#ifndef QT_NO_COMPAT +#define QVector QPtrVector +#endif + +#endif // QVECTOR_H diff --git a/qmake/include/qregexp.h b/qmake/include/qregexp.h new file mode 100644 index 0000000..7bb777a --- a/dev/null +++ b/qmake/include/qregexp.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QRegExp class +** +** Created : 950126 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QREGEXP_H +#define QREGEXP_H + +#ifndef QT_H +#include "qstringlist.h" +#endif // QT_H + +#ifndef QT_NO_REGEXP +class QRegExpEngine; +struct QRegExpPrivate; + +class Q_EXPORT QRegExp +{ +public: + enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; + + QRegExp(); + QRegExp( const QString& pattern, bool caseSensitive = TRUE, + bool wildcard = FALSE ); + QRegExp( const QRegExp& rx ); + ~QRegExp(); + QRegExp& operator=( const QRegExp& rx ); + + bool operator==( const QRegExp& rx ) const; + bool operator!=( const QRegExp& rx ) const { return !operator==( rx ); } + + bool isEmpty() const; + bool isValid() const; + QString pattern() const; + void setPattern( const QString& pattern ); + bool caseSensitive() const; + void setCaseSensitive( bool sensitive ); +#ifndef QT_NO_REGEXP_WILDCARD + bool wildcard() const; + void setWildcard( bool wildcard ); +#endif + bool minimal() const; + void setMinimal( bool minimal ); + + bool exactMatch( const QString& str ) const; +#ifndef QT_NO_COMPAT + int match( const QString& str, int index = 0, int *len = 0, + bool indexIsStart = TRUE ) const; +#endif + +#if defined(qdoc) + int search( const QString& str, int offset = 0, + CaretMode caretMode = CaretAtZero ) const; + int searchRev( const QString& str, int offset = -1, + CaretMode caretMode = CaretAtZero ) const; +#else + // ### Qt 4.0: reduce these four to two functions + int search( const QString& str, int offset = 0 ) const; + int search( const QString& str, int offset, CaretMode caretMode ) const; + int searchRev( const QString& str, int offset = -1 ) const; + int searchRev( const QString& str, int offset, CaretMode caretMode ) const; +#endif + int matchedLength() const; +#ifndef QT_NO_REGEXP_CAPTURE + int numCaptures() const; + QStringList capturedTexts(); + QString cap( int nth = 0 ); + int pos( int nth = 0 ); + QString errorString(); +#endif + + static QString escape( const QString& str ); + +private: + void compile( bool caseSensitive ); + + static int caretIndex( int offset, CaretMode caretMode ); + + QRegExpEngine *eng; + QRegExpPrivate *priv; +}; +#endif // QT_NO_REGEXP +#endif // QREGEXP_H diff --git a/qmake/include/qshared.h b/qmake/include/qshared.h new file mode 100644 index 0000000..3c2f97f --- a/dev/null +++ b/qmake/include/qshared.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QShared struct +** +** Created : 940112 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSHARED_H +#define QSHARED_H + +#ifndef QT_H +#include "qglobal.h" +#endif // QT_H + + +struct Q_EXPORT QShared +{ + QShared() : count( 1 ) { } + void ref() { count++; } + bool deref() { return !--count; } + uint count; +}; + + +#endif // QSHARED_H diff --git a/qmake/include/qstring.h b/qmake/include/qstring.h new file mode 100644 index 0000000..2a87a5a --- a/dev/null +++ b/qmake/include/qstring.h @@ -0,0 +1,950 @@ +/**************************************************************************** +** $Id$ +** +** Definition of the QString class, and related Unicode +** functions. +** +** Created : 920609 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSTRING_H +#define QSTRING_H + +#ifndef QT_H +#include "qcstring.h" +#endif // QT_H + + +/***************************************************************************** + QString class + *****************************************************************************/ + +class QRegExp; +class QString; +class QCharRef; +template <class T> class QDeepCopy; + +class Q_EXPORT QChar { +public: + QChar(); + QChar( char c ); + QChar( uchar c ); + QChar( uchar c, uchar r ); + QChar( const QChar& c ); + QChar( ushort rc ); + QChar( short rc ); + QChar( uint rc ); + QChar( int rc ); + + QT_STATIC_CONST QChar null; // 0000 + QT_STATIC_CONST QChar replacement; // FFFD + QT_STATIC_CONST QChar byteOrderMark; // FEFF + QT_STATIC_CONST QChar byteOrderSwapped; // FFFE + QT_STATIC_CONST QChar nbsp; // 00A0 + + // Unicode information + + enum Category + { + NoCategory, + + Mark_NonSpacing, // Mn + Mark_SpacingCombining, // Mc + Mark_Enclosing, // Me + + Number_DecimalDigit, // Nd + Number_Letter, // Nl + Number_Other, // No + + Separator_Space, // Zs + Separator_Line, // Zl + Separator_Paragraph, // Zp + + Other_Control, // Cc + Other_Format, // Cf + Other_Surrogate, // Cs + Other_PrivateUse, // Co + Other_NotAssigned, // Cn + + Letter_Uppercase, // Lu + Letter_Lowercase, // Ll + Letter_Titlecase, // Lt + Letter_Modifier, // Lm + Letter_Other, // Lo + + Punctuation_Connector, // Pc + Punctuation_Dash, // Pd + Punctuation_Dask = Punctuation_Dash, // oops + Punctuation_Open, // Ps + Punctuation_Close, // Pe + Punctuation_InitialQuote, // Pi + Punctuation_FinalQuote, // Pf + Punctuation_Other, // Po + + Symbol_Math, // Sm + Symbol_Currency, // Sc + Symbol_Modifier, // Sk + Symbol_Other // So + }; + + enum Direction + { + DirL, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON, + DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN + }; + + enum Decomposition + { + Single, Canonical, Font, NoBreak, Initial, Medial, + Final, Isolated, Circle, Super, Sub, Vertical, + Wide, Narrow, Small, Square, Compat, Fraction + }; + + enum Joining + { + OtherJoining, Dual, Right, Center + }; + + enum CombiningClass + { + Combining_BelowLeftAttached = 200, + Combining_BelowAttached = 202, + Combining_BelowRightAttached = 204, + Combining_LeftAttached = 208, + Combining_RightAttached = 210, + Combining_AboveLeftAttached = 212, + Combining_AboveAttached = 214, + Combining_AboveRightAttached = 216, + + Combining_BelowLeft = 218, + Combining_Below = 220, + Combining_BelowRight = 222, + Combining_Left = 224, + Combining_Right = 226, + Combining_AboveLeft = 228, + Combining_Above = 230, + Combining_AboveRight = 232, + + Combining_DoubleBelow = 233, + Combining_DoubleAbove = 234, + Combining_IotaSubscript = 240 + }; + + // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO + + int digitValue() const; + QChar lower() const; + QChar upper() const; + + Category category() const; + Direction direction() const; + Joining joining() const; + bool mirrored() const; + QChar mirroredChar() const; + const QString &decomposition() const; // ### return just QString in 4.0 + Decomposition decompositionTag() const; + unsigned char combiningClass() const; + + char latin1() const { return ucs > 0xff ? 0 : (char) ucs; } + ushort unicode() const { return ucs; } + ushort &unicode() { return ucs; } +#ifndef QT_NO_CAST_ASCII + // like all ifdef'd code this is undocumented + operator char() const { return latin1(); } +#endif + + bool isNull() const { return unicode()==0; } + bool isPrint() const; + bool isPunct() const; + bool isSpace() const; + bool isMark() const; + bool isLetter() const; + bool isNumber() const; + bool isLetterOrNumber() const; + bool isDigit() const; + bool isSymbol() const; + + uchar cell() const { return ((uchar) ucs & 0xff); } + uchar row() const { return ((uchar) (ucs>>8)&0xff); } + void setCell( uchar cell ) { ucs = (ucs & 0xff00) + cell; } + void setRow( uchar row ) { ucs = (((ushort) row)<<8) + (ucs&0xff); } + + static bool networkOrdered() { + int wordSize; + bool bigEndian = FALSE; + qSysInfo( &wordSize, &bigEndian ); + return bigEndian; + } + + friend inline bool operator==( char ch, QChar c ); + friend inline bool operator==( QChar c, char ch ); + friend inline bool operator==( QChar c1, QChar c2 ); + friend inline bool operator!=( QChar c1, QChar c2 ); + friend inline bool operator!=( char ch, QChar c ); + friend inline bool operator!=( QChar c, char ch ); + friend inline bool operator<=( QChar c, char ch ); + friend inline bool operator<=( char ch, QChar c ); + friend inline bool operator<=( QChar c1, QChar c2 ); + +private: + ushort ucs; +#if defined(QT_QSTRING_UCS_4) + ushort grp; +#endif +} Q_PACKED; + +inline QChar::QChar() : ucs( 0 ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( char c ) : ucs( (uchar)c ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( uchar c ) : ucs( c ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( uchar c, uchar r ) : ucs( (r << 8) | c ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( const QChar& c ) : ucs( c.ucs ) +#ifdef QT_QSTRING_UCS_4 + , grp( c.grp ) +#endif +{ +} + +inline QChar::QChar( ushort rc ) : ucs( rc ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( short rc ) : ucs( (ushort) rc ) +#ifdef QT_QSTRING_UCS_4 + , grp( 0 ) +#endif +{ +} +inline QChar::QChar( uint rc ) : ucs( (ushort ) (rc & 0xffff) ) +#ifdef QT_QSTRING_UCS_4 + , grp( (ushort) ((rc >> 16) & 0xffff) ) +#endif +{ +} +inline QChar::QChar( int rc ) : ucs( (ushort) (rc & 0xffff) ) +#ifdef QT_QSTRING_UCS_4 + , grp( (ushort) ((rc >> 16) & 0xffff) ) +#endif +{ +} + +inline bool operator==( char ch, QChar c ) +{ + return ((uchar) ch) == c.ucs; +} + +inline bool operator==( QChar c, char ch ) +{ + return ((uchar) ch) == c.ucs; +} + +inline bool operator==( QChar c1, QChar c2 ) +{ + return c1.ucs == c2.ucs; +} + +inline bool operator!=( QChar c1, QChar c2 ) +{ + return c1.ucs != c2.ucs; +} + +inline bool operator!=( char ch, QChar c ) +{ + return ((uchar)ch) != c.ucs; +} + +inline bool operator!=( QChar c, char ch ) +{ + return ((uchar) ch) != c.ucs; +} + +inline bool operator<=( QChar c, char ch ) +{ + return c.ucs <= ((uchar) ch); +} + +inline bool operator<=( char ch, QChar c ) +{ + return ((uchar) ch) <= c.ucs; +} + +inline bool operator<=( QChar c1, QChar c2 ) +{ + return c1.ucs <= c2.ucs; +} + +inline bool operator>=( QChar c, char ch ) { return ch <= c; } +inline bool operator>=( char ch, QChar c ) { return c <= ch; } +inline bool operator>=( QChar c1, QChar c2 ) { return c2 <= c1; } +inline bool operator<( QChar c, char ch ) { return !(ch<=c); } +inline bool operator<( char ch, QChar c ) { return !(c<=ch); } +inline bool operator<( QChar c1, QChar c2 ) { return !(c2<=c1); } +inline bool operator>( QChar c, char ch ) { return !(ch>=c); } +inline bool operator>( char ch, QChar c ) { return !(c>=ch); } +inline bool operator>( QChar c1, QChar c2 ) { return !(c2>=c1); } + +// internal +struct Q_EXPORT QStringData : public QShared { + QStringData() : + QShared(), unicode(0), ascii(0), len(0), simpletext(1), maxl(0), dirty(0) { ref(); } + QStringData(QChar *u, uint l, uint m) : + QShared(), unicode(u), ascii(0), len(l), simpletext(1), maxl(m), dirty(1) { } + ~QStringData() { if ( unicode ) delete[] ((char*)unicode); + if ( ascii ) delete[] ascii; } + + void deleteSelf(); + QChar *unicode; + char *ascii; + void setDirty() { + if ( ascii ) { + delete [] ascii; + ascii = 0; + } + dirty = 1; + } +#ifdef Q_OS_MAC9 + uint len; +#else + uint len : 30; +#endif + uint simpletext : 1; +#ifdef Q_OS_MAC9 + uint maxl; +#else + uint maxl : 30; +#endif + uint dirty : 1; + +private: +#if defined(Q_DISABLE_COPY) + QStringData( const QStringData& ); + QStringData& operator=( const QStringData& ); +#endif +}; + + +class Q_EXPORT QString +{ +public: + QString(); // make null string + QString( QChar ); // one-char string + QString( const QString & ); // impl-shared copy + QString( const QByteArray& ); // deep copy + QString( const QChar* unicode, uint length ); // deep copy +#ifndef QT_NO_CAST_ASCII + QString( const char *str ); // deep copy +#endif + ~QString(); + + QString &operator=( const QString & ); // impl-shared copy +#ifndef QT_NO_CAST_ASCII + QString &operator=( const char * ); // deep copy +#endif + QString &operator=( const QCString& ); // deep copy + QString &operator=( QChar c ); + QString &operator=( char c ); + + QT_STATIC_CONST QString null; + + bool isNull() const; + bool isEmpty() const; + uint length() const; + void truncate( uint pos ); + + QString & fill( QChar c, int len = -1 ); + + QString copy() const; + + QString arg( long a, int fieldwidth=0, int base=10 ) const; + QString arg( ulong a, int fieldwidth=0, int base=10 ) const; + QString arg( int a, int fieldwidth=0, int base=10 ) const; + QString arg( uint a, int fieldwidth=0, int base=10 ) const; + QString arg( short a, int fieldwidth=0, int base=10 ) const; + QString arg( ushort a, int fieldwidth=0, int base=10 ) const; + QString arg( char a, int fieldwidth=0 ) const; + QString arg( QChar a, int fieldwidth=0 ) const; + QString arg( const QString& a, int fieldwidth=0 ) const; + QString arg( double a, int fieldwidth=0, char fmt='g', int prec=-1 ) const; + +#ifndef QT_NO_SPRINTF + QString &sprintf( const char* format, ... ) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; +#endif + + int find( QChar c, int index=0, bool cs=TRUE ) const; + int find( char c, int index=0, bool cs=TRUE ) const; + int find( const QString &str, int index=0, bool cs=TRUE ) const; +#ifndef QT_NO_REGEXP + int find( const QRegExp &, int index=0 ) const; +#endif +#ifndef QT_NO_CAST_ASCII + int find( const char* str, int index=0 ) const; +#endif + int findRev( QChar c, int index=-1, bool cs=TRUE) const; + int findRev( char c, int index=-1, bool cs=TRUE) const; + int findRev( const QString &str, int index=-1, bool cs=TRUE) const; +#ifndef QT_NO_REGEXP + int findRev( const QRegExp &, int index=-1 ) const; +#endif +#ifndef QT_NO_CAST_ASCII + int findRev( const char* str, int index=-1 ) const; +#endif + int contains( QChar c, bool cs=TRUE ) const; + int contains( char c, bool cs=TRUE ) const + { return contains(QChar(c), cs); } +#ifndef QT_NO_CAST_ASCII + int contains( const char* str, bool cs=TRUE ) const; +#endif + int contains( const QString &str, bool cs=TRUE ) const; +#ifndef QT_NO_REGEXP + int contains( const QRegExp & ) const; +#endif + + enum SectionFlags { + SectionDefault = 0x00, + SectionSkipEmpty = 0x01, + SectionIncludeLeadingSep = 0x02, + SectionIncludeTrailingSep = 0x04, + SectionCaseInsensitiveSeps = 0x08 + }; + QString section( QChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; + QString section( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; +#ifndef QT_NO_CAST_ASCII + QString section( const char *in_sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; +#endif + QString section( const QString &in_sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; +#ifndef QT_NO_REGEXP + QString section( const QRegExp ®, int start, int end = 0xffffffff, int flags = SectionDefault ) const; +#endif + + QString left( uint len ) const; + QString right( uint len ) const; + QString mid( uint index, uint len=0xffffffff) const; + + QString leftJustify( uint width, QChar fill=' ', bool trunc=FALSE)const; + QString rightJustify( uint width, QChar fill=' ',bool trunc=FALSE)const; + + QString lower() const; + QString upper() const; + + QString stripWhiteSpace() const; + QString simplifyWhiteSpace() const; + + QString &insert( uint index, const QString & ); + QString &insert( uint index, const QChar*, uint len ); + QString &insert( uint index, QChar ); + QString &insert( uint index, char c ) { return insert(index,QChar(c)); } + QString &append( char ); + QString &append( QChar ); + QString &append( const QString & ); +#ifndef QT_NO_CAST_ASCII + QString &append( const QByteArray & ); + QString &append( const char * ); +#endif + QString &prepend( char ); + QString &prepend( QChar ); + QString &prepend( const QString & ); +#ifndef QT_NO_CAST_ASCII + QString &prepend( const QByteArray & ); + QString &prepend( const char * ); +#endif + QString &remove( uint index, uint len ); + QString &remove( QChar c ); + QString &remove( char c ) { return remove( QChar(c) ); } + QString &remove( const QString & ); +#ifndef QT_NO_REGEXP + QString &remove( const QRegExp & ); +#endif +#ifndef QT_NO_CAST_ASCII + QString &remove( const char * ); +#endif + QString &replace( uint index, uint len, const QString & ); + QString &replace( uint index, uint len, const QChar*, uint clen ); + QString &replace( uint index, uint len, QChar ); + QString &replace( uint index, uint len, char c ) + { return replace( index, len, QChar(c) ); } + QString &replace( QChar c, const QString & ); + QString &replace( char c, const QString & after ) + { return replace( QChar(c), after ); } + QString &replace( const QString &, const QString & ); +#ifndef QT_NO_REGEXP_CAPTURE + QString &replace( const QRegExp &, const QString & ); +#endif + QString &replace( QChar, QChar ); + + short toShort( bool *ok=0, int base=10 ) const; + ushort toUShort( bool *ok=0, int base=10 ) const; + int toInt( bool *ok=0, int base=10 ) const; + uint toUInt( bool *ok=0, int base=10 ) const; + long toLong( bool *ok=0, int base=10 ) const; + ulong toULong( bool *ok=0, int base=10 ) const; + float toFloat( bool *ok=0 ) const; + double toDouble( bool *ok=0 ) const; + + QString &setNum( short, int base=10 ); + QString &setNum( ushort, int base=10 ); + QString &setNum( int, int base=10 ); + QString &setNum( uint, int base=10 ); + QString &setNum( long, int base=10 ); + QString &setNum( ulong, int base=10 ); + QString &setNum( float, char f='g', int prec=6 ); + QString &setNum( double, char f='g', int prec=6 ); + + static QString number( long, int base=10 ); + static QString number( ulong, int base=10); + static QString number( int, int base=10 ); + static QString number( uint, int base=10); + static QString number( double, char f='g', int prec=6 ); + + void setExpand( uint index, QChar c ); + + QString &operator+=( const QString &str ); +#ifndef QT_NO_CAST_ASCII + QString &operator+=( const QByteArray &str ); + QString &operator+=( const char *str ); +#endif + QString &operator+=( QChar c ); + QString &operator+=( char c ); + + QChar at( uint i ) const + { return i < d->len ? d->unicode[i] : QChar::null; } + QChar operator[]( int i ) const { return at((uint)i); } + QCharRef at( uint i ); + QCharRef operator[]( int i ); + + QChar constref(uint i) const + { return at(i); } + QChar& ref(uint i) + { // Optimized for easy-inlining by simple compilers. + if ( d->count != 1 || i >= d->len ) + subat( i ); + d->setDirty(); + return d->unicode[i]; + } + + const QChar* unicode() const { return d->unicode; } + const char* ascii() const { return latin1(); } + const char* latin1() const; + static QString fromLatin1(const char*, int len=-1); + QCString utf8() const; + static QString fromUtf8(const char*, int len=-1); + QCString local8Bit() const; + static QString fromLocal8Bit(const char*, int len=-1); + bool operator!() const; +#ifndef QT_NO_ASCII_CAST + operator const char *() const { return latin1(); } +#endif + static QString fromUcs2( const unsigned short *ucs2 ); + const unsigned short *ucs2() const; + + QString &setUnicode( const QChar* unicode, uint len ); + QString &setUnicodeCodes( const ushort* unicode_as_ushorts, uint len ); + QString &setLatin1( const char*, int len=-1 ); + + int compare( const QString& s ) const; + static int compare( const QString& s1, const QString& s2 ) + { return s1.compare( s2 ); } + + int localeAwareCompare( const QString& s ) const; + static int localeAwareCompare( const QString& s1, const QString& s2 ) + { return s1.localeAwareCompare( s2 ); } + +#ifndef QT_NO_DATASTREAM + friend Q_EXPORT QDataStream &operator>>( QDataStream &, QString & ); +#endif + + void compose(); + +#ifndef QT_NO_COMPAT + const char* data() const { return latin1(); } +#endif + + bool startsWith( const QString& ) const; + bool endsWith( const QString& ) const; + + void setLength( uint newLength ); + + bool simpleText() const { if ( d->dirty ) checkSimpleText(); return (bool)d->simpletext; } + bool isRightToLeft() const; + + +private: + QString( int size, bool /* dummy */ ); // allocate size incl. \0 + + void deref(); + void real_detach(); + void subat( uint ); + bool findArg(int& pos, int& len) const; + + void checkSimpleText() const; + + static QChar* asciiToUnicode( const char*, uint * len, uint maxlen=(uint)-1 ); + static QChar* asciiToUnicode( const QByteArray&, uint * len ); + static char* unicodeToAscii( const QChar*, uint len ); + + QStringData *d; + static QStringData* shared_null; + static QStringData* makeSharedNull(); + + friend class QConstString; + friend class QTextStream; + QString( QStringData* dd, bool /* dummy */ ) : d(dd) { } + + // needed for QDeepCopy + void detach(); + friend class QDeepCopy<QString>; +}; + +class Q_EXPORT QCharRef { + friend class QString; + QString& s; + uint p; + QCharRef(QString* str, uint pos) : s(*str), p(pos) { } + +public: + // most QChar operations repeated here... + + // all this is not documented: We just say "like QChar" and let it be. +#ifndef Q_QDOC + ushort unicode() const { return s.constref(p).unicode(); } + char latin1() const { return s.constref(p).latin1(); } + + // An operator= for each QChar cast constructor... + QCharRef operator=(char c ) { s.ref(p)=c; return *this; } + QCharRef operator=(uchar c ) { s.ref(p)=c; return *this; } + QCharRef operator=(QChar c ) { s.ref(p)=c; return *this; } + QCharRef operator=(const QCharRef& c ) { s.ref(p)=c.unicode(); return *this; } + QCharRef operator=(ushort rc ) { s.ref(p)=rc; return *this; } + QCharRef operator=(short rc ) { s.ref(p)=rc; return *this; } + QCharRef operator=(uint rc ) { s.ref(p)=rc; return *this; } + QCharRef operator=(int rc ) { s.ref(p)=rc; return *this; } + + operator QChar () const { return s.constref(p); } + + // each function... + bool isNull() const { return unicode()==0; } + bool isPrint() const { return s.constref(p).isPrint(); } + bool isPunct() const { return s.constref(p).isPunct(); } + bool isSpace() const { return s.constref(p).isSpace(); } + bool isMark() const { return s.constref(p).isMark(); } + bool isLetter() const { return s.constref(p).isLetter(); } + bool isNumber() const { return s.constref(p).isNumber(); } + bool isLetterOrNumber() { return s.constref(p).isLetterOrNumber(); } + bool isDigit() const { return s.constref(p).isDigit(); } + + int digitValue() const { return s.constref(p).digitValue(); } + QChar lower() const { return s.constref(p).lower(); } + QChar upper() const { return s.constref(p).upper(); } + + QChar::Category category() const { return s.constref(p).category(); } + QChar::Direction direction() const { return s.constref(p).direction(); } + QChar::Joining joining() const { return s.constref(p).joining(); } + bool mirrored() const { return s.constref(p).mirrored(); } + QChar mirroredChar() const { return s.constref(p).mirroredChar(); } + const QString &decomposition() const { return s.constref(p).decomposition(); } + QChar::Decomposition decompositionTag() const { return s.constref(p).decompositionTag(); } + unsigned char combiningClass() const { return s.constref(p).combiningClass(); } + + // Not the non-const ones of these. + uchar cell() const { return s.constref(p).cell(); } + uchar row() const { return s.constref(p).row(); } +#endif +}; + +inline QCharRef QString::at( uint i ) { return QCharRef(this,i); } +inline QCharRef QString::operator[]( int i ) { return at((uint)i); } + + +class Q_EXPORT QConstString : private QString { +public: + QConstString( const QChar* unicode, uint length ); + ~QConstString(); + const QString& string() const { return *this; } +}; + + +/***************************************************************************** + QString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QString & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QString & ); +#endif + +/***************************************************************************** + QString inline functions + *****************************************************************************/ + +// These two move code into makeSharedNull() and deletesData() +// to improve cache-coherence (and reduce code bloat), while +// keeping the common cases fast. +// +// No safe way to pre-init shared_null on ALL compilers/linkers. +inline QString::QString() : + d(shared_null ? shared_null : makeSharedNull()) +{ + d->ref(); +} +// +inline QString::~QString() +{ + if ( d->deref() ) { + if ( d != shared_null ) + d->deleteSelf(); + } +} + +// needed for QDeepCopy +inline void QString::detach() +{ real_detach(); } + +inline QString QString::section( QChar sep, int start, int end, int flags ) const +{ return section(QString(sep), start, end, flags); } + +inline QString QString::section( char sep, int start, int end, int flags ) const +{ return section(QChar(sep), start, end, flags); } + +#ifndef QT_NO_CAST_ASCII +inline QString QString::section( const char *in_sep, int start, int end, int flags ) const +{ return section(QString(in_sep), start, end, flags); } +#endif + +inline QString &QString::operator=( QChar c ) +{ *this = QString(c); return *this; } + +inline QString &QString::operator=( char c ) +{ *this = QString(QChar(c)); return *this; } + +inline bool QString::isNull() const +{ return unicode() == 0; } + +inline bool QString::operator!() const +{ return isNull(); } + +inline uint QString::length() const +{ return d->len; } + +inline bool QString::isEmpty() const +{ return length() == 0; } + +inline QString QString::copy() const +{ return QString( *this ); } + +inline QString &QString::prepend( const QString & s ) +{ return insert(0,s); } + +inline QString &QString::prepend( QChar c ) +{ return insert(0,c); } + +inline QString &QString::prepend( char c ) +{ return insert(0,c); } + +#ifndef QT_NO_CAST_ASCII +inline QString &QString::prepend( const QByteArray & s ) +{ return insert(0,s.data()); } +#endif + +inline QString &QString::append( const QString & s ) +{ return operator+=(s); } + +#ifndef QT_NO_CAST_ASCII +inline QString &QString::append( const QByteArray &s ) +{ return operator+=(s.data()); } + +inline QString &QString::append( const char * s ) +{ return operator+=(s); } +#endif + +inline QString &QString::append( QChar c ) +{ return operator+=(c); } + +inline QString &QString::append( char c ) +{ return operator+=(c); } + +#ifndef QT_NO_CAST_ASCII +inline QString &QString::operator+=( const QByteArray &s ) +{ return operator+=(s.data()); } +#endif + +inline QString &QString::setNum( short n, int base ) +{ return setNum((long)n, base); } + +inline QString &QString::setNum( ushort n, int base ) +{ return setNum((ulong)n, base); } + +inline QString &QString::setNum( int n, int base ) +{ return setNum((long)n, base); } + +inline QString &QString::setNum( uint n, int base ) +{ return setNum((ulong)n, base); } + +inline QString &QString::setNum( float n, char f, int prec ) +{ return setNum((double)n,f,prec); } + +inline QString QString::arg(int a, int fieldwidth, int base) const +{ return arg((long)a, fieldwidth, base); } + +inline QString QString::arg(uint a, int fieldwidth, int base) const +{ return arg((ulong)a, fieldwidth, base); } + +inline QString QString::arg(short a, int fieldwidth, int base) const +{ return arg((long)a, fieldwidth, base); } + +inline QString QString::arg(ushort a, int fieldwidth, int base) const +{ return arg((ulong)a, fieldwidth, base); } + +inline int QString::find( char c, int index, bool cs ) const +{ return find(QChar(c), index, cs); } + +inline int QString::findRev( char c, int index, bool cs) const +{ return findRev( QChar(c), index, cs ); } + +#ifndef QT_NO_CAST_ASCII +inline int QString::find( const char* str, int index ) const +{ return find(QString::fromLatin1(str), index); } + +inline int QString::findRev( const char* str, int index ) const +{ return findRev(QString::fromLatin1(str), index); } +#endif + + +/***************************************************************************** + QString non-member operators + *****************************************************************************/ + +Q_EXPORT bool operator!=( const QString &s1, const QString &s2 ); +Q_EXPORT bool operator<( const QString &s1, const QString &s2 ); +Q_EXPORT bool operator<=( const QString &s1, const QString &s2 ); +Q_EXPORT bool operator==( const QString &s1, const QString &s2 ); +Q_EXPORT bool operator>( const QString &s1, const QString &s2 ); +Q_EXPORT bool operator>=( const QString &s1, const QString &s2 ); +#ifndef QT_NO_CAST_ASCII +Q_EXPORT bool operator!=( const QString &s1, const char *s2 ); +Q_EXPORT bool operator<( const QString &s1, const char *s2 ); +Q_EXPORT bool operator<=( const QString &s1, const char *s2 ); +Q_EXPORT bool operator==( const QString &s1, const char *s2 ); +Q_EXPORT bool operator>( const QString &s1, const char *s2 ); +Q_EXPORT bool operator>=( const QString &s1, const char *s2 ); +Q_EXPORT bool operator!=( const char *s1, const QString &s2 ); +Q_EXPORT bool operator<( const char *s1, const QString &s2 ); +Q_EXPORT bool operator<=( const char *s1, const QString &s2 ); +Q_EXPORT bool operator==( const char *s1, const QString &s2 ); +//Q_EXPORT bool operator>( const char *s1, const QString &s2 ); // MSVC++ +Q_EXPORT bool operator>=( const char *s1, const QString &s2 ); +#endif + +Q_EXPORT inline const QString operator+( const QString &s1, const QString &s2 ) +{ + QString tmp( s1 ); + tmp += s2; + return tmp; +} + +#ifndef QT_NO_CAST_ASCII +Q_EXPORT inline const QString operator+( const QString &s1, const char *s2 ) +{ + QString tmp( s1 ); + tmp += QString::fromLatin1(s2); + return tmp; +} + +Q_EXPORT inline const QString operator+( const char *s1, const QString &s2 ) +{ + QString tmp = QString::fromLatin1( s1 ); + tmp += s2; + return tmp; +} +#endif + +Q_EXPORT inline const QString operator+( const QString &s1, QChar c2 ) +{ + QString tmp( s1 ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline const QString operator+( const QString &s1, char c2 ) +{ + QString tmp( s1 ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline const QString operator+( QChar c1, const QString &s2 ) +{ + QString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +Q_EXPORT inline const QString operator+( char c1, const QString &s2 ) +{ + QString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +#if defined(Q_OS_WIN32) +extern Q_EXPORT QString qt_winQString(void*); +extern Q_EXPORT const void* qt_winTchar(const QString& str, bool addnul); +extern Q_EXPORT void* qt_winTchar_new(const QString& str); +extern Q_EXPORT QCString qt_winQString2MB( const QString& s, int len=-1 ); +extern Q_EXPORT QString qt_winMB2QString( const char* mb, int len=-1 ); +#endif + +#endif // QSTRING_H diff --git a/qmake/include/qstringlist.h b/qmake/include/qstringlist.h new file mode 100644 index 0000000..be9d6ae --- a/dev/null +++ b/qmake/include/qstringlist.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QStringList class +** +** Created : 990406 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSTRINGLIST_H +#define QSTRINGLIST_H + +#ifndef QT_H +#include "qvaluelist.h" +#include "qstring.h" +#include "qstrlist.h" +#endif // QT_H + +#ifndef QT_NO_STRINGLIST + +class QRegExp; + +class Q_EXPORT QStringList : public QValueList<QString> +{ +public: + QStringList() { } + QStringList( const QStringList& l ) : QValueList<QString>(l) { } + QStringList( const QValueList<QString>& l ) : QValueList<QString>(l) { } + QStringList( const QString& i ) { append(i); } +#ifndef QT_NO_CAST_ASCII + QStringList( const char* i ) { append(i); } +#endif + + static QStringList fromStrList(const QStrList&); + + void sort(); + + static QStringList split( const QString &sep, const QString &str, bool allowEmptyEntries = FALSE ); + static QStringList split( const QChar &sep, const QString &str, bool allowEmptyEntries = FALSE ); +#ifndef QT_NO_REGEXP + static QStringList split( const QRegExp &sep, const QString &str, bool allowEmptyEntries = FALSE ); +#endif + QString join( const QString &sep ) const; + + QStringList grep( const QString &str, bool cs = TRUE ) const; +#ifndef QT_NO_REGEXP + QStringList grep( const QRegExp &expr ) const; +#endif +}; + +#ifndef QT_NO_DATASTREAM +class QDataStream; +extern Q_EXPORT QDataStream &operator>>( QDataStream &, QStringList& ); +extern Q_EXPORT QDataStream &operator<<( QDataStream &, const QStringList& ); +#endif + +#endif // QT_NO_STRINGLIST +#endif // QSTRINGLIST_H diff --git a/qmake/include/qstrlist.h b/qmake/include/qstrlist.h new file mode 100644 index 0000000..86de328 --- a/dev/null +++ b/qmake/include/qstrlist.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QStrList, QStrIList and QStrListIterator classes +** +** Created : 920730 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QSTRLIST_H +#define QSTRLIST_H + +#ifndef QT_H +#include "qstring.h" +#include "qptrlist.h" +#include "qdatastream.h" +#endif // QT_H + + +#if defined(Q_TEMPLATEDLL) +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<char>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrListIterator<char>; +#endif + +#if defined(Q_QDOC) +class QStrListIterator : public QPtrListIterator<char> +{ +}; +#else +typedef QPtrListIterator<char> QStrListIterator; +#endif + +class Q_EXPORT QStrList : public QPtrList<char> +{ +public: + QStrList( bool deepCopies=TRUE ) { dc = deepCopies; del_item = deepCopies; } + QStrList( const QStrList & ); + ~QStrList() { clear(); } + QStrList& operator=( const QStrList & ); + +private: + QPtrCollection::Item newItem( QPtrCollection::Item d ) { return dc ? qstrdup( (const char*)d ) : d; } + void deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete[] (char*)d; } + int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 ) { return qstrcmp((const char*)s1, + (const char*)s2); } +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream &s, QPtrCollection::Item &d ) + { s >> (char *&)d; return s; } + QDataStream &write( QDataStream &s, QPtrCollection::Item d ) const + { return s << (const char *)d; } +#endif + bool dc; +}; + + +class Q_EXPORT QStrIList : public QStrList // case insensitive string list +{ +public: + QStrIList( bool deepCopies=TRUE ) : QStrList( deepCopies ) {} + ~QStrIList() { clear(); } +private: + int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 ) + { return qstricmp((const char*)s1, + (const char*)s2); } +}; + + +inline QStrList & QStrList::operator=( const QStrList &strList ) +{ + clear(); + dc = strList.dc; + del_item = dc; + QPtrList<char>::operator=( strList ); + return *this; +} + +inline QStrList::QStrList( const QStrList &strList ) + : QPtrList<char>( strList ) +{ + dc = FALSE; + operator=( strList ); +} + +#endif // QSTRLIST_H diff --git a/qmake/include/qtextcodec.h b/qmake/include/qtextcodec.h new file mode 100644 index 0000000..149b5cb --- a/dev/null +++ b/qmake/include/qtextcodec.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QTextCodec class +** +** Created : 981015 +** +** Copyright (C) 1998-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTEXTCODEC_H +#define QTEXTCODEC_H + +#ifndef QT_H +#include "qstring.h" +#endif // QT_H + +#ifndef QT_NO_TEXTCODEC + +class QTextCodec; +class QIODevice; +class QFont; + +class Q_EXPORT QTextEncoder { +public: + virtual ~QTextEncoder(); + virtual QCString fromUnicode(const QString& uc, int& lenInOut) = 0; +}; + +class Q_EXPORT QTextDecoder { +public: + virtual ~QTextDecoder(); + virtual QString toUnicode(const char* chars, int len) = 0; +}; + +class Q_EXPORT QTextCodec { +public: + virtual ~QTextCodec(); + +#ifndef QT_NO_CODECS + static QTextCodec* loadCharmap(QIODevice*); + static QTextCodec* loadCharmapFile(QString filename); +#endif //QT_NO_CODECS + static QTextCodec* codecForMib(int mib); + static QTextCodec* codecForName(const char* hint, int accuracy=0); + static QTextCodec* codecForContent(const char* chars, int len); + static QTextCodec* codecForIndex(int i); + static QTextCodec* codecForLocale(); + static void setCodecForLocale(QTextCodec *c); + + static void deleteAllCodecs(); + + static const char* locale(); + + virtual const char* name() const = 0; + virtual const char* mimeName() const; + virtual int mibEnum() const = 0; + + virtual QTextDecoder* makeDecoder() const; + virtual QTextEncoder* makeEncoder() const; + + virtual QString toUnicode(const char* chars, int len) const; + virtual QCString fromUnicode(const QString& uc, int& lenInOut) const; + + QCString fromUnicode(const QString& uc) const; + QString toUnicode(const QByteArray&, int len) const; + QString toUnicode(const QByteArray&) const; + QString toUnicode(const QCString&, int len) const; + QString toUnicode(const QCString&) const; + QString toUnicode(const char* chars) const; + virtual bool canEncode( QChar ) const; + virtual bool canEncode( const QString& ) const; + + virtual int heuristicContentMatch(const char* chars, int len) const = 0; + virtual int heuristicNameMatch(const char* hint) const; + + virtual QByteArray fromUnicode(const QString& uc, int from, int len) const; + virtual unsigned short characterFromUnicode(const QString &str, int pos) const; + +protected: + QTextCodec(); + static int simpleHeuristicNameMatch(const char* name, const char* hint); + + friend class QFont; +}; +#endif // QT_NO_TEXTCODEC +#endif // QTEXTCODEC_H diff --git a/qmake/include/qtextstream.h b/qmake/include/qtextstream.h new file mode 100644 index 0000000..6979ed7 --- a/dev/null +++ b/qmake/include/qtextstream.h @@ -0,0 +1,335 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QTextStream class +** +** Created : 940922 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTEXTSTREAM_H +#define QTEXTSTREAM_H + +#ifndef QT_H +#include "qiodevice.h" +#include "qstring.h" +#include <stdio.h> +#endif // QT_H + +#ifndef QT_NO_TEXTSTREAM +class QTextCodec; +class QTextDecoder; + +class QTextStreamPrivate; + +class Q_EXPORT QTextStream // text stream class +{ +public: + enum Encoding { Locale, Latin1, Unicode, UnicodeNetworkOrder, + UnicodeReverse, RawUnicode, UnicodeUTF8 }; + + void setEncoding( Encoding ); +#ifndef QT_NO_TEXTCODEC + void setCodec( QTextCodec* ); + QTextCodec *codec(); +#endif + + QTextStream(); + QTextStream( QIODevice * ); + QTextStream( QString*, int mode ); + QTextStream( QString&, int mode ); // obsolete + QTextStream( QByteArray, int mode ); + QTextStream( FILE *, int mode ); + virtual ~QTextStream(); + + QIODevice *device() const; + void setDevice( QIODevice * ); + void unsetDevice(); + + bool atEnd() const; + bool eof() const; + + QTextStream &operator>>( QChar & ); + QTextStream &operator>>( char & ); + QTextStream &operator>>( signed short & ); + QTextStream &operator>>( unsigned short & ); + QTextStream &operator>>( signed int & ); + QTextStream &operator>>( unsigned int & ); + QTextStream &operator>>( signed long & ); + QTextStream &operator>>( unsigned long & ); + QTextStream &operator>>( float & ); + QTextStream &operator>>( double & ); + QTextStream &operator>>( char * ); + QTextStream &operator>>( QString & ); + QTextStream &operator>>( QCString & ); + + QTextStream &operator<<( QChar ); + QTextStream &operator<<( char ); + QTextStream &operator<<( signed short ); + QTextStream &operator<<( unsigned short ); + QTextStream &operator<<( signed int ); + QTextStream &operator<<( unsigned int ); + QTextStream &operator<<( signed long ); + QTextStream &operator<<( unsigned long ); + QTextStream &operator<<( float ); + QTextStream &operator<<( double ); + QTextStream &operator<<( const char* ); + QTextStream &operator<<( const QString & ); + QTextStream &operator<<( const QCString & ); + QTextStream &operator<<( void * ); // any pointer + + QTextStream &readRawBytes( char *, uint len ); + QTextStream &writeRawBytes( const char* , uint len ); + + QString readLine(); + QString read(); + void skipWhiteSpace(); + + enum { + skipws = 0x0001, // skip whitespace on input + left = 0x0002, // left-adjust output + right = 0x0004, // right-adjust output + internal = 0x0008, // pad after sign + bin = 0x0010, // binary format integer + oct = 0x0020, // octal format integer + dec = 0x0040, // decimal format integer + hex = 0x0080, // hex format integer + showbase = 0x0100, // show base indicator + showpoint = 0x0200, // force decimal point (float) + uppercase = 0x0400, // upper-case hex output + showpos = 0x0800, // add '+' to positive integers + scientific= 0x1000, // scientific float output + fixed = 0x2000 // fixed float output + }; + + static const int basefield; // bin | oct | dec | hex + static const int adjustfield; // left | right | internal + static const int floatfield; // scientific | fixed + + int flags() const; + int flags( int f ); + int setf( int bits ); + int setf( int bits, int mask ); + int unsetf( int bits ); + + void reset(); + + int width() const; + int width( int ); + int fill() const; + int fill( int ); + int precision() const; + int precision( int ); + +private: + long input_int(); + void init(); + QTextStream &output_int( int, ulong, bool ); + QIODevice *dev; + + int fflags; + int fwidth; + int fillchar; + int fprec; + bool doUnicodeHeader; + bool owndev; + QTextCodec *mapper; + QTextStreamPrivate * d; + QChar unused1; // ### remove in Qt 4.0 + bool latin1; + bool internalOrder; + bool networkOrder; + void *unused2; // ### remove in Qt 4.0 + + QChar eat_ws(); + uint ts_getline( QChar* ); + void ts_ungetc( QChar ); + QChar ts_getc(); + uint ts_getbuf( QChar*, uint ); + void ts_putc(int); + void ts_putc(QChar); + bool ts_isspace(QChar); + bool ts_isdigit(QChar); + ulong input_bin(); + ulong input_oct(); + ulong input_dec(); + ulong input_hex(); + double input_double(); + QTextStream &writeBlock( const char* p, uint len ); + QTextStream &writeBlock( const QChar* p, uint len ); + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QTextStream( const QTextStream & ); + QTextStream &operator=( const QTextStream & ); +#endif +}; + +typedef QTextStream QTS; + +class Q_EXPORT QTextIStream : public QTextStream { +public: + QTextIStream( const QString* s ) : + QTextStream((QString*)s,IO_ReadOnly) { } + QTextIStream( QByteArray ba ) : + QTextStream(ba,IO_ReadOnly) { } + QTextIStream( FILE *f ) : + QTextStream(f,IO_ReadOnly) { } + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QTextIStream( const QTextIStream & ); + QTextIStream &operator=( const QTextIStream & ); +#endif +}; + +class Q_EXPORT QTextOStream : public QTextStream { +public: + QTextOStream( QString* s ) : + QTextStream(s,IO_WriteOnly) { } + QTextOStream( QByteArray ba ) : + QTextStream(ba,IO_WriteOnly) { } + QTextOStream( FILE *f ) : + QTextStream(f,IO_WriteOnly) { } + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QTextOStream( const QTextOStream & ); + QTextOStream &operator=( const QTextOStream & ); +#endif +}; + +/***************************************************************************** + QTextStream inline functions + *****************************************************************************/ + +inline QIODevice *QTextStream::device() const +{ return dev; } + +inline bool QTextStream::atEnd() const +{ return dev ? dev->atEnd() : FALSE; } + +inline bool QTextStream::eof() const +{ return atEnd(); } + +inline int QTextStream::flags() const +{ return fflags; } + +inline int QTextStream::flags( int f ) +{ int oldf = fflags; fflags = f; return oldf; } + +inline int QTextStream::setf( int bits ) +{ int oldf = fflags; fflags |= bits; return oldf; } + +inline int QTextStream::setf( int bits, int mask ) +{ int oldf = fflags; fflags = (fflags & ~mask) | (bits & mask); return oldf; } + +inline int QTextStream::unsetf( int bits ) +{ int oldf = fflags; fflags &= ~bits; return oldf; } + +inline int QTextStream::width() const +{ return fwidth; } + +inline int QTextStream::width( int w ) +{ int oldw = fwidth; fwidth = w; return oldw; } + +inline int QTextStream::fill() const +{ return fillchar; } + +inline int QTextStream::fill( int f ) +{ int oldc = fillchar; fillchar = f; return oldc; } + +inline int QTextStream::precision() const +{ return fprec; } + +inline int QTextStream::precision( int p ) +{ int oldp = fprec; fprec = p; return oldp; } + +/*! + Returns one character from the stream, or EOF. +*/ +inline QChar QTextStream::ts_getc() +{ QChar r; return ( ts_getbuf( &r,1 ) == 1 ? r : QChar((ushort)0xffff) ); } + +/***************************************************************************** + QTextStream manipulators + *****************************************************************************/ + +typedef QTextStream & (*QTSFUNC)(QTextStream &);// manipulator function +typedef int (QTextStream::*QTSMFI)(int); // manipulator w/int argument + +class Q_EXPORT QTSManip { // text stream manipulator +public: + QTSManip( QTSMFI m, int a ) { mf=m; arg=a; } + void exec( QTextStream &s ) { (s.*mf)(arg); } +private: + QTSMFI mf; // QTextStream member function + int arg; // member function argument +}; + +Q_EXPORT inline QTextStream &operator>>( QTextStream &s, QTSFUNC f ) +{ return (*f)( s ); } + +Q_EXPORT inline QTextStream &operator<<( QTextStream &s, QTSFUNC f ) +{ return (*f)( s ); } + +Q_EXPORT inline QTextStream &operator<<( QTextStream &s, QTSManip m ) +{ m.exec(s); return s; } + +Q_EXPORT QTextStream &bin( QTextStream &s ); // set bin notation +Q_EXPORT QTextStream &oct( QTextStream &s ); // set oct notation +Q_EXPORT QTextStream &dec( QTextStream &s ); // set dec notation +Q_EXPORT QTextStream &hex( QTextStream &s ); // set hex notation +Q_EXPORT QTextStream &endl( QTextStream &s ); // insert EOL ('\n') +Q_EXPORT QTextStream &flush( QTextStream &s ); // flush output +Q_EXPORT QTextStream &ws( QTextStream &s ); // eat whitespace on input +Q_EXPORT QTextStream &reset( QTextStream &s ); // set default flags + +Q_EXPORT inline QTSManip qSetW( int w ) +{ + QTSMFI func = &QTextStream::width; + return QTSManip(func,w); +} + +Q_EXPORT inline QTSManip qSetFill( int f ) +{ + QTSMFI func = &QTextStream::fill; + return QTSManip(func,f); +} + +Q_EXPORT inline QTSManip qSetPrecision( int p ) +{ + QTSMFI func = &QTextStream::precision; + return QTSManip(func,p); +} + +#endif // QT_NO_TEXTSTREAM +#endif // QTEXTSTREAM_H diff --git a/qmake/include/qtl.h b/qmake/include/qtl.h new file mode 100644 index 0000000..346cecc --- a/dev/null +++ b/qmake/include/qtl.h @@ -0,0 +1,321 @@ +/**************************************************************************** +** $Id$ +** +** Definition of Qt template library classes +** +** Created : 990128 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QTL_H +#define QTL_H + +#ifndef QT_H +#include "qglobal.h" +#include "qtextstream.h" +#include "qstring.h" +#endif // QT_H + +#ifndef QT_NO_TEXTSTREAM +template <class T> +class QTextOStreamIterator +{ +protected: + QTextOStream& stream; + QString separator; + +public: + QTextOStreamIterator( QTextOStream& s) : stream( s ) {} + QTextOStreamIterator( QTextOStream& s, const QString& sep ) + : stream( s ), separator( sep ) {} + QTextOStreamIterator<T>& operator= ( const T& x ) { + stream << x; + if ( !separator.isEmpty() ) + stream << separator; + return *this; + } + QTextOStreamIterator<T>& operator*() { return *this; } + QTextOStreamIterator<T>& operator++() { return *this; } + QTextOStreamIterator<T>& operator++(int) { return *this; } +}; +#endif //QT_NO_TEXTSTREAM + +template <class InputIterator, class OutputIterator> +inline OutputIterator qCopy( InputIterator _begin, InputIterator _end, + OutputIterator _dest ) +{ + while( _begin != _end ) + *_dest++ = *_begin++; + return _dest; +} + +template <class BiIterator, class BiOutputIterator> +inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end, + BiOutputIterator _dest ) +{ + while ( _begin != _end ) + *--_dest = *--_end; + return _dest; +} + +template <class InputIterator1, class InputIterator2> +inline bool qEqual( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 ) +{ + for ( ; first1 != last1; ++first1, ++first2 ) + if ( *first1 != *first2 ) + return FALSE; + return TRUE; +} + +template <class ForwardIterator, class T> +inline void qFill( ForwardIterator first, ForwardIterator last, const T& val ) +{ + for ( ; first != last; ++first ) + *first = val; +} + +#if 0 +template <class BiIterator, class OutputIterator> +inline OutputIterator qReverseCopy( BiIterator _begin, BiIterator _end, + OutputIterator _dest ) +{ + while ( _begin != _end ) { + --_end; + *_dest = *_end; + ++_dest; + } + return _dest; +} +#endif + + +template <class InputIterator, class T> +inline InputIterator qFind( InputIterator first, InputIterator last, + const T& val ) +{ + while ( first != last && *first != val ) + ++first; + return first; +} + +template <class InputIterator, class T, class Size> +inline void qCount( InputIterator first, InputIterator last, const T& value, + Size& n ) +{ + for ( ; first != last; ++first ) + if ( *first == value ) + ++n; +} + +template <class T> +inline void qSwap( T& _value1, T& _value2 ) +{ + T tmp = _value1; + _value1 = _value2; + _value2 = tmp; +} + + +template <class InputIterator> +Q_INLINE_TEMPLATES void qBubbleSort( InputIterator b, InputIterator e ) +{ + // Goto last element; + InputIterator last = e; + --last; + // only one element or no elements ? + if ( last == b ) + return; + + // So we have at least two elements in here + while( b != last ) { + bool swapped = FALSE; + InputIterator swap_pos = b; + InputIterator x = e; + InputIterator y = x; + y--; + do { + --x; + --y; + if ( *x < *y ) { + swapped = TRUE; + qSwap( *x, *y ); + swap_pos = y; + } + } while( y != b ); + if ( !swapped ) + return; + b = swap_pos; + b++; + } +} + + +template <class Container> +inline void qBubbleSort( Container &c ) +{ + qBubbleSort( c.begin(), c.end() ); +} + + +template <class Value> +Q_INLINE_TEMPLATES void qHeapSortPushDown( Value* heap, int first, int last ) +{ + int r = first; + while ( r <= last / 2 ) { + if ( last == 2 * r ) { + // node r has only one child + if ( heap[2 * r] < heap[r] ) + qSwap( heap[r], heap[2 * r] ); + r = last; + } else { + // node r has two children + if ( heap[2 * r] < heap[r] && !(heap[2 * r + 1] < heap[2 * r]) ) { + // swap with left child + qSwap( heap[r], heap[2 * r] ); + r *= 2; + } else if ( heap[2 * r + 1] < heap[r] + && heap[2 * r + 1] < heap[2 * r] ) { + // swap with right child + qSwap( heap[r], heap[2 * r + 1] ); + r = 2 * r + 1; + } else { + r = last; + } + } + } +} + + +template <class InputIterator, class Value> +Q_INLINE_TEMPLATES void qHeapSortHelper( InputIterator b, InputIterator e, Value, uint n ) +{ + // Create the heap + InputIterator insert = b; + Value* realheap = new Value[n]; + // Wow, what a fake. But I want the heap to be indexed as 1...n + Value* heap = realheap - 1; + int size = 0; + for( ; insert != e; ++insert ) { + heap[++size] = *insert; + int i = size; + while( i > 1 && heap[i] < heap[i / 2] ) { + qSwap( heap[i], heap[i / 2] ); + i /= 2; + } + } + + // Now do the sorting + for( uint i = n; i > 0; i-- ) { + *b++ = heap[1]; + if ( i > 1 ) { + heap[1] = heap[i]; + qHeapSortPushDown( heap, 1, (int)i - 1 ); + } + } + + delete[] realheap; +} + + +template <class InputIterator> +Q_INLINE_TEMPLATES void qHeapSort( InputIterator b, InputIterator e ) +{ + // Empty ? + if ( b == e ) + return; + + // How many entries have to be sorted ? + InputIterator it = b; + uint n = 0; + while ( it != e ) { + ++n; + ++it; + } + + // The second last parameter is a hack to retrieve the value type + // Do the real sorting here + qHeapSortHelper( b, e, *b, n ); +} + + +template <class Container> +Q_INLINE_TEMPLATES void qHeapSort( Container &c ) +{ + if ( c.begin() == c.end() ) + return; + + // The second last parameter is a hack to retrieve the value type + // Do the real sorting here + qHeapSortHelper( c.begin(), c.end(), *(c.begin()), (uint)c.count() ); +} + +template <class Container> +class QBackInsertIterator +{ +public: + Q_EXPLICIT QBackInsertIterator( Container &c ) + : container( &c ) + { + } + + QBackInsertIterator<Container>& + operator=( const Q_TYPENAME Container::value_type &value ) + { + container->push_back( value ); + return *this; + } + + QBackInsertIterator<Container>& operator*() + { + return *this; + } + + QBackInsertIterator<Container>& operator++() + { + return *this; + } + + QBackInsertIterator<Container>& operator++(int) + { + return *this; + } + +protected: + Container *container; +}; + +template <class Container> +inline QBackInsertIterator<Container> qBackInserter( Container &c ) +{ + return QBackInsertIterator<Container>( c ); +} + +#endif diff --git a/qmake/include/quuid.h b/qmake/include/quuid.h new file mode 100644 index 0000000..591d2f1 --- a/dev/null +++ b/qmake/include/quuid.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QUuid class +** +** Created: 010523 +** +** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QUUID_H +#define QUUID_H + +#ifndef QT_H +#include <qstring.h> +#endif // QT_H + +#include <string.h> + +#if defined(Q_OS_WIN32) +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + ulong Data1; + ushort Data2; + ushort Data3; + uchar Data4[ 8 ]; +} GUID; +#endif +#endif + +struct Q_EXPORT QUuid +{ + QUuid() + { + memset( this, 0, sizeof(QUuid) ); + } + QUuid( uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8 ) + { + data1 = l; + data2 = w1; + data3 = w2; + data4[0] = b1; + data4[1] = b2; + data4[2] = b3; + data4[3] = b4; + data4[4] = b5; + data4[5] = b6; + data4[6] = b7; + data4[7] = b8; + } + QUuid( const QUuid &uuid ) + { + memcpy( this, &uuid, sizeof(QUuid) ); + } +#ifndef QT_NO_QUUID_STRING + QUuid( const QString & ); + QUuid( const char * ); + QString toString() const; + operator QString() const { return toString(); } +#endif + bool isNull() const; + + QUuid &operator=(const QUuid &orig ) + { + memcpy( this, &orig, sizeof(QUuid) ); + return *this; + } + + bool operator==(const QUuid &orig ) const + { + uint i; + if ( data1 != orig.data1 || data2 != orig.data2 || + data3 != orig.data3 ) + return FALSE; + + for( i = 0; i < 8; i++ ) + if ( data4[i] != orig.data4[i] ) + return FALSE; + + return TRUE; + } + + bool operator!=(const QUuid &orig ) const + { + return !( *this == orig ); + } + +#if defined(Q_OS_WIN32) + // On Windows we have a type GUID that is used by the platform API, so we + // provide convenience operators to cast from and to this type. + QUuid( const GUID &guid ) + { + memcpy( this, &guid, sizeof(GUID) ); + } + + QUuid &operator=(const GUID &orig ) + { + memcpy( this, &orig, sizeof(QUuid) ); + return *this; + } + + operator GUID() const + { + GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } }; + return guid; + } + + bool operator==( const GUID &guid ) const + { + uint i; + if ( data1 != guid.Data1 || data2 != guid.Data2 || + data3 != guid.Data3 ) + return FALSE; + + for( i = 0; i < 8; i++ ) + if ( data4[i] != guid.Data4[i] ) + return FALSE; + + return TRUE; + } + + bool operator!=( const GUID &guid ) const + { + return !( *this == guid ); + } +#endif + + uint data1; + ushort data2; + ushort data3; + uchar data4[ 8 ]; +}; + +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator<<( QDataStream &, const QUuid & ); +Q_EXPORT QDataStream &operator>>( QDataStream &, QUuid & ); +#endif + +#endif //QUUID_H diff --git a/qmake/include/qvaluelist.h b/qmake/include/qvaluelist.h new file mode 100644 index 0000000..54f7aec --- a/dev/null +++ b/qmake/include/qvaluelist.h @@ -0,0 +1,665 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QValueList class +** +** Created : 990406 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QVALUELIST_H +#define QVALUELIST_H + +#ifndef QT_H +#include "qtl.h" +#include "qshared.h" +#include "qdatastream.h" +#endif // QT_H + +#ifndef QT_NO_STL +#include <iterator> +#include <list> +#endif + +//#define QT_CHECK_VALUELIST_RANGE + +#if defined(Q_CC_MSVC) +#pragma warning(disable:4284) // "return type for operator -> is not a UDT" +#endif + +template <class T> +class QValueListNode +{ +public: + QValueListNode( const T& t ) : data( t ) { } + QValueListNode() { } +#if defined(Q_TEMPLATEDLL) + // Workaround MS bug in memory de/allocation in DLL vs. EXE + virtual ~QValueListNode() { } +#endif + + QValueListNode<T>* next; + QValueListNode<T>* prev; + T data; +}; + +template<class T> +class QValueListIterator +{ + public: + /** + * Typedefs + */ + typedef QValueListNode<T>* NodePtr; +#ifndef QT_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; +#endif + typedef T value_type; + typedef size_t size_type; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef T* pointer; + typedef T& reference; + + /** + * Variables + */ + NodePtr node; + + /** + * Functions + */ + QValueListIterator() : node( 0 ) {} + QValueListIterator( NodePtr p ) : node( p ) {} + QValueListIterator( const QValueListIterator<T>& it ) : node( it.node ) {} + + bool operator==( const QValueListIterator<T>& it ) const { return node == it.node; } + bool operator!=( const QValueListIterator<T>& it ) const { return node != it.node; } + const T& operator*() const { return node->data; } + T& operator*() { return node->data; } + // UDT for T = x* + // T* operator->() const { return &node->data; } + + QValueListIterator<T>& operator++() { + node = node->next; + return *this; + } + + QValueListIterator<T> operator++(int) { + QValueListIterator<T> tmp = *this; + node = node->next; + return tmp; + } + + QValueListIterator<T>& operator--() { + node = node->prev; + return *this; + } + + QValueListIterator<T> operator--(int) { + QValueListIterator<T> tmp = *this; + node = node->prev; + return tmp; + } + + QValueListIterator<T>& operator+=( int j ) { + while ( j-- ) + node = node->next; + return *this; + } + + QValueListIterator<T>& operator-=( int j ) { + while ( j-- ) + node = node->prev; + return *this; + } + +}; + +template<class T> +class QValueListConstIterator +{ + public: + /** + * Typedefs + */ + typedef QValueListNode<T>* NodePtr; +#ifndef QT_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; +#endif + typedef T value_type; + typedef size_t size_type; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef const T* pointer; + typedef const T& reference; + + /** + * Variables + */ + NodePtr node; + + /** + * Functions + */ + QValueListConstIterator() : node( 0 ) {} + QValueListConstIterator( NodePtr p ) : node( p ) {} + QValueListConstIterator( const QValueListConstIterator<T>& it ) : node( it.node ) {} + QValueListConstIterator( const QValueListIterator<T>& it ) : node( it.node ) {} + + bool operator==( const QValueListConstIterator<T>& it ) const { return node == it.node; } + bool operator!=( const QValueListConstIterator<T>& it ) const { return node != it.node; } + const T& operator*() const { return node->data; } + // UDT for T = x* + // const T* operator->() const { return &node->data; } + + QValueListConstIterator<T>& operator++() { + node = node->next; + return *this; + } + + QValueListConstIterator<T> operator++(int) { + QValueListConstIterator<T> tmp = *this; + node = node->next; + return tmp; + } + + QValueListConstIterator<T>& operator--() { + node = node->prev; + return *this; + } + + QValueListConstIterator<T> operator--(int) { + QValueListConstIterator<T> tmp = *this; + node = node->prev; + return tmp; + } +}; + +template <class T> +class QValueListPrivate : public QShared +{ +public: + /** + * Typedefs + */ + typedef QValueListIterator<T> Iterator; + typedef QValueListConstIterator<T> ConstIterator; + typedef QValueListNode<T> Node; + typedef QValueListNode<T>* NodePtr; + typedef size_t size_type; + + /** + * Functions + */ + QValueListPrivate(); + QValueListPrivate( const QValueListPrivate<T>& _p ); + + void derefAndDelete() // ### hack to get around hp-cc brain damage + { + if ( deref() ) + delete this; + } + +#if defined(Q_TEMPLATEDLL) + // Workaround MS bug in memory de/allocation in DLL vs. EXE + virtual +#endif + ~QValueListPrivate(); + + Iterator insert( Iterator it, const T& x ); + Iterator remove( Iterator it ); + NodePtr find( NodePtr start, const T& x ) const; + int findIndex( NodePtr start, const T& x ) const; + uint contains( const T& x ) const; + uint remove( const T& x ); + NodePtr at( size_type i ) const; + void clear(); + + NodePtr node; + size_type nodes; +}; + +template <class T> +Q_INLINE_TEMPLATES QValueListPrivate<T>::QValueListPrivate() +{ + node = new Node; node->next = node->prev = node; nodes = 0; +} + +template <class T> +Q_INLINE_TEMPLATES QValueListPrivate<T>::QValueListPrivate( const QValueListPrivate<T>& _p ) + : QShared() +{ + node = new Node; node->next = node->prev = node; nodes = 0; + Iterator b( _p.node->next ); + Iterator e( _p.node ); + Iterator i( node ); + while( b != e ) + insert( i, *b++ ); +} + +template <class T> +Q_INLINE_TEMPLATES QValueListPrivate<T>::~QValueListPrivate() { + NodePtr p = node->next; + while( p != node ) { + NodePtr x = p->next; + delete p; + p = x; + } + delete node; +} + +template <class T> +Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::insert( Q_TYPENAME QValueListPrivate<T>::Iterator it, const T& x ) +{ + NodePtr p = new Node( x ); + p->next = it.node; + p->prev = it.node->prev; + it.node->prev->next = p; + it.node->prev = p; + nodes++; + return p; +} + +template <class T> +Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::remove( Q_TYPENAME QValueListPrivate<T>::Iterator it ) +{ + Q_ASSERT ( it.node != node ); + NodePtr next = it.node->next; + NodePtr prev = it.node->prev; + prev->next = next; + next->prev = prev; + delete it.node; + nodes--; + return Iterator( next ); +} + +template <class T> +Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::find( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const +{ + ConstIterator first( start ); + ConstIterator last( node ); + while( first != last) { + if ( *first == x ) + return first.node; + ++first; + } + return last.node; +} + +template <class T> +Q_INLINE_TEMPLATES int QValueListPrivate<T>::findIndex( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const +{ + ConstIterator first( start ); + ConstIterator last( node ); + int pos = 0; + while( first != last) { + if ( *first == x ) + return pos; + ++first; + ++pos; + } + return -1; +} + +template <class T> +Q_INLINE_TEMPLATES uint QValueListPrivate<T>::contains( const T& x ) const +{ + uint result = 0; + Iterator first = Iterator( node->next ); + Iterator last = Iterator( node ); + while( first != last) { + if ( *first == x ) + ++result; + ++first; + } + return result; +} + +template <class T> +Q_INLINE_TEMPLATES uint QValueListPrivate<T>::remove( const T& x ) +{ + uint result = 0; + Iterator first = Iterator( node->next ); + Iterator last = Iterator( node ); + while( first != last) { + if ( *first == x ) { + first = remove( first ); + ++result; + } else + ++first; + } + return result; +} + +template <class T> +Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::at( size_type i ) const +{ + Q_ASSERT( i <= nodes ); + NodePtr p = node->next; + for( size_type x = 0; x < i; ++x ) + p = p->next; + return p; +} + +template <class T> +Q_INLINE_TEMPLATES void QValueListPrivate<T>::clear() +{ + nodes = 0; + NodePtr p = node->next; + while( p != node ) { + NodePtr next = p->next; + delete p; + p = next; + } + node->next = node->prev = node; +} + +#ifdef QT_CHECK_RANGE +# if !defined( QT_NO_DEBUG ) && defined( QT_CHECK_VALUELIST_RANGE ) +# define QT_CHECK_INVALID_LIST_ELEMENT if ( empty() ) qWarning( "QValueList: Warning invalid element" ) +# define QT_CHECK_INVALID_LIST_ELEMENT_FATAL Q_ASSERT( !empty() ); +# else +# define QT_CHECK_INVALID_LIST_ELEMENT +# define QT_CHECK_INVALID_LIST_ELEMENT_FATAL +# endif +#else +# define QT_CHECK_INVALID_LIST_ELEMENT +# define QT_CHECK_INVALID_LIST_ELEMENT_FATAL +#endif + +template <class T> class QDeepCopy; + +template <class T> +class QValueList +{ +public: + /** + * Typedefs + */ + typedef QValueListIterator<T> iterator; + typedef QValueListConstIterator<T> const_iterator; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + + /** + * API + */ + QValueList() { sh = new QValueListPrivate<T>; } + QValueList( const QValueList<T>& l ) { sh = l.sh; sh->ref(); } +#ifndef QT_NO_STL +# ifdef Q_CC_HPACC // HP-UX aCC does require typename in some place +# undef Q_TYPENAME // but not accept them at others. +# define Q_TYPENAME // also doesn't like re-defines ... +# endif + QValueList( const Q_TYPENAME std::list<T>& l ) + { + sh = new QValueListPrivate<T>; + qCopy( l.begin(), l.end(), std::back_inserter( *this ) ); + } +#endif + ~QValueList() { sh->derefAndDelete(); } + + QValueList<T>& operator= ( const QValueList<T>& l ) + { + l.sh->ref(); + sh->derefAndDelete(); + sh = l.sh; + return *this; + } +#ifndef QT_NO_STL + QValueList<T>& operator= ( const Q_TYPENAME std::list<T>& l ) + { + detach(); + qCopy( l.begin(), l.end(), std::back_inserter( *this ) ); + return *this; + } + bool operator== ( const Q_TYPENAME std::list<T>& l ) const + { + if ( size() != l.size() ) + return FALSE; + const_iterator it2 = begin(); +#if !defined(Q_CC_MIPS) + typename +#endif + std::list<T>::const_iterator it = l.begin(); + for ( ; it2 != end(); ++it2, ++it ) + if ( !((*it2) == (*it)) ) + return FALSE; + return TRUE; + } +# ifdef Q_CC_HPACC // undo the HP-UX aCC hackery done above +# undef Q_TYPENAME +# define Q_TYPENAME typename +# endif +#endif + bool operator== ( const QValueList<T>& l ) const; + bool operator!= ( const QValueList<T>& l ) const { return !( *this == l ); } + iterator begin() { detach(); return iterator( sh->node->next ); } + const_iterator begin() const { return const_iterator( sh->node->next ); } + iterator end() { detach(); return iterator( sh->node ); } + const_iterator end() const { return const_iterator( sh->node ); } + iterator insert( iterator it, const T& x ) { detach(); return sh->insert( it, x ); } + uint remove( const T& x ) { detach(); return sh->remove( x ); } + void clear(); + + QValueList<T>& operator<< ( const T& x ) + { + append( x ); + return *this; + } + + size_type size() const { return sh->nodes; } + bool empty() const { return sh->nodes == 0; } + void push_front( const T& x ) { detach(); sh->insert( begin(), x ); } + void push_back( const T& x ) { detach(); sh->insert( end(), x ); } + iterator erase( iterator pos ) { detach(); return sh->remove( pos ); } + iterator erase( iterator first, iterator last ); + reference front() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); } + const_reference front() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); } + reference back() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); } + const_reference back() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); } + void pop_front() { QT_CHECK_INVALID_LIST_ELEMENT; erase( begin() ); } + void pop_back() { + QT_CHECK_INVALID_LIST_ELEMENT; + iterator tmp = end(); + erase( --tmp ); + } + void insert( iterator pos, size_type n, const T& x ); + // Some compilers (incl. vc++) would instantiate this function even if + // it is not used; this would constrain QValueList to classes that provide + // an operator< + /* + void sort() + { + qHeapSort( *this ); + } + */ + + QValueList<T> operator+ ( const QValueList<T>& l ) const; + QValueList<T>& operator+= ( const QValueList<T>& l ); + + iterator fromLast() { detach(); return iterator( sh->node->prev ); } + const_iterator fromLast() const { return const_iterator( sh->node->prev ); } + + bool isEmpty() const { return ( sh->nodes == 0 ); } + + iterator append( const T& x ) { detach(); return sh->insert( end(), x ); } + iterator prepend( const T& x ) { detach(); return sh->insert( begin(), x ); } + + iterator remove( iterator it ) { detach(); return sh->remove( it ); } + + T& first() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->next->data; } + const T& first() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->next->data; } + T& last() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->prev->data; } + const T& last() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->prev->data; } + + T& operator[] ( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->at(i)->data; } + const T& operator[] ( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->at(i)->data; } + iterator at( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return iterator( sh->at(i) ); } + const_iterator at( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return const_iterator( sh->at(i) ); } + iterator find ( const T& x ) { detach(); return iterator( sh->find( sh->node->next, x) ); } + const_iterator find ( const T& x ) const { return const_iterator( sh->find( sh->node->next, x) ); } + iterator find ( iterator it, const T& x ) { detach(); return iterator( sh->find( it.node, x ) ); } + const_iterator find ( const_iterator it, const T& x ) const { return const_iterator( sh->find( it.node, x ) ); } + int findIndex( const T& x ) const { return sh->findIndex( sh->node->next, x) ; } + size_type contains( const T& x ) const { return sh->contains( x ); } + + size_type count() const { return sh->nodes; } + + QValueList<T>& operator+= ( const T& x ) + { + append( x ); + return *this; + } + typedef QValueListIterator<T> Iterator; + typedef QValueListConstIterator<T> ConstIterator; + typedef T ValueType; + +protected: + /** + * Helpers + */ + void detach() { if ( sh->count > 1 ) detachInternal(); } + + /** + * Variables + */ + QValueListPrivate<T>* sh; + +private: + void detachInternal(); + + friend class QDeepCopy< QValueList<T> >; +}; + +template <class T> +Q_INLINE_TEMPLATES bool QValueList<T>::operator== ( const QValueList<T>& l ) const +{ + if ( size() != l.size() ) + return FALSE; + const_iterator it2 = begin(); + const_iterator it = l.begin(); + for( ; it != l.end(); ++it, ++it2 ) + if ( !( *it == *it2 ) ) + return FALSE; + return TRUE; +} + +template <class T> +Q_INLINE_TEMPLATES void QValueList<T>::clear() +{ + if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QValueListPrivate<T>; } +} + +template <class T> +Q_INLINE_TEMPLATES Q_TYPENAME QValueList<T>::iterator QValueList<T>::erase( Q_TYPENAME QValueList<T>::iterator first, Q_TYPENAME QValueList<T>::iterator last ) +{ + while ( first != last ) + erase( first++ ); + return last; +} + + +template <class T> +Q_INLINE_TEMPLATES void QValueList<T>::insert( Q_TYPENAME QValueList<T>::iterator pos, size_type n, const T& x ) +{ + for ( ; n > 0; --n ) + insert( pos, x ); +} + +template <class T> +Q_INLINE_TEMPLATES QValueList<T> QValueList<T>::operator+ ( const QValueList<T>& l ) const +{ + QValueList<T> l2( *this ); + for( const_iterator it = l.begin(); it != l.end(); ++it ) + l2.append( *it ); + return l2; +} + +template <class T> +Q_INLINE_TEMPLATES QValueList<T>& QValueList<T>::operator+= ( const QValueList<T>& l ) +{ + for( const_iterator it = l.begin(); it != l.end(); ++it ) + append( *it ); + return *this; +} + +template <class T> +Q_INLINE_TEMPLATES void QValueList<T>::detachInternal() +{ + sh->deref(); sh = new QValueListPrivate<T>( *sh ); +} + +#ifndef QT_NO_DATASTREAM +template <class T> +Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QValueList<T>& l ) +{ + l.clear(); + Q_UINT32 c; + s >> c; + for( Q_UINT32 i = 0; i < c; ++i ) + { + T t; + s >> t; + l.append( t ); + if ( s.atEnd() ) + break; + } + return s; +} + +template <class T> +Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QValueList<T>& l ) +{ + s << (Q_UINT32)l.size(); + QValueListConstIterator<T> it = l.begin(); + for( ; it != l.end(); ++it ) + s << *it; + return s; +} +#endif // QT_NO_DATASTREAM +#endif // QVALUELIST_H diff --git a/qmake/include/qvaluestack.h b/qmake/include/qvaluestack.h new file mode 100644 index 0000000..7e9bc48 --- a/dev/null +++ b/qmake/include/qvaluestack.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QValueStack class +** +** Created : 990925 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QVALUESTACK_H +#define QVALUESTACK_H + +#ifndef QT_H +#include "qvaluelist.h" +#endif // QT_H + + +template<class T> +class QValueStack : public QValueList<T> +{ +public: + QValueStack() {} + ~QValueStack() {} + void push( const T& d ) { append(d); } + T pop() + { + T elem( this->last() ); + if ( !this->isEmpty() ) + remove( this->fromLast() ); + return elem; + } + T& top() { return this->last(); } + const T& top() const { return this->last(); } +}; + +#endif diff --git a/qmake/main.cpp b/qmake/main.cpp new file mode 100644 index 0000000..eed1697 --- a/dev/null +++ b/qmake/main.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "project.h" +#include "option.h" +#include "makefile.h" +#include <qnamespace.h> +#include <qregexp.h> +#include <qdir.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +// for Borland, main is defined to qMain which breaks qmake +#undef main + +int main(int argc, char **argv) +{ + /* parse command line */ + if(!Option::parseCommandLine(argc, argv)) + return 666; + + QDir sunworkshop42workaround = QDir::current(); + QString oldpwd = sunworkshop42workaround.currentDirPath(); + Option::output_dir = oldpwd; //for now this is the output dir + if(Option::output_dir.right(1) != QString(QChar(QDir::separator()))) + Option::output_dir += QDir::separator(); + QMakeProject proj; + int exit_val = 0; + QStringList files; + if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) + files << "(*hack*)"; //we don't even use files, but we do the for() body once + else + files = Option::mkfile::project_files; + for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) { + if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || + Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { + QString fn = (*pfile); + + //setup pwd properly + debug_msg(1, "Resetting dir to: %s", oldpwd.latin1()); + QDir::setCurrent(oldpwd); //reset the old pwd + int di = fn.findRev(Option::dir_sep); + if(di != -1) { + debug_msg(1, "Changing dir to: %s", fn.left(di).latin1()); + if(!QDir::setCurrent(fn.left(fn.findRev(Option::dir_sep)))) + fprintf(stderr, "Cannot find directory: %s\n", fn.left(di).latin1()); + fn = fn.right(fn.length() - di - 1); + } + + /* read project.. */ + if(!proj.read(fn, oldpwd)) { + fprintf(stderr, "Error processing project file: %s\n", + fn == "-" ? "(stdin)" : (*pfile).latin1()); + exit_val = 2; + continue; + } + if(Option::mkfile::do_preprocess) //no need to create makefile + continue; + + /* let Option post-process */ + if(!Option::postProcessProject(&proj)) { + fprintf(stderr, "Error post-processing project file: %s", + fn == "-" ? "(stdin)" : (*pfile).latin1()); + exit_val = 8; + continue; + } + } + + bool using_stdout = FALSE; + MakefileGenerator *mkfile = MakefileGenerator::create(&proj); //figure out generator + if(mkfile && (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || + Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)) { + //open output + if(!(Option::output.state() & IO_Open)) { + if(Option::output.name() == "-") { + Option::output.setName(""); + Option::output_dir = QDir::currentDirPath(); + Option::output.open(IO_WriteOnly | IO_Translate, stdout); + using_stdout = TRUE; + } else { + if(Option::output.name().isEmpty() && Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE) + Option::output.setName(proj.first("QMAKE_MAKEFILE")); + if(!mkfile->openOutput(Option::output)) { + fprintf(stderr, "Failure to open file: %s\n", + Option::output.name().isEmpty() ? "(stdout)" : Option::output.name().latin1()); + return 5; + } + } + } + } else { + using_stdout = TRUE; //kind of.. + } + if(mkfile && !mkfile->write()) { + if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) + fprintf(stderr, "Unable to generate project file.\n"); + else + fprintf(stderr, "Unable to generate makefile for: %s\n", (*pfile).latin1()); + if(!using_stdout) + QFile::remove(Option::output.name()); + exit_val = 6; + } + delete mkfile; + mkfile = NULL; + + /* debugging */ + if(Option::debug_level) { + QMap<QString, QStringList> &vars = proj.variables(); + for(QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it) { + if(it.key().left(1) != "." && !it.data().isEmpty()) + debug_msg(1, "%s === %s", it.key().latin1(), it.data().join(" :: ").latin1()); + } + } + } + return exit_val; +} diff --git a/qmake/option.cpp b/qmake/option.cpp new file mode 100644 index 0000000..34b3ee2 --- a/dev/null +++ b/qmake/option.cpp @@ -0,0 +1,449 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "option.h" +#include <qdir.h> +#include <qregexp.h> +#include <stdlib.h> +#include <stdarg.h> + +//convenience +QString Option::prf_ext; +QString Option::prl_ext; +QString Option::ui_ext; +QStringList Option::h_ext; +QString Option::moc_ext; +QStringList Option::cpp_ext; +QString Option::obj_ext; +QString Option::lex_ext; +QString Option::yacc_ext; +QString Option::dir_sep; +QString Option::moc_mod; +QString Option::yacc_mod; +QString Option::lex_mod; + +//mode +Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING; + +//all modes +int Option::warn_level = WarnLogic; +int Option::debug_level = 0; +QFile Option::output; +QString Option::output_dir; +QStringList Option::before_user_vars; +QStringList Option::after_user_vars; +QString Option::user_template; +QString Option::user_template_prefix; +#if defined(Q_OS_WIN32) +Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE; +#elif defined(Q_OS_MAC9) +Option::TARG_MODE Option::target_mode = Option::TARG_MAC9_MODE; +#elif defined(Q_OS_MACX) +Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE; +#elif defined(Q_OS_QNX6) +Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE; +#else +Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE; +#endif + +//QMAKE_GENERATE_PROJECT stuff +bool Option::projfile::do_pwd = TRUE; +bool Option::projfile::do_recursive = FALSE; +QStringList Option::projfile::project_dirs; + +//QMAKE_GENERATE_MAKEFILE stuff +QString Option::mkfile::qmakespec; +int Option::mkfile::cachefile_depth = -1; +bool Option::mkfile::do_deps = TRUE; +bool Option::mkfile::do_mocs = TRUE; +bool Option::mkfile::do_dep_heuristics = TRUE; +bool Option::mkfile::do_preprocess = FALSE; +bool Option::mkfile::do_cache = TRUE; +QString Option::mkfile::cachefile; +QStringList Option::mkfile::project_files; +QString Option::mkfile::qmakespec_commandline; + +bool usage(const char *a0) +{ + fprintf(stdout, "Usage: %s [mode] [options] [files]\n" + "\n" + " QMake has two modes, one mode for generating project files based on\n" + "some heuristics, and the other for generating makefiles. Normally you\n" + "shouldn't need to specify a mode, as makefile generation is the default\n" + "mode for qmake, but you may use this to test qmake on an existing project\n" + "\n" + "Mode:\n" + "\t-project Put qmake into project file generation mode\n" + "\t In this mode qmake interprets files as files to\n" + "\t be built,\n" + "\t defaults to *.cpp; *.l; *.y; *.ui\n" + "\t-makefile Put qmake into makefile generation mode (default)\n" + "\t In this mode qmake interprets files as project files to\n" + "\t be processed, if skipped qmake will try to find a project\n" + "\t file in your current working directory\n" + "\n" + "Warnings Options:\n" + "\t-Wnone Turn off all warnings\n" + "\t-Wall Turn on all warnings\n" + "\t-Wparser Turn on parser warnings\n" + "\t-Wlogic Turn on logic warnings\n" + "\n" + "Options:\n" + "\t * You can place any variable assignment in options and it will be *\n" + "\t * processed as if it was in [files]. These assignments will be parsed *\n" + "\t * before [files]. *\n" + "\t-o file Write output to file\n" + "\t-unix Run in unix mode\n" + "\t-win32 Run in win32 mode\n" + "\t-macx Run in Mac OS X mode\n" + "\t-d Increase debug level\n" + "\t-t templ Overrides TEMPLATE as templ\n" + "\t-tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n" + "\t-help This help\n" + "\t-v Version information\n" + "\t-after All variable assignments after this will be\n" + "\t parsed after [files] [makefile mode only]\n" + "\t-cache file Use file as cache [makefile mode only]\n" + "\t-spec spec Use spec as QMAKESPEC [makefile mode only]\n" + "\t-nocache Don't use a cache file [makefile mode only]\n" + "\t-nodepend Don't generate dependencies [makefile mode only]\n" + "\t-nomoc Don't generate moc targets [makefile mode only]\n" + "\t-nopwd Don't look for files in pwd [ project mode only]\n" + "\t-r Recursive search [ project mode only]\n" + ,a0); + return FALSE; +} +static Option::QMAKE_MODE default_mode(QString progname) +{ + int s = progname.findRev(Option::dir_sep); + if(s != -1) + progname = progname.right(progname.length() - (s + 1)); + if(progname == "qmakegen") + return Option::QMAKE_GENERATE_PROJECT; + return Option::QMAKE_GENERATE_MAKEFILE; +} + + +bool +Option::parseCommandLine(int argc, char **argv) +{ + bool before = TRUE; + for(int x = 1; x < argc; x++) { + if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */ + QString opt = argv[x] + 1; + + //first param is a mode, or we default + if(x == 1) { + bool specified = TRUE; + if(opt == "project") { + Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT; + } else if(opt == "prl") { + Option::mkfile::do_deps = FALSE; + Option::mkfile::do_mocs = FALSE; + Option::qmake_mode = Option::QMAKE_GENERATE_PRL; + } else if(opt == "makefile") { + Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE; + } else { + specified = FALSE; + Option::qmake_mode = default_mode(argv[0]); + } + if(specified) + continue; + } + //all modes + if(opt == "o" || opt == "output") { + Option::output.setName(argv[++x]); + } else if(opt == "after") { + before = FALSE; + } else if(opt == "t" || opt == "template") { + Option::user_template = argv[++x]; + } else if(opt == "tp" || opt == "template_prefix") { + Option::user_template_prefix = argv[++x]; + } else if(opt == "mac9") { + Option::target_mode = TARG_MAC9_MODE; + } else if(opt == "macx") { + Option::target_mode = TARG_MACX_MODE; + } else if(opt == "unix") { + Option::target_mode = TARG_UNIX_MODE; + } else if(opt == "win32") { + Option::target_mode = TARG_WIN_MODE; + } else if(opt == "d") { + Option::debug_level++; + } else if(opt == "version" || opt == "v" || opt == "-version") { + fprintf(stderr, "Qmake version: %s\n", qmake_version()); + fprintf(stderr, "Qmake is free software from Trolltech AS.\n"); + return FALSE; + } else if(opt == "h" || opt == "help") { + return usage(argv[0]); + } else if(opt == "Wall") { + Option::warn_level |= WarnAll; + } else if(opt == "Wparser") { + Option::warn_level |= WarnParser; + } else if(opt == "Wlogic") { + Option::warn_level |= WarnLogic; + } else if(opt == "Wnone") { + Option::warn_level = WarnNone; + } else { + if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || + Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { + if(opt == "nodepend") { + Option::mkfile::do_deps = FALSE; + } else if(opt == "nomoc") { + Option::mkfile::do_mocs = FALSE; + } else if(opt == "nocache") { + Option::mkfile::do_cache = FALSE; + } else if(opt == "nodependheuristics") { + Option::mkfile::do_dep_heuristics = FALSE; + } else if(opt == "E") { + Option::mkfile::do_preprocess = TRUE; + } else if(opt == "cache") { + Option::mkfile::cachefile = argv[++x]; + } else if(opt == "platform" || opt == "spec") { + Option::mkfile::qmakespec = argv[++x]; + Option::mkfile::qmakespec_commandline = argv[x]; + } else { + fprintf(stderr, "***Unknown option -%s\n", opt.latin1()); + return usage(argv[0]); + } + } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { + if(opt == "nopwd") { + Option::projfile::do_pwd = FALSE; + } else if(opt == "r") { + Option::projfile::do_recursive = TRUE; + } else { + fprintf(stderr, "***Unknown option -%s\n", opt.latin1()); + return usage(argv[0]); + } + } + } + } else { + if(x == 1) + Option::qmake_mode = default_mode(argv[0]); + + QString arg = argv[x]; + if(arg.find('=') != -1) { + if(before) + Option::before_user_vars.append(arg); + else + Option::after_user_vars.append(arg); + } else { + QFileInfo fi(arg); + if(!fi.convertToAbs()) //strange + arg = fi.filePath(); + if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || + Option::qmake_mode == Option::QMAKE_GENERATE_PRL) + Option::mkfile::project_files.append(arg); + else + Option::projfile::project_dirs.append(arg); + } + } + } + if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING) + Option::qmake_mode = default_mode(argv[0]); + + //last chance for defaults + if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || + Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { + if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty()) + Option::mkfile::qmakespec = getenv("QMAKESPEC"); + + //try REALLY hard to do it for them, lazy.. + if(Option::mkfile::project_files.isEmpty()) { + QString proj = QDir::currentDirPath(); + proj = proj.right(proj.length() - (proj.findRev('/') + 1)) + ".pro"; + if(QFile::exists(proj)) + Option::mkfile::project_files.append(proj); + else + return usage(argv[0]); + } + } + + //defaults for globals + Option::moc_mod = "moc_"; + Option::lex_mod = "_lex"; + Option::yacc_mod = "_yacc"; + Option::prl_ext = ".prl"; + Option::prf_ext = ".prf"; + Option::ui_ext = ".ui"; + Option::h_ext << ".h" << ".hpp" << ".hh" << ".H" << ".hxx"; + Option::moc_ext = ".moc"; + Option::cpp_ext << ".cpp" << ".cc" << ".cxx" << ".C"; + Option::lex_ext = ".l"; + Option::yacc_ext = ".y"; + if(Option::target_mode == Option::TARG_WIN_MODE) { + Option::dir_sep = "\\"; + Option::obj_ext = ".obj"; + } else { + if(Option::target_mode == Option::TARG_MAC9_MODE) + Option::dir_sep = ":"; + else + Option::dir_sep = "/"; + Option::obj_ext = ".o"; + } + return TRUE; +} + +bool Option::postProcessProject(QMakeProject *project) +{ + Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"]; + if(cpp_ext.isEmpty()) + cpp_ext << ".cpp"; //something must be there + Option::h_ext = project->variables()["QMAKE_EXT_H"]; + if(h_ext.isEmpty()) + h_ext << ".h"; + + if(!project->isEmpty("QMAKE_EXT_PRL")) + Option::prl_ext = project->first("QMAKE_EXT_PRL"); + if(!project->isEmpty("QMAKE_EXT_PRF")) + Option::prf_ext = project->first("QMAKE_EXT_PRF"); + if(!project->isEmpty("QMAKE_EXT_UI")) + Option::ui_ext = project->first("QMAKE_EXT_UI"); + if(!project->isEmpty("QMAKE_EXT_MOC")) + Option::moc_ext = project->first("QMAKE_EXT_MOC"); + if(!project->isEmpty("QMAKE_EXT_LEX")) + Option::lex_ext = project->first("QMAKE_EXT_LEX"); + if(!project->isEmpty("QMAKE_EXT_YACC")) + Option::yacc_ext = project->first("QMAKE_EXT_YACC"); + if(!project->isEmpty("QMAKE_EXT_OBJ")) + Option::obj_ext = project->first("QMAKE_EXT_OBJ"); + if(!project->isEmpty("QMAKE_MOD_MOC")) + Option::moc_mod = project->first("QMAKE_MOD_MOC"); + if(!project->isEmpty("QMAKE_MOD_LEX")) + Option::lex_mod = project->first("QMAKE_MOD_LEX"); + if(!project->isEmpty("QMAKE_MOD_YACC")) + Option::yacc_mod = project->first("QMAKE_MOD_YACC"); + if(!project->isEmpty("QMAKE_DIR_SEP")) + Option::dir_sep = project->first("QMAKE_DIR_SEP"); + return TRUE; +} + +void fixEnvVariables(QString &x) +{ + int rep; + QRegExp reg_var("\\$\\(.*\\)"); + reg_var.setMinimal( TRUE ); + while((rep = reg_var.search(x)) != -1) + x.replace(rep, reg_var.matchedLength(), QString(getenv(x.mid(rep + 2, reg_var.matchedLength() - 3).latin1()))); +} +static QString fixPath(QString x) +{ +#if 0 + QFileInfo fi(x); + if(fi.isDir()) { + QDir dir(x); + x = dir.canonicalPath(); + } else { + QString dir = fi.dir().canonicalPath(); + if(!dir.isEmpty() && dir.right(1) != Option::dir_sep) + dir += Option::dir_sep; + x = dir + fi.fileName(); + } +#endif + return QDir::cleanDirPath(x); +} + + +QString +Option::fixPathToTargetOS(const QString& in, bool fix_env, bool canonical) +{ + QString tmp(in); + if(fix_env) + fixEnvVariables(tmp); + if(canonical) + tmp = fixPath(tmp); + QString rep; + if(Option::target_mode == TARG_MAC9_MODE) + rep = "[/\\\\]"; + else if(Option::target_mode == TARG_WIN_MODE) + rep = "[/]"; + else + rep = "[\\\\]"; + return tmp.replace(QRegExp(rep), Option::dir_sep); +} + +QString +Option::fixPathToLocalOS(const QString& in, bool fix_env, bool canonical) +{ + QString tmp(in); + if(fix_env) + fixEnvVariables(tmp); + if(canonical) + tmp = fixPath(tmp); +#if defined(Q_OS_WIN32) + return tmp.replace('/', '\\'); +#else + return tmp.replace('\\', '/'); +#endif +} + +const char *qmake_version() +{ + static char *ret = NULL; + if(ret) + return ret; + ret = (char *)malloc(15); + sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH); + return ret; +} + +void debug_msg(int level, const char *fmt, ...) +{ + if(Option::debug_level < level) + return; + fprintf(stderr, "DEBUG %d: ", level); + { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } + fprintf(stderr, "\n"); +} + +void warn_msg(QMakeWarn type, const char *fmt, ...) +{ + if(!(Option::warn_level & type)) + return; + fprintf(stderr, "WARNING: "); + { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } + fprintf(stderr, "\n"); +} diff --git a/qmake/option.h b/qmake/option.h new file mode 100644 index 0000000..9a5a85a --- a/dev/null +++ b/qmake/option.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __OPTION_H__ +#define __OPTION_H__ + +#include "project.h" +#include <qstring.h> +#include <qstringlist.h> +#include <qfile.h> + +#define QMAKE_VERSION_MAJOR 1 +#define QMAKE_VERSION_MINOR 4 +#define QMAKE_VERSION_PATCH 0 +const char *qmake_version(); + +void fixEnvVariables(QString &x); +void debug_msg(int level, const char *fmt, ...); +enum QMakeWarn { + WarnNone = 0x00, + WarnParser = 0x01, + WarnLogic = 0x02, + WarnAll = 0xFF +}; +void warn_msg(QMakeWarn t, const char *fmt, ...); + +struct Option +{ + //simply global convenience + static QString prf_ext; + static QString prl_ext; + static QString ui_ext; + static QStringList h_ext; + static QStringList cpp_ext; + static QString moc_ext; + static QString obj_ext; + static QString lex_ext; + static QString yacc_ext; + static QString moc_mod; + static QString lex_mod; + static QString yacc_mod; + static QString dir_sep; + //both of these must be called.. + static bool parseCommandLine(int argc, char **argv); //parse cmdline + static bool postProcessProject(QMakeProject *); + + //and convenience functions + static QString fixPathToLocalOS(const QString& in, bool fix_env=TRUE, bool canonical=TRUE); + static QString fixPathToTargetOS(const QString& in, bool fix_env=TRUE, bool canonical=TRUE); + + //global qmake mode, can only be in one mode per invocation! + enum QMAKE_MODE { QMAKE_GENERATE_NOTHING, QMAKE_GENERATE_PROJECT, QMAKE_GENERATE_MAKEFILE, + QMAKE_GENERATE_PRL }; + static QMAKE_MODE qmake_mode; + + //all modes + static QFile output; + static QString output_dir; + static int debug_level; + static int warn_level; + static QStringList before_user_vars, after_user_vars; + enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE }; + static TARG_MODE target_mode; + static QString user_template, user_template_prefix; + + //QMAKE_GENERATE_PROJECT options + struct projfile { + static bool do_pwd; + static bool do_recursive; + static QStringList project_dirs; + }; + + //QMAKE_GENERATE_MAKEFILE options + struct mkfile { + static QString qmakespec; + static bool do_cache; + static bool do_deps; + static bool do_mocs; + static bool do_dep_heuristics; + static bool do_preprocess; + static QString cachefile; + static int cachefile_depth; + static QStringList project_files; + static QString qmakespec_commandline; + }; +}; + + +#endif /* __OPTION_H__ */ diff --git a/qmake/project.cpp b/qmake/project.cpp new file mode 100644 index 0000000..ae24193 --- a/dev/null +++ b/qmake/project.cpp @@ -0,0 +1,987 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "project.h" +#include "option.h" +#include <qfile.h> +#include <qdir.h> +#include <qregexp.h> +#include <qtextstream.h> +#include <qvaluestack.h> +#ifdef Q_OS_UNIX +# include <unistd.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +#ifdef Q_OS_WIN32 +#define QT_POPEN _popen +#else +#define QT_POPEN popen +#endif + +struct parser_info { + QString file; + int line_no; +} parser; +static void qmake_error_msg(const char *msg) +{ + fprintf(stderr, "%s:%d: %s\n", parser.file.latin1(), parser.line_no, msg); +} + +static QString varMap(const QString &x) +{ + QString ret(x); + ret.replace(QRegExp("^TMAKE"), "QMAKE"); + if(ret == "INTERFACES") + ret = "FORMS"; + return ret; +} + +static QStringList split_arg_list(const QString ¶ms) +{ + QStringList args; + int last = 0, parens = 0; + QChar quote = 0; + for(int x = 0; x < (int)params.length(); x++) { + if(params[x] == ')') { + parens--; + } else if(params[x] == '(') { + parens++; + } else if(params[x] == quote) { + quote = 0; + } else if(params[x] == '\'' || params[x] == '"') { + quote = params[x]; + } else if(!parens && !quote && params[x] == ',') { + args << params.mid(last, x - last); + last = x+1; + } + } + if(last != (int)params.length()) + args << params.mid(last); + return args; +} + +static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE) +{ + int last = 0; + QStringList ret; + QValueStack<QChar> quote; + for(int x = 0; x < (int)vals.length(); x++) { + if(!quote.isEmpty() && vals[x] == quote.top()) { + quote.pop(); + } else if(vals[x] == '\'' || vals[x] == '"') { + quote.push(vals[x]); + } else if(quote.isEmpty() && + ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) { + ret << vals.mid(last, x - last); + last = x+1; + } + } + if(last != (int)vals.length()) + ret << vals.mid(last); + return ret; +} + +QMakeProject::QMakeProject() +{ +} + +bool +QMakeProject::parse(QString t, QMap<QString, QStringList> &place) +{ + QString s = t.simplifyWhiteSpace(); + s.replace(QRegExp("#.*$"), ""); /* bye comments */ + if(s.isEmpty()) /* blank_line */ + return TRUE; + + if(s.stripWhiteSpace().left(1) == "}") { + debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), + parser.line_no, scope_block); + test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); + scope_block--; + s = s.mid(1).stripWhiteSpace(); + if(s.isEmpty()) + return TRUE; + } + if(!(scope_flag & (0x01 << scope_block))) { + /* adjust scope for each block which appears on a single line */ + for(int i = (s.contains('{')-s.contains('}')); i; i--) + scope_flag &= ~(0x01 << (++scope_block)); + debug_msg(1, "Project Parser: %s:%d : Ignored due to block being false.", + parser.file.latin1(), parser.line_no); + return TRUE; + } + + QString scope, var, op; + QStringList val; +#define SKIP_WS(d) while(*d && (*d == ' ' || *d == '\t')) d++ + const char *d = s.latin1(); + SKIP_WS(d); + bool scope_failed = FALSE, else_line = FALSE, or_op=FALSE; + int parens = 0, scope_count=0; + while(*d && *d != '=') { + if((*d == '+' || *d == '-' || *d == '*' || *d == '~')) { + if(*(d+1) == '=') { + break; + } else if(*(d+1) == ' ') { + const char *k = d + 1; + SKIP_WS(k); + if(*k == '=') { + QString msg; + qmake_error_msg(*d + "must be followed immediatly by ="); + return FALSE; + } + } + } + + if ( *d == '(' ) + ++parens; + else if ( *d == ')' ) + --parens; + + if(!parens && (*d == ':' || *d == '{' || *d == ')' || *d == '|')) { + scope_count++; + scope = var.stripWhiteSpace(); + if ( *d == ')' ) + scope += *d; /* need this */ + var = ""; + + bool test = scope_failed; + if(scope.lower() == "else") { + if(scope_count != 1 || test_status == TestNone) { + qmake_error_msg("Unexpected " + scope + " ('" + s + "')"); + return FALSE; + } + else_line = TRUE; + test = (test_status == TestSeek); + debug_msg(1, "Project Parser: %s:%d : Else%s %s.", parser.file.latin1(), parser.line_no, + scope == "else" ? "" : QString(" (" + scope + ")").latin1(), + test ? "considered" : "excluded"); + } else { + QString comp_scope = scope; + bool invert_test = (comp_scope.left(1) == "!"); + if(invert_test) + comp_scope = comp_scope.right(comp_scope.length()-1); + int lparen = comp_scope.find('('); + if(or_op || !scope_failed) { + if(lparen != -1) { /* if there is an lparen in the scope, it IS a function */ + int rparen = comp_scope.findRev(')'); + if(rparen == -1) { + QCString error; + error.sprintf("Function missing right paren: %s ('%s')", + comp_scope.latin1(), s.latin1()); + qmake_error_msg(error); + return FALSE; + } + QString func = comp_scope.left(lparen); + test = doProjectTest(func, comp_scope.mid(lparen+1, rparen - lparen - 1), place); + if ( *d == ')' && !*(d+1) ) { + if(invert_test) + test = !test; + test_status = (test ? TestFound : TestSeek); + return TRUE; /* assume we are done */ + } + } else { + test = isActiveConfig(comp_scope.stripWhiteSpace()); + } + if(invert_test) + test = !test; + } + } + if(!test && !scope_failed) + debug_msg(1, "Project Parser: %s:%d : Test (%s) failed.", parser.file.latin1(), + parser.line_no, scope.latin1()); + if(test == or_op) + scope_failed = !test; + or_op = (*d == '|'); + if(*d == '{') { /* scoping block */ + if(!scope_failed) + scope_flag |= (0x01 << (++scope_block)); + else + scope_flag &= ~(0x01 << (++scope_block)); + debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d).", parser.file.latin1(), + parser.line_no, scope_block, !scope_failed); + } + } else { + var += *d; + } + d++; + } + if(!scope_count || (scope_count == 1 && else_line)) + test_status = TestNone; + else if(!else_line || test_status != TestFound) + test_status = (scope_failed ? TestSeek : TestFound); + if(scope_failed) + return TRUE; /* oh well */ + if(!*d) { + if(!var.isEmpty()) + qmake_error_msg("Parse Error ('" + s + "')"); + return var.isEmpty(); /* allow just a scope */ + } + + SKIP_WS(d); + for( ; *d && op.find('=') == -1; op += *(d++)); + op.replace(QRegExp("\\s"), ""); + + SKIP_WS(d); + QString vals(d); /* vals now contains the space separated list of values */ + int rbraces = vals.contains('}'), lbraces = vals.contains('{'); + if(scope_block && rbraces - lbraces == 1) { + debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), + parser.line_no, scope_block); + test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); + scope_block--; + vals.truncate(vals.length()-1); + } else if(rbraces != lbraces) { + warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d", + vals.latin1(), parser.file.latin1(), parser.line_no); + } + doVariableReplace(vals, place); + + var = var.stripWhiteSpace(); +#undef SKIP_WS + + if(!var.isEmpty() && Option::mkfile::do_preprocess) { + static QString last_file("*none*"); + if(parser.file != last_file) { + fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no); + last_file = parser.file; + } + fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); + } + var = varMap(var); //backwards compatability + + /* vallist is the broken up list of values */ + QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH")); + if(!vallist.grep("=").isEmpty()) + warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d", + var.latin1(), parser.file.latin1(), parser.line_no); + + QStringList &varlist = place[var]; /* varlist is the list in the symbol table */ + debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no, + var.latin1(), op.latin1(), vallist.join(" :: ").latin1()); + + /* now do the operation */ + if(op == "~=") { + if(vallist.count() != 1) { + qmake_error_msg("~= operator only accepts one right hand paramater ('" + + s + "')"); + return FALSE; + } + QString val(vallist.first()); + if(val.length() < 4 || val.at(0) != 's') { + qmake_error_msg("~= operator only can handle s/// function ('" + + s + "')"); + return FALSE; + } + QChar sep = val.at(1); + QStringList func = QStringList::split(sep, val, TRUE); + if(func.count() < 3 || func.count() > 4) { + qmake_error_msg("~= operator only can handle s/// function ('" + + s + "')"); + return FALSE; + } + bool global = FALSE, case_sense = TRUE; + if(func.count() == 4) { + global = func[3].find('g') != -1; + case_sense = func[3].find('i') == -1; + } + QRegExp regexp(func[1], case_sense); + for(QStringList::Iterator varit = varlist.begin(); + varit != varlist.end(); ++varit) { + if((*varit).contains(regexp)) { + (*varit) = (*varit).replace(regexp, func[2]); + if(!global) + break; + } + } + } else { + if(op == "=") { + if(!varlist.isEmpty()) + warn_msg(WarnParser, "Operator=(%s) clears variables previously set: %s:%d", + var.latin1(), parser.file.latin1(), parser.line_no); + varlist.clear(); + } + for(QStringList::Iterator valit = vallist.begin(); + valit != vallist.end(); ++valit) { + if((*valit).isEmpty()) + continue; + if((op == "*=" && !(*varlist.find((*valit)))) || + op == "=" || op == "+=") + varlist.append((*valit)); + else if(op == "-=") + varlist.remove((*valit)); + } + } + if(var == "REQUIRES") /* special case to get communicated to backends! */ + doProjectCheckReqs(vallist, place); + + return TRUE; +} + +bool +QMakeProject::read(QString file, QMap<QString, QStringList> &place) +{ + parser_info pi = parser; + /* scope blocks start at true */ + test_status = TestNone; + scope_flag = 0x01; + scope_block = 0; + + file = Option::fixPathToLocalOS(file); + doVariableReplace(file, place); + bool ret = FALSE, using_stdin = FALSE; + QFile qfile; + if(!strcmp(file, "-")) { + qfile.setName(""); + ret = qfile.open(IO_ReadOnly, stdin); + using_stdin = TRUE; + } else { + qfile.setName(file); + ret = qfile.open(IO_ReadOnly); + } + if ( ret ) { + QTextStream t( &qfile ); + QString s, line; + parser.file = file; + parser.line_no = 0; + while ( !t.eof() ) { + parser.line_no++; + line = t.readLine().stripWhiteSpace(); + int prelen = line.length(); + line.replace(QRegExp("#.*$"), ""); // bye comments + if(!line.isEmpty() && line.right(1) == "\\") { + line.truncate(line.length() - 1); + s += line + " "; + } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) { + if(s.isEmpty() && line.isEmpty()) + continue; + if(!line.isEmpty()) + s += line; + if(!s.isEmpty()) { + if(!(ret = parse(s, place))) + break; + s = ""; + } + } + } + if(!using_stdin) + qfile.close(); + } + parser = pi; + return ret; +} + +bool +QMakeProject::read(QString project, QString) +{ + if(cfile.isEmpty()) { + // hack to get the Option stuff in there + base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; + base_vars["QMAKE_EXT_H"] = Option::h_ext; + + /* parse the cache */ + if(Option::mkfile::do_cache) { + if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified + QString dir = QDir::convertSeparators(Option::output_dir); + while(!QFile::exists((Option::mkfile::cachefile = dir + + QDir::separator() + ".qmake.cache"))) { + dir = dir.left(dir.findRev(QDir::separator())); + if(dir.isEmpty() || dir.find(QDir::separator()) == -1) { + Option::mkfile::cachefile = ""; + break; + } + if(Option::mkfile::cachefile_depth == -1) + Option::mkfile::cachefile_depth = 1; + else + Option::mkfile::cachefile_depth++; + } + } + if(!Option::mkfile::cachefile.isEmpty()) { + read(Option::mkfile::cachefile, cache); + if(Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) + Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); + } + } + /* parse mkspec */ + QStringList mkspec_roots; + /* prefer $QTDIR if it is set */ + /* minor hack here, prefer QMAKESPECDIR -cl */ + + if (getenv("QMAKESPECDIR")){ + mkspec_roots << getenv("QMAKESPECDIR"); + } else if (getenv("QTDIR")) { + mkspec_roots << getenv("QTDIR"); + } + mkspec_roots << qInstallPathData(); + if(Option::mkfile::qmakespec.isEmpty()) { + for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { + QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + + QDir::separator() + "default"; + if(QFile::exists(mkspec)) { + Option::mkfile::qmakespec = mkspec; + break; + } + } + if(Option::mkfile::qmakespec.isEmpty()) { + fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); + return FALSE; + } + } + + if(QDir::isRelativePath(Option::mkfile::qmakespec)) { + bool found_mkspec = FALSE; + for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { + QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + + QDir::separator() + Option::mkfile::qmakespec; + if(QFile::exists(mkspec)) { + found_mkspec = TRUE; + Option::mkfile::qmakespec = mkspec; + break; + } + } + if(!found_mkspec) { + fprintf(stderr, "Could not find mkspecs for your QMAKESPEC after trying:\n\t%s\n", + mkspec_roots.join("\n\t").latin1()); + return FALSE; + } + } + + /* parse qmake configuration */ + QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf"; + debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1()); + if(!read(spec, base_vars)) { + fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.latin1()); + return FALSE; + } + if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { + debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.latin1()); + read(Option::mkfile::cachefile, base_vars); + } + + /* commandline */ + cfile = project; + parser.line_no = 1; //really arg count now.. duh + parser.file = "(internal)"; + for(QStringList::Iterator it = Option::before_user_vars.begin(); + it != Option::before_user_vars.end(); ++it) { + if(!parse((*it), base_vars)) { + fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); + return FALSE; + } + parser.line_no++; + } + } + + /* parse project file */ + debug_msg(1, "Project file: reading %s", project.latin1()); + vars = base_vars; /* start with the base */ + + pfile = project; + if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") + pfile += ".pro"; + + if(!read(pfile, vars)) + return FALSE; + + parser.line_no = 1; //really arg count now.. duh + parser.file = "(internal)"; + for(QStringList::Iterator it = Option::after_user_vars.begin(); + it != Option::after_user_vars.end(); ++it) { + if(!parse((*it), vars)) { + fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); + return FALSE; + } + parser.line_no++; + } + + /* now let the user override the template from an option.. */ + if(!Option::user_template.isEmpty()) { + debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1()); + vars["TEMPLATE"].clear(); + vars["TEMPLATE"].append(Option::user_template); + } + + if(vars["TEMPLATE"].isEmpty()) + vars["TEMPLATE"].append(QString("app")); + else + vars["TEMPLATE"].first().replace(QRegExp("\\.t$"), ""); + if(!Option::user_template_prefix.isEmpty()) + vars["TEMPLATE"].first().prepend(Option::user_template_prefix); + + if(vars["TARGET"].isEmpty()) { + // ### why not simply use: + // QFileInfo fi(pfile); + // fi.baseName(); + QString tmp = pfile; + if(tmp.findRev('/') != -1) + tmp = tmp.right( tmp.length() - tmp.findRev('/') - 1 ); + if(tmp.findRev('.') != -1) + tmp = tmp.left(tmp.findRev('.')); + vars["TARGET"].append(tmp); + } + + QString test_version = getenv("QTESTVERSION"); + if (!test_version.isEmpty()) { + QString s = vars["TARGET"].first(); + if (s == "qt" || s == "qt-mt" || s == "qte" || s == "qte-mt") { + QString &ver = vars["VERSION"].first(); +// fprintf(stderr,"Current QT version number: " + ver + "\n"); + if (ver != "" && ver != test_version) { + ver = test_version; + fprintf(stderr,"Changed QT version number to " + test_version + "!\n"); + } + } + } + return TRUE; +} + +bool +QMakeProject::isActiveConfig(const QString &x) +{ + if(x.isEmpty()) + return TRUE; + + QRegExp re(x, FALSE, TRUE); + if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_UNIX_MODE) && + x == "unix") + return TRUE; + else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx") + return TRUE; + else if(Option::target_mode == Option::TARG_QNX6_MODE && x == "qnx6") + return TRUE; + else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9") + return TRUE; + else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) && + x == "mac") + return TRUE; + else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32") + return TRUE; + + + QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() - + (Option::mkfile::qmakespec.findRev(QDir::separator())+1)); + if(re.exactMatch(spec)) + return TRUE; +#ifdef Q_OS_UNIX + else if(spec == "default") { + static char *buffer = NULL; + if(!buffer) + buffer = (char *)malloc(1024); + int l = readlink(Option::mkfile::qmakespec, buffer, 1024); + if(l != -1) { + buffer[l] = '\0'; + QString r = buffer; + if(r.findRev('/') != -1) + r = r.mid(r.findRev('/') + 1); + if(re.exactMatch(r)) + return TRUE; + } + } +#endif + + + QStringList &configs = vars["CONFIG"]; + for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) { + if(re.exactMatch((*it))) + return TRUE; + } + return FALSE; +} + +bool +QMakeProject::doProjectTest(QString func, const QString ¶ms, QMap<QString, QStringList> &place) +{ + QStringList args = split_arg_list(params); + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + QString tmp = (*arit).stripWhiteSpace(); + if((tmp[0] == '\'' || tmp[0] == '"') && tmp.right(1) == tmp.left(1)) + tmp = tmp.mid(1, tmp.length() - 2); + } + return doProjectTest(func.stripWhiteSpace(), args, place); +} + +bool +QMakeProject::doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place) +{ + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space + doVariableReplace((*arit), place); + } + debug_msg(1, "Running project test: %s( %s )", func.latin1(), args.join("::").latin1()); + + if(func == "requires") { + return doProjectCheckReqs(args, place); + } else if(func == "exists") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d: exists(file) requires one argument.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + QString file = args.first(); + file = Option::fixPathToLocalOS(file); + doVariableReplace(file, place); + + if(QFile::exists(file)) + return TRUE; + //regular expression I guess + QString dirstr = QDir::currentDirPath(); + int slsh = file.findRev(Option::dir_sep); + if(slsh != -1) { + dirstr = file.left(slsh+1); + file = file.right(file.length() - slsh - 1); + } + QDir dir(dirstr, file); + return dir.count() != 0; + } else if(func == "system") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + return system(args.first().latin1()) == 0; + } else if(func == "contains") { + if(args.count() != 2) { + fprintf(stderr, "%s:%d: contains(var, val) requires two arguments.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + QRegExp regx(args[1]); + QStringList &l = place[args[0]]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if(regx.exactMatch((*it))) + return TRUE; + } + return FALSE; + } else if(func == "infile") { + if(args.count() < 2 || args.count() > 3) { + fprintf(stderr, "%s:%d: infile(file, var, val) requires at least 2 arguments.\n", + parser.file.latin1(), parser.line_no); + return FALSE; + } + QMakeProject proj; + QString file = args[0]; + doVariableReplace(file, place); + fixEnvVariables(file); + int di = file.findRev(Option::dir_sep); + QDir sunworkshop42workaround = QDir::current(); + QString oldpwd = sunworkshop42workaround.currentDirPath(); + if(di != -1) { + if(!QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) { + fprintf(stderr, "Cannot find directory: %s\n", file.left(di).latin1()); + return FALSE; + } + file = file.right(file.length() - di - 1); + } + parser_info pi = parser; + bool ret = !proj.read(file, oldpwd); + parser = pi; + if(ret) { + fprintf(stderr, "Error processing project file: %s\n", file.latin1()); + QDir::setCurrent(oldpwd); + return FALSE; + } + if(args.count() == 2) { + ret = !proj.isEmpty(args[1]); + } else { + QRegExp regx(args[2]); + QStringList &l = proj.values(args[1]); + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if(regx.exactMatch((*it))) { + ret = TRUE; + break; + } + } + } + QDir::setCurrent(oldpwd); + return ret; + } else if(func == "count") { + if(args.count() != 2) { + fprintf(stderr, "%s:%d: count(var, count) requires two arguments.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + return vars[args[0]].count() == args[1].toUInt(); + } else if(func == "isEmpty") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d: isEmpty(var) requires one argument.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + return vars[args[0]].isEmpty(); + } else if(func == "include" || func == "load") { + if(args.count() != 1) { + QString func_desc = "include(file)"; + if(func == "load") + func_desc = "load(feature)"; + fprintf(stderr, "%s:%d: %s requires one argument.\n", parser.file.latin1(), + parser.line_no, func_desc.latin1()); + return FALSE; + } + + QString file = args.first(); + file = Option::fixPathToLocalOS(file); + file.replace("\"", ""); + doVariableReplace(file, place); + if(func == "load") { + if(!file.endsWith(Option::prf_ext)) + file += Option::prf_ext; + if(file.find(Option::dir_sep) == -1 || !QFile::exists(file)) { + if(QFile::exists(Option::mkfile::qmakespec + QDir::separator() + file)) { + file.prepend(Option::mkfile::qmakespec + QDir::separator()); + } else { + bool found = FALSE; + QStringList feature_roots; + if(getenv("QTDIR")) + feature_roots << getenv("QTDIR"); +#ifdef QT_INSTALL_PREFIX + feature_roots << QT_INSTALL_PREFIX; +#endif +#ifdef QT_INSTALL_DATA + feature_roots << QT_INSTALL_DATA; +#endif + for(QStringList::Iterator it = feature_roots.begin(); it != feature_roots.end(); ++it) { + QString prf = (*it) + QDir::separator() + QString("mkspecs") + + QDir::separator() + QString("features") + QDir::separator() + file; + if(QFile::exists(prf)) { + found = TRUE; + file = prf; + break; + } + } + if(!found) { + printf("Project LOAD(): Feature %s cannot be found.\n", args.first().latin1()); + exit(3); + } + } + } + } + + debug_msg(1, "Project Parser: %s'ing file %s.", func.latin1(), file.latin1()); + parser_info pi = parser; + int sb = scope_block; + int sf = scope_flag; + TestStatus sc = test_status; + bool r = read(file.latin1(), place); + if(r) + vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(file); + parser = pi; + test_status = sc; + scope_flag = sf; + scope_block = sb; + return r; + } else if(func == "error" || func == "message") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d: %s(message) requires one argument.\n", parser.file.latin1(), + parser.line_no, func.latin1()); + return FALSE; + } + QString msg = args.first(); + doVariableReplace(msg, place); + fixEnvVariables(msg); + printf("Project %s: %s\n", func.upper().latin1(), msg.latin1()); + if(func == "message") + return TRUE; + exit(2); + } else { + fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.latin1(), parser.line_no, + func.latin1()); + } + return FALSE; +} + +bool +QMakeProject::doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place) +{ + bool ret = FALSE; + for(QStringList::ConstIterator it = deps.begin(); it != deps.end(); ++it) { + QString chk = (*it); + if(chk.isEmpty()) + continue; + bool invert_test = (chk.left(1) == "!"); + if(invert_test) + chk = chk.right(chk.length() - 1); + + bool test; + int lparen = chk.find('('); + if(lparen != -1) { /* if there is an lparen in the chk, it IS a function */ + int rparen = chk.findRev(')'); + if(rparen == -1) { + QCString error; + error.sprintf("Function (in REQUIRES) missing right paren: %s", chk.latin1()); + qmake_error_msg(error); + } else { + QString func = chk.left(lparen); + test = doProjectTest(func, chk.mid(lparen+1, rparen - lparen - 1), place); + } + } else { + test = isActiveConfig(chk); + } + if(invert_test) { + chk.prepend("!"); + test = !test; + } + if(!test) { + debug_msg(1, "Project Parser: %s:%d Failed test: REQUIRES = %s", + parser.file.latin1(), parser.line_no, chk.latin1()); + place["QMAKE_FAILED_REQUIREMENTS"].append(chk); + ret = FALSE; + } + } + return ret; +} + + +QString +QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> &place) +{ + for(int x = 0, rep; x < 5; x++) { + QRegExp reg_var; + reg_var.setMinimal(TRUE); + if( x == 0 ) //function blocked out by {}'s + reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)\\}"); + else if( x == 1 ) //variables blocked out by {}'s + reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_\\.-]*)\\}"); + else if(x == 2) //environment + reg_var = QRegExp("\\$\\$\\(([a-zA-Z0-9_\\.-]*)\\)"); + else if(x == 3) //function + reg_var = QRegExp("\\$\\$([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)"); + else if(x == 4) //normal variable + reg_var = QRegExp("\\$\\$([a-zA-Z0-9_\\.-]*)"); + while((rep = reg_var.search(str)) != -1) { + QString replacement; + if(x == 2) {//environment + replacement = getenv(reg_var.cap(1)); + } else if(x == 0 || x == 3) { //function + QStringList args = split_arg_list(reg_var.cap(2)); + for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space + doVariableReplace((*arit), place); + } + debug_msg(1, "Running function: %s( %s )", reg_var.cap(1).latin1(), args.join("::").latin1()); + if(reg_var.cap(1).lower() == "member") { + if(args.count() < 1 || args.count() > 2) { + fprintf(stderr, "%s:%d: member(var, place) requires two arguments.\n", + parser.file.latin1(), parser.line_no); + } else { + uint pos = 0; + if(args.count() == 2) + pos = args[1].toInt(); + const QStringList &var = place[varMap(args.first())]; + if(var.count() >= pos) + replacement = var[pos]; + } + } else if(reg_var.cap(1).lower() == "list") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d: list(vals) requires one" + "argument.\n", parser.file.latin1(), parser.line_no); + } else { + static int x = 0; + replacement.sprintf(".QMAKE_INTERNAL_TMP_VAR_%d", x++); + (*((QMap<QString, QStringList>*)&place))[replacement] = split_value_list(args.first()); + } + } else if(reg_var.cap(1).lower() == "join") { + if(args.count() < 1 || args.count() > 4) { + fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four" + "arguments.\n", parser.file.latin1(), parser.line_no); + } else { + QString glue, before, after; + if(args.count() >= 2) + glue = args[1].replace("\"", "" ); + if(args.count() >= 3) + before = args[2].replace("\"", "" ); + if(args.count() == 4) + after = args[3].replace("\"", "" ); + const QStringList &var = place[varMap(args.first())]; + if(!var.isEmpty()) + replacement = before + var.join(glue) + after; + } + } else if(reg_var.cap(1).lower() == "find") { + if(args.count() != 2) { + fprintf(stderr, "%s:%d find(var, str) requires two arguments\n", + parser.file.latin1(), parser.line_no); + } else { + QRegExp regx(args[1]); + const QStringList &var = place[varMap(args.first())]; + for(QStringList::ConstIterator vit = var.begin(); + vit != var.end(); ++vit) { + if(regx.search(*vit) != -1) { + if(!replacement.isEmpty()) + replacement += " "; + replacement += (*vit); + } + } + } + } else if(reg_var.cap(1).lower() == "system") { + if(args.count() != 1) { + fprintf(stderr, "%s:%d system(execut) requires one argument\n", + parser.file.latin1(), parser.line_no); + } else { + char buff[256]; + FILE *proc = QT_POPEN(args.join(" ").latin1(), "r"); + while(proc && !feof(proc)) { + int read_in = fread(buff, 1, 255, proc); + if(!read_in) + break; + for(int i = 0; i < read_in; i++) { + if(buff[i] == '\n' || buff[i] == '\t') + buff[i] = ' '; + } + buff[read_in] = '\0'; + replacement += buff; + } + } + } else { + fprintf(stderr, "%s:%d: Unknown replace function: %s\n", + parser.file.latin1(), parser.line_no, reg_var.cap(1).latin1()); + } + } else { //variable + if(reg_var.cap(1).left(1) == ".") + replacement = ""; + else if(reg_var.cap(1) == "LITERAL_WHITESPACE") + replacement = "\t"; + else + replacement = place[varMap(reg_var.cap(1))].join(" "); + } + debug_msg(2, "Project parser: %d (%s) :: %s -> %s", x, str.latin1(), + reg_var.capturedTexts().join("::").latin1(), replacement.latin1()); + str.replace(rep, reg_var.matchedLength(), replacement); + } + } + return str; +} diff --git a/qmake/project.h b/qmake/project.h new file mode 100644 index 0000000..201e63c --- a/dev/null +++ b/qmake/project.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** $Id$ +** +** Definition of ________ class. +** +** Created : 970521 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the network module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition licenses may use this +** file in accordance with the Qt Commercial License Agreement provided +** with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef __QMAKE_H__ +#define __QMAKE_H__ + +#include <qstringlist.h> +#include <qstring.h> +#include <qmap.h> + +class QMakeProject +{ + enum TestStatus { TestNone, TestFound, TestSeek } test_status; + int scope_block, scope_flag; + + QString pfile, cfile; + QMap<QString, QStringList> vars, base_vars, cache; + bool parse(QString text, QMap<QString, QStringList> &place); + bool doProjectTest(QString func, const QString ¶ms, QMap<QString, QStringList> &place); + bool doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place); + bool doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place); + QString doVariableReplace(QString &str, const QMap<QString, QStringList> &place); + +public: + QMakeProject(); + + bool read(QString project, QString pwd); + QString projectFile(); + QString configFile(); + + bool isEmpty(const QString &v); + QStringList &values(const QString &v); + QString first(const QString &v); + QMap<QString, QStringList> &variables(); + bool isActiveConfig(const QString &x); + +protected: + friend class MakefileGenerator; + bool read(QString file, QMap<QString, QStringList> &place); + +}; + +inline QString QMakeProject::projectFile() +{ +#if defined(Q_CC_SUN) && (__SUNPRO_CC == 0x500) || defined(Q_CC_HP) + // workaround for Sun WorkShop 5.0 bug fixed in Forte 6 + if (pfile == "-") + return QString("(stdin)"); + else + return pfile; +#else + return pfile == "-" ? QString("(stdin)") : pfile; +#endif +} + +inline QString QMakeProject::configFile() +{ return cfile; } + +inline bool QMakeProject::isEmpty(const QString &v) +{ return !vars.contains(v) || vars[v].isEmpty(); } + +inline QStringList &QMakeProject::values(const QString &v) +{ return vars[v]; } + +inline QString QMakeProject::first(const QString &v) +{ +#if defined(Q_CC_SUN) && (__SUNPRO_CC == 0x500) || defined(Q_CC_HP) + // workaround for Sun WorkShop 5.0 bug fixed in Forte 6 + if (isEmpty(v)) + return QString(""); + else + return vars[v].first(); +#else + return isEmpty(v) ? QString("") : vars[v].first(); +#endif +} + +inline QMap<QString, QStringList> &QMakeProject::variables() +{ return vars; } + +#endif /* __QMAKE_H__ */ diff --git a/qmake/tools/qbitarray.cpp b/qmake/tools/qbitarray.cpp new file mode 100644 index 0000000..4f4e14b --- a/dev/null +++ b/qmake/tools/qbitarray.cpp @@ -0,0 +1,661 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QBitArray class +** +** Created : 940118 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qbitarray.h" +#include "qdatastream.h" + +#define SHBLOCK ((bitarr_data*)(sharedBlock())) + + +/*! + \class QBitVal qbitarray.h + \reentrant + \brief The QBitVal class is an internal class, used with QBitArray. + + \ingroup collection + + The QBitVal is required by the indexing [] operator on bit arrays. + It is not for use in any other context. +*/ + +/*! + \fn QBitVal::QBitVal (QBitArray* a, uint i) + + Constructs a reference to element \a i in the QBitArray \a a. + This is what QBitArray::operator[] constructs its return value + with. +*/ + +/*! + \fn QBitVal::operator int() + + Returns the value referenced by the QBitVal. +*/ + +/*! + \fn QBitVal& QBitVal::operator= (const QBitVal& v) + + Sets the value referenced by the QBitVal to that referenced by + QBitVal \a v. +*/ + +/*! + \overload QBitVal& QBitVal::operator= (bool v) + + Sets the value referenced by the QBitVal to \a v. +*/ + + +/*! + \class QBitArray qbitarray.h + \reentrant + \brief The QBitArray class provides an array of bits. + + \ingroup collection + \ingroup tools + \ingroup shared + + Because QBitArray is a QMemArray, it uses explicit \link + shclass.html sharing\endlink with a reference count. + + A QBitArray is a special byte array that can access individual + bits and perform bit-operations (AND, OR, XOR and NOT) on entire + arrays or bits. + + Bits can be manipulated by the setBit() and clearBit() functions, + but it is also possible to use the indexing [] operator to test + and set individual bits. The [] operator is a little slower than + setBit() and clearBit() because some tricks are required to + implement single-bit assignments. + + Example: + \code + QBitArray a(3); + a.setBit( 0 ); + a.clearBit( 1 ); + a.setBit( 2 ); // a = [1 0 1] + + QBitArray b(3); + b[0] = 1; + b[1] = 1; + b[2] = 0; // b = [1 1 0] + + QBitArray c; + c = ~a & b; // c = [0 1 0] + \endcode + + When a QBitArray is constructed the bits are uninitialized. Use + fill() to set all the bits to 0 or 1. The array can be resized + with resize() and copied with copy(). Bits can be set with + setBit() and cleared with clearBit(). Bits can be toggled with + toggleBit(). A bit's value can be obtained with testBit() and with + at(). + + QBitArray supports the \& (AND), | (OR), ^ (XOR) and ~ (NOT) + operators. +*/ + +/*! \class QBitArray::bitarr_data + \brief The QBitArray::bitarr_data class is internal. + \internal +*/ + + +/*! + Constructs an empty bit array. +*/ + +QBitArray::QBitArray() : QByteArray( 0, 0 ) +{ + bitarr_data *x = new bitarr_data; + Q_CHECK_PTR( x ); + x->nbits = 0; + setSharedBlock( x ); +} + +/*! + Constructs a bit array of \a size bits. The bits are uninitialized. + + \sa fill() +*/ + +QBitArray::QBitArray( uint size ) : QByteArray( 0, 0 ) +{ + bitarr_data *x = new bitarr_data; + Q_CHECK_PTR( x ); + x->nbits = 0; + setSharedBlock( x ); + resize( size ); +} + +/*! + \fn QBitArray::QBitArray( const QBitArray &a ) + + Constructs a shallow copy of \a a. +*/ + +/*! + \fn QBitArray &QBitArray::operator=( const QBitArray &a ) + + Assigns a shallow copy of \a a to this bit array and returns a + reference to this array. +*/ + + +/*! + Pad last byte with 0-bits. +*/ +void QBitArray::pad0() +{ + uint sz = size(); + if ( sz && sz%8 ) + *(data()+sz/8) &= (1 << (sz%8)) - 1; +} + + +/*! + \fn uint QBitArray::size() const + + Returns the bit array's size (number of bits). + + \sa resize() +*/ + +/*! + Resizes the bit array to \a size bits and returns TRUE if the bit + array could be resized; otherwise returns FALSE. + + If the array is expanded, the new bits are set to 0. + + \sa size() +*/ + +bool QBitArray::resize( uint size ) +{ + uint s = this->size(); + if ( !QByteArray::resize( (size+7)/8 ) ) + return FALSE; // cannot resize + SHBLOCK->nbits = size; + if ( size != 0 ) { // not null array + int ds = (int)(size+7)/8 - (int)(s+7)/8;// number of bytes difference + if ( ds > 0 ) // expanding array + memset( data() + (s+7)/8, 0, ds ); // reset new data + } + return TRUE; +} + + +/*! + Fills the bit array with \a v (1's if \a v is TRUE, or 0's if \a v + is FALSE). + + fill() resizes the bit array to \a size bits if \a size is + nonnegative. + + Returns FALSE if a nonnegative \e size was specified and the bit + array could not be resized; otherwise returns TRUE. + + \sa resize() +*/ + +bool QBitArray::fill( bool v, int size ) +{ + if ( size >= 0 ) { // resize first + if ( !resize( size ) ) + return FALSE; // cannot resize + } else { + size = this->size(); + } + if ( size > 0 ) + memset( data(), v ? 0xff : 0, (size + 7) / 8 ); + if ( v ) + pad0(); + return TRUE; +} + + +/*! + Detaches from shared bit array data and makes sure that this bit + array is the only one referring to the data. + + If multiple bit arrays share common data, this bit array + dereferences the data and gets a copy of the data. Nothing happens + if there is only a single reference. + + \sa copy() +*/ + +void QBitArray::detach() +{ + int nbits = SHBLOCK->nbits; + this->duplicate( *this ); + SHBLOCK->nbits = nbits; +} + +/*! + Returns a deep copy of the bit array. + + \sa detach() +*/ + +QBitArray QBitArray::copy() const +{ + QBitArray tmp; + tmp.duplicate( *this ); + ((bitarr_data*)(tmp.sharedBlock()))->nbits = SHBLOCK->nbits; + return tmp; +} + + +/*! + Returns TRUE if the bit at position \a index is set, i.e. is 1; + otherwise returns FALSE. + + \sa setBit(), clearBit() +*/ + +bool QBitArray::testBit( uint index ) const +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + qWarning( "QBitArray::testBit: Index %d out of range", index ); + return FALSE; + } +#endif + return (*(data()+(index>>3)) & (1 << (index & 7))) != 0; +} + +/*! + \overload + + Sets the bit at position \a index to 1. + + \sa clearBit() toggleBit() +*/ + +void QBitArray::setBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + qWarning( "QBitArray::setBit: Index %d out of range", index ); + return; + } +#endif + *(data()+(index>>3)) |= (1 << (index & 7)); +} + +/*! + \fn void QBitArray::setBit( uint index, bool value ) + + Sets the bit at position \a index to \a value. + + Equivalent to: + \code + if ( value ) + setBit( index ); + else + clearBit( index ); + \endcode + + \sa clearBit() toggleBit() +*/ + +/*! + Clears the bit at position \a index, i.e. sets it to 0. + + \sa setBit(), toggleBit() +*/ + +void QBitArray::clearBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + qWarning( "QBitArray::clearBit: Index %d out of range", index ); + return; + } +#endif + *(data()+(index>>3)) &= ~(1 << (index & 7)); +} + +/*! + Toggles the bit at position \a index. + + If the previous value was 0, the new value will be 1. If the + previous value was 1, the new value will be 0. + + \sa setBit(), clearBit() +*/ + +bool QBitArray::toggleBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + qWarning( "QBitArray::toggleBit: Index %d out of range", index ); + return FALSE; + } +#endif + register uchar *p = (uchar *)data() + (index>>3); + uchar b = (1 << (index & 7)); // bit position + uchar c = *p & b; // read bit + *p ^= b; // toggle bit + return c; +} + + +/*! + \fn bool QBitArray::at( uint index ) const + + Returns the value (0 or 1) of the bit at position \a index. + + \sa operator[]() +*/ + +/*! + \fn QBitVal QBitArray::operator[]( int index ) + + Implements the [] operator for bit arrays. + + The returned QBitVal is a context object. It makes it possible to + get and set a single bit value by its \a index position. + + Example: + \code + QBitArray a( 3 ); + a[0] = 0; + a[1] = 1; + a[2] = a[0] ^ a[1]; + \endcode + + The functions testBit(), setBit() and clearBit() are faster. + + \sa at() +*/ + +/*! + \overload bool QBitArray::operator[]( int index ) const + + Implements the [] operator for constant bit arrays. +*/ + + +/*! + Performs the AND operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + QBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a &= b; // a = [1 0 0] + \endcode + + \sa operator|=(), operator^=(), operator~() +*/ + +QBitArray &QBitArray::operator&=( const QBitArray &a ) +{ + resize( QMAX(size(), a.size()) ); + register uchar *a1 = (uchar *)data(); + register uchar *a2 = (uchar *)a.data(); + int n = QMIN( QByteArray::size(), a.QByteArray::size() ); + int p = QMAX( QByteArray::size(), a.QByteArray::size() ) - n; + while ( n-- > 0 ) + *a1++ &= *a2++; + while ( p-- > 0 ) + *a1++ = 0; + return *this; +} + +/*! + Performs the OR operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + QBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a |= b; // a = [1 0 1] + \endcode + + \sa operator&=(), operator^=(), operator~() +*/ + +QBitArray &QBitArray::operator|=( const QBitArray &a ) +{ + resize( QMAX(size(), a.size()) ); + register uchar *a1 = (uchar *)data(); + register uchar *a2 = (uchar *)a.data(); + int n = QMIN( QByteArray::size(), a.QByteArray::size() ); + while ( n-- > 0 ) + *a1++ |= *a2++; + return *this; +} + +/*! + Performs the XOR operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + QBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a ^= b; // a = [0 0 1] + \endcode + + \sa operator&=(), operator|=(), operator~() +*/ + +QBitArray &QBitArray::operator^=( const QBitArray &a ) +{ + resize( QMAX(size(), a.size()) ); + register uchar *a1 = (uchar *)data(); + register uchar *a2 = (uchar *)a.data(); + int n = QMIN( QByteArray::size(), a.QByteArray::size() ); + while ( n-- > 0 ) + *a1++ ^= *a2++; + return *this; +} + +/*! + Returns a bit array that contains the inverted bits of this bit array. + + Example: + \code + QBitArray a( 3 ), b; + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b = ~a; // b = [0 1 0] + \endcode +*/ + +QBitArray QBitArray::operator~() const +{ + QBitArray a( size() ); + register uchar *a1 = (uchar *)data(); + register uchar *a2 = (uchar *)a.data(); + int n = QByteArray::size(); + while ( n-- ) + *a2++ = ~*a1++; + a.pad0(); + return a; +} + + +/*! + \relates QBitArray + + Returns the AND result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa QBitArray::operator&=() +*/ + +QBitArray operator&( const QBitArray &a1, const QBitArray &a2 ) +{ + QBitArray tmp = a1.copy(); + tmp &= a2; + return tmp; +} + +/*! + \relates QBitArray + + Returns the OR result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa QBitArray::operator|=() +*/ + +QBitArray operator|( const QBitArray &a1, const QBitArray &a2 ) +{ + QBitArray tmp = a1.copy(); + tmp |= a2; + return tmp; +} + +/*! + \relates QBitArray + + Returns the XOR result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa QBitArray::operator^() +*/ + +QBitArray operator^( const QBitArray &a1, const QBitArray &a2 ) +{ + QBitArray tmp = a1.copy(); + tmp ^= a2; + return tmp; +} + + +/* \enum QGArray::array_data + + \warning This will be renamed in the next major release of Qt. Until + then it is undocumented and we recommend against its use. + + \internal + + ### 3.0 rename ### + ### 3.0 move it to QGArray? ### +*/ + + +/*! + \fn QBitArray::array_data * QBitArray::newData() + + \internal + + Returns data specific to QBitArray that extends what QGArray provides. + QPtrCollection mechanism for allowing extra/different data. +*/ + + +/*! + \fn void QBitArray::deleteData ( array_data * d ) + + \internal + + Deletes data specific to QBitArray that extended what QGArray provided. + + QPtrCollection mechanism for allowing extra/different data. +*/ + + +/***************************************************************************** + QBitArray stream functions + *****************************************************************************/ + +/*! + \relates QBitArray + + Writes bit array \a a to stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<( QDataStream &s, const QBitArray &a ) +{ + Q_UINT32 len = a.size(); + s << len; // write size of array + if ( len > 0 ) // write data + s.writeRawBytes( a.data(), a.QByteArray::size() ); + return s; +} + +/*! + \relates QBitArray + + Reads a bit array into \a a from stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QBitArray &a ) +{ + Q_UINT32 len; + s >> len; // read size of array + if ( !a.resize( (uint)len ) ) { // resize array +#if defined(QT_CHECK_NULL) + qWarning( "QDataStream: Not enough memory to read QBitArray" ); +#endif + len = 0; + } + if ( len > 0 ) // read data + s.readRawBytes( a.data(), a.QByteArray::size() ); + return s; +} + +#endif // QT_NO_DATASTREAM diff --git a/qmake/tools/qbuffer.cpp b/qmake/tools/qbuffer.cpp new file mode 100644 index 0000000..b213dd9 --- a/dev/null +++ b/qmake/tools/qbuffer.cpp @@ -0,0 +1,495 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QBuffer class +** +** Created : 930812 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qbuffer.h" +#include <stdlib.h> + +/*! + \class QBuffer qbuffer.h + \reentrant + \brief The QBuffer class is an I/O device that operates on a QByteArray. + + \ingroup io + \ingroup collection + + QBuffer is used to read and write to a memory buffer. It is + normally used with a QTextStream or a QDataStream. QBuffer has an + associated QByteArray which holds the buffer data. The size() of + the buffer is automatically adjusted as data is written. + + The constructor \c QBuffer(QByteArray) creates a QBuffer using an + existing byte array. The byte array can also be set with + setBuffer(). Writing to the QBuffer will modify the original byte + array because QByteArray is \link shclass.html explicitly + shared.\endlink + + Use open() to open the buffer before use and to set the mode + (read-only, write-only, etc.). close() closes the buffer. The + buffer must be closed before reopening or calling setBuffer(). + + A common way to use QBuffer is through \l QDataStream or \l + QTextStream, which have constructors that take a QBuffer + parameter. For convenience, there are also QDataStream and + QTextStream constructors that take a QByteArray parameter. These + constructors create and open an internal QBuffer. + + Note that QTextStream can also operate on a QString (a Unicode + string); a QBuffer cannot. + + You can also use QBuffer directly through the standard QIODevice + functions readBlock(), writeBlock() readLine(), at(), getch(), + putch() and ungetch(). + + \sa QFile, QDataStream, QTextStream, QByteArray, \link shclass.html Shared Classes\endlink +*/ + + +/*! + Constructs an empty buffer. +*/ + +QBuffer::QBuffer() +{ + setFlags( IO_Direct ); + a_inc = 16; // initial increment + a_len = 0; + ioIndex = 0; +} + + +/*! + Constructs a buffer that operates on \a buf. + + If you open the buffer in write mode (\c IO_WriteOnly or + \c IO_ReadWrite) and write something into the buffer, \a buf + will be modified. + + Example: + \code + QCString str = "abc"; + QBuffer b( str ); + b.open( IO_WriteOnly ); + b.at( 3 ); // position at the 4th character (the terminating \0) + b.writeBlock( "def", 4 ); // write "def" including the terminating \0 + b.close(); + // Now, str == "abcdef" with a terminating \0 + \endcode + + \sa setBuffer() +*/ + +QBuffer::QBuffer( QByteArray buf ) : a(buf) +{ + setFlags( IO_Direct ); + a_len = a.size(); + a_inc = (a_len > 512) ? 512 : a_len; // initial increment + if ( a_inc < 16 ) + a_inc = 16; + ioIndex = 0; +} + +/*! + Destroys the buffer. +*/ + +QBuffer::~QBuffer() +{ +} + + +/*! + Replaces the buffer's contents with \a buf and returns TRUE. + + Does nothing (and returns FALSE) if isOpen() is TRUE. + + Note that if you open the buffer in write mode (\c IO_WriteOnly or + IO_ReadWrite) and write something into the buffer, \a buf is also + modified because QByteArray is an explicitly shared class. + + \sa buffer(), open(), close() +*/ + +bool QBuffer::setBuffer( QByteArray buf ) +{ + if ( isOpen() ) { +#if defined(QT_CHECK_STATE) + qWarning( "QBuffer::setBuffer: Buffer is open" ); +#endif + return FALSE; + } + a = buf; + a_len = a.size(); + a_inc = (a_len > 512) ? 512 : a_len; // initial increment + if ( a_inc < 16 ) + a_inc = 16; + ioIndex = 0; + return TRUE; +} + +/*! + \fn QByteArray QBuffer::buffer() const + + Returns this buffer's byte array. + + \sa setBuffer() +*/ + +/*! + \reimp + + Opens the buffer in mode \a m. Returns TRUE if successful; + otherwise returns FALSE. The buffer must be opened before use. + + The mode parameter \a m must be a combination of the following flags. + \list + \i \c IO_ReadOnly opens the buffer in read-only mode. + \i \c IO_WriteOnly opens the buffer in write-only mode. + \i \c IO_ReadWrite opens the buffer in read/write mode. + \i \c IO_Append sets the buffer index to the end of the buffer. + \i \c IO_Truncate truncates the buffer. + \endlist + + \sa close(), isOpen() +*/ + +bool QBuffer::open( int m ) +{ + if ( isOpen() ) { // buffer already open +#if defined(QT_CHECK_STATE) + qWarning( "QBuffer::open: Buffer already open" ); +#endif + return FALSE; + } + setMode( m ); + if ( m & IO_Truncate ) { // truncate buffer + a.resize( 0 ); + a_len = 0; + } + if ( m & IO_Append ) { // append to end of buffer + ioIndex = a.size(); + } else { + ioIndex = 0; + } + a_inc = 16; + setState( IO_Open ); + setStatus( 0 ); + return TRUE; +} + +/*! + \reimp + + Closes an open buffer. + + \sa open() +*/ + +void QBuffer::close() +{ + if ( isOpen() ) { + setFlags( IO_Direct ); + ioIndex = 0; + a_inc = 16; + } +} + +/*! + \reimp + + The flush function does nothing for a QBuffer. +*/ + +void QBuffer::flush() +{ + return; +} + + +/*! + \fn QIODevice::Offset QBuffer::at() const + + \reimp +*/ + +/*! + \fn QIODevice::Offset QBuffer::size() const + + \reimp +*/ + +/*! + \reimp +*/ + +bool QBuffer::at( Offset pos ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + qWarning( "QBuffer::at: Buffer is not open" ); + return FALSE; + } +#endif + if ( pos > a_len ) { +#if defined(QT_CHECK_RANGE) +#if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) + qWarning( "QBuffer::at: Index %llu out of range", pos ); +#else + qWarning( "QBuffer::at: Index %lu out of range", pos ); +#endif +#endif + return FALSE; + } + ioIndex = pos; + return TRUE; +} + + +/*! + \reimp +*/ + +Q_LONG QBuffer::readBlock( char *p, Q_ULONG len ) +{ +#if defined(QT_CHECK_STATE) + if ( !p ) { + qWarning( "QBuffer::readBlock: Null pointer error" ); + return -1; + } + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::readBlock: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QBuffer::readBlock: Read operation not permitted" ); + return -1; + } +#endif + if ( ioIndex + len > a.size() ) { // overflow + if ( ioIndex >= a.size() ) { + return 0; + } else { + len = a.size() - ioIndex; + } + } + memcpy( p, a.data()+ioIndex, len ); + ioIndex += len; + return len; +} + +/*! + \overload Q_LONG QBuffer::writeBlock( const QByteArray& data ) + + This convenience function is the same as calling + \c{writeBlock( data.data(), data.size() )} with \a data. +*/ + +/*! + Writes \a len bytes from \a p into the buffer at the current + index position, overwriting any characters there and extending the + buffer if necessary. Returns the number of bytes actually written. + + Returns -1 if an error occurred. + + \sa readBlock() +*/ + +Q_LONG QBuffer::writeBlock( const char *p, Q_ULONG len ) +{ + if ( len == 0 ) + return 0; + +#if defined(QT_CHECK_NULL) + if ( p == 0 ) { + qWarning( "QBuffer::writeBlock: Null pointer error" ); + return -1; + } +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::writeBlock: Buffer not open" ); + return -1; + } + if ( !isWritable() ) { // writing not permitted + qWarning( "QBuffer::writeBlock: Write operation not permitted" ); + return -1; + } +#endif + if ( ioIndex + len >= a_len ) { // overflow + Q_ULONG new_len = a_len + a_inc*((ioIndex+len-a_len)/a_inc+1); + if ( !a.resize( new_len ) ) { // could not resize +#if defined(QT_CHECK_NULL) + qWarning( "QBuffer::writeBlock: Memory allocation error" ); +#endif + setStatus( IO_ResourceError ); + return -1; + } + a_inc *= 2; // double increment + a_len = new_len; + a.shd->len = ioIndex + len; + } + memcpy( a.data()+ioIndex, p, len ); + ioIndex += len; + if ( a.shd->len < ioIndex ) + a.shd->len = ioIndex; // fake (not alloc'd) length + return len; +} + + +/*! + \reimp +*/ + +Q_LONG QBuffer::readLine( char *p, Q_ULONG maxlen ) +{ +#if defined(QT_CHECK_NULL) + if ( p == 0 ) { + qWarning( "QBuffer::readLine: Null pointer error" ); + return -1; + } +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::readLine: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QBuffer::readLine: Read operation not permitted" ); + return -1; + } +#endif + if ( maxlen == 0 ) + return 0; + Q_ULONG start = ioIndex; + char *d = a.data() + ioIndex; + maxlen--; // make room for 0-terminator + if ( a.size() - ioIndex < maxlen ) + maxlen = a.size() - ioIndex; + while ( maxlen-- ) { + if ( (*p++ = *d++) == '\n' ) + break; + } + *p = '\0'; + ioIndex = d - a.data(); + return ioIndex - start; +} + + +/*! + \reimp +*/ + +int QBuffer::getch() +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::getch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QBuffer::getch: Read operation not permitted" ); + return -1; + } +#endif + if ( ioIndex+1 > a.size() ) { // overflow + setStatus( IO_ReadError ); + return -1; + } + return uchar(*(a.data()+ioIndex++)); +} + +/*! + \reimp + + Writes the character \a ch into the buffer at the current index + position, overwriting any existing character and extending the + buffer if necessary. + + Returns \a ch, or -1 if an error occurred. + + \sa getch(), ungetch() +*/ + +int QBuffer::putch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::putch: Buffer not open" ); + return -1; + } + if ( !isWritable() ) { // writing not permitted + qWarning( "QBuffer::putch: Write operation not permitted" ); + return -1; + } +#endif + if ( ioIndex + 1 >= a_len ) { // overflow + char buf[1]; + buf[0] = (char)ch; + if ( writeBlock(buf,1) != 1 ) + return -1; // write error + } else { + *(a.data() + ioIndex++) = (char)ch; + if ( a.shd->len < ioIndex ) + a.shd->len = ioIndex; + } + return ch; +} + +/*! + \reimp +*/ + +int QBuffer::ungetch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QBuffer::ungetch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QBuffer::ungetch: Read operation not permitted" ); + return -1; + } +#endif + if ( ch != -1 ) { + if ( ioIndex ) + ioIndex--; + else + ch = -1; + } + return ch; +} + diff --git a/qmake/tools/qcomlibrary.cpp b/qmake/tools/qcomlibrary.cpp new file mode 100644 index 0000000..a7162fc --- a/dev/null +++ b/qmake/tools/qcomlibrary.cpp @@ -0,0 +1,538 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QComLibrary class +** +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qcomlibrary_p.h" + +#ifndef QT_NO_COMPONENT +#include <qapplication.h> +#include <qsettings.h> +#include <qfileinfo.h> +#include <qdatetime.h> +#include <qcleanuphandler.h> +#include <errno.h> + +#ifdef QT_THREAD_SUPPORT +# include "qmutexpool_p.h" +#endif // QT_THREAD_SUPPORT + +#ifndef QT_DEBUG_COMPONENT +# if defined(QT_DEBUG) +# define QT_DEBUG_COMPONENT 1 +# endif +#endif + + +QComLibrary::QComLibrary( const QString &filename ) + : QLibrary( filename ), entry( 0 ), libiface( 0 ), qt_version( 0 ) +{ +} + +QComLibrary::~QComLibrary() +{ + if ( autoUnload() ) + unload(); +} + +bool QComLibrary::unload() +{ + if ( libiface ) { + libiface->cleanup(); + if ( !libiface->canUnload() ) + return FALSE; + libiface->release(); + libiface = 0; + } + int refs = entry ? entry->release() : 0; + if ( refs ) + return FALSE; + + entry = 0; + + return QLibrary::unload(); +} + +static bool qt_verify( const QString& library, uint version, uint flags, + const QCString &key, bool warn ) +{ + uint our_flags = 1; +#if defined(QT_THREAD_SUPPORT) + our_flags |= 2; +#endif + + if ( (flags & 1) == 0 ) { + if ( warn ) + qWarning( "Conflict in %s:\n" + " Plugin cannot be queried successfully!", + (const char*) QFile::encodeName(library) ); + } else if ( ( version > QT_VERSION ) || + ( ( QT_VERSION & 0xff0000 ) > ( version & 0xff0000 ) ) ) { + if ( warn ) + qWarning( "Conflict in %s:\n" + " Plugin uses incompatible Qt library (%d.%d.%d)!", + (const char*) QFile::encodeName(library), + (version&0xff0000) >> 16, (version&0xff00) >> 8, version&0xff ); + } else if ( (flags & 2) != (our_flags & 2) ) { + if ( warn ) + qWarning( "Conflict in %s:\n" + " Plugin uses %s Qt library!", + (const char*) QFile::encodeName(library), + (flags & 2) ? "multi threaded" : "single threaded" ); + } else if ( key != QT_BUILD_KEY ) { + if ( warn ) + qWarning( "Conflict in %s:\n" + " Plugin uses incompatible Qt library!\n" + " expected build key \"%s\", got \"%s\".", + (const char*) QFile::encodeName(library), + QT_BUILD_KEY, + key.isEmpty() ? "<null>" : (const char *) key ); + } else { + return TRUE; + } + return FALSE; +} + +struct qt_token_info +{ + qt_token_info( const char *f, const ulong fc ) + : fields( f ), field_count( fc ), results( fc ), lengths( fc ) + { + results.fill( 0 ); + lengths.fill( 0 ); + } + + const char *fields; + const ulong field_count; + + QMemArray<const char *> results; + QMemArray<ulong> lengths; +}; + +/* + return values: + 1 parse ok + 0 eos + -1 parse error +*/ +static int qt_tokenize( const char *s, ulong s_len, ulong *advance, + const qt_token_info &token_info ) +{ + ulong pos = 0, field = 0, fieldlen = 0; + char current; + int ret = -1; + *advance = 0; + for (;;) { + current = s[ pos ]; + + // next char + ++pos; + ++fieldlen; + ++*advance; + + if ( ! current || pos == s_len + 1 ) { + // save result + token_info.results[ (int)field ] = s; + token_info.lengths[ (int)field ] = fieldlen - 1; + + // end of string + ret = 0; + break; + } + + if ( current == token_info.fields[ field ] ) { + // save result + token_info.results[ (int)field ] = s; + token_info.lengths[ (int)field ] = fieldlen - 1; + + // end of field + fieldlen = 0; + ++field; + if ( field == token_info.field_count - 1 ) { + // parse ok + ret = 1; + } + if ( field == token_info.field_count ) { + // done parsing + break; + } + + // reset string and its length + s = s + pos; + s_len -= pos; + pos = 0; + } + } + + return ret; +} + +/* + returns TRUE if the string s was correctly parsed, FALSE otherwise. +*/ +static bool qt_parse_pattern( const char *s, uint *version, uint *flags, + QCString *key ) +{ + bool ret = TRUE; + + qt_token_info pinfo("=\n", 2); + int parse; + ulong at = 0, advance, parselen = qstrlen( s ); + do { + parse = qt_tokenize( s + at, parselen, &advance, pinfo ); + if ( parse == -1 ) { + ret = FALSE; + break; + } + + at += advance; + parselen -= advance; + + if ( qstrncmp( "version", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { + // parse version string + qt_token_info pinfo2("..-", 3); + if ( qt_tokenize( pinfo.results[ 1 ], pinfo.lengths[ 1 ], + &advance, pinfo2 ) != -1 ) { + QCString m( pinfo2.results[ 0 ], pinfo2.lengths[ 0 ] + 1 ); + QCString n( pinfo2.results[ 1 ], pinfo2.lengths[ 1 ] + 1 ); + QCString p( pinfo2.results[ 2 ], pinfo2.lengths[ 2 ] + 1 ); + *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt(); + } else { + ret = FALSE; + break; + } + } else if ( qstrncmp( "flags", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { + // parse flags string + char ch; + *flags = 0; + ulong p = 0, c = 0, bit = 0; + while ( p < pinfo.lengths[ 1 ] ) { + ch = pinfo.results[ 1 ][ p ]; + bit = pinfo.lengths[ 1 ] - p - 1; + c = 1 << bit; + if ( ch == '1' ) { + *flags |= c; + } else if ( ch != '0' ) { + ret = FALSE; + break; + } + ++p; + } + } else if ( qstrncmp( "buildkey", pinfo.results[ 0 ], + pinfo.lengths[ 0 ] ) == 0 ){ + // save buildkey + *key = QCString( pinfo.results[ 1 ], pinfo.lengths[ 1 ] + 1 ); + } + } while ( parse == 1 && parselen > 0 ); + + return ret; +} + +#if defined(Q_OS_UNIX) + +#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) +# define USE_MMAP +# include <sys/types.h> +# include <sys/mman.h> +#endif // Q_OS_FREEBSD || Q_OS_LINUX + +static long qt_find_pattern( const char *s, ulong s_len, + const char *pattern, ulong p_len ) +{ + /* + this uses the same algorithm as QString::findRev... + + we search from the end of the file because on the supported + systems, the read-only data/text segments are placed at the end + of the file. HOWEVER, when building with debugging enabled, all + the debug symbols are placed AFTER the data/text segments. + + what does this mean? when building in release mode, the search + is fast because the data we are looking for is at the end of the + file... when building in debug mode, the search is slower + because we have to skip over all the debugging symbols first + */ + + if ( ! s || ! pattern || p_len > s_len ) return -1; + ulong i, hs = 0, hp = 0, delta = s_len - p_len; + + for (i = 0; i < p_len; ++i ) { + hs += s[delta + i]; + hp += pattern[i]; + } + i = delta; + for (;;) { + if ( hs == hp && qstrncmp( s + i, pattern, p_len ) == 0 ) + return i; + if ( i == 0 ) + break; + --i; + hs -= s[i + p_len]; + hs += s[i]; + } + + return -1; +} + +/* + This opens the specified library, mmaps it into memory, and searches + for the QT_UCM_VERIFICATION_DATA. The advantage of this approach is that + we can get the verification data without have to actually load the library. + This lets us detect mismatches more safely. + + Returns FALSE if version/flags/key information is not present, or if the + information could not be read. + Returns TRUE if version/flags/key information is present and succesfully read. +*/ +static bool qt_unix_query( const QString &library, uint *version, uint *flags, + QCString *key ) +{ + QFile file( library ); + if (! file.open( IO_ReadOnly ) ) { + qWarning( "%s: %s", (const char*) QFile::encodeName(library), + strerror( errno ) ); + return FALSE; + } + + QByteArray data; + char *filedata = 0; + ulong fdlen = 0; + +#ifdef USE_MMAP + char *mapaddr = 0; + size_t maplen = file.size(); + mapaddr = (char *) mmap( mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0 ); + if ( mapaddr != MAP_FAILED ) { + // mmap succeeded + filedata = mapaddr; + fdlen = maplen; + } else { + // mmap failed + qWarning( "mmap: %s", strerror( errno ) ); +#endif // USE_MMAP + // try reading the data into memory instead + data = file.readAll(); + filedata = data.data(); + fdlen = data.size(); +#ifdef USE_MMAP + } +#endif // USE_MMAP + + // verify that the pattern is present in the plugin + const char *pattern = "pattern=QT_UCM_VERIFICATION_DATA"; + const ulong plen = qstrlen( pattern ); + long pos = qt_find_pattern( filedata, fdlen, pattern, plen ); + + bool ret = FALSE; + if ( pos >= 0 ) { + ret = qt_parse_pattern( filedata + pos, version, flags, key ); + } + +#ifdef USE_MMAP + if ( mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0 ) { + qWarning( "munmap: %s", strerror( errno ) ); + } +#endif // USE_MMAP + + file.close(); + return ret; +} + +#endif // Q_OS_UNIX + + +static QSettings *cache = 0; +static QSingleCleanupHandler<QSettings> cleanup_cache; + +void QComLibrary::createInstanceInternal() +{ + if ( library().isEmpty() ) + return; + + QFileInfo fileinfo( library() ); + QString lastModified = fileinfo.lastModified().toString(); + QString regkey = QString("/Qt Plugins %1.%2/%3") + .arg( ( QT_VERSION & 0xff0000 ) >> 16 ) + .arg( ( QT_VERSION & 0xff00 ) >> 8 ) + .arg( library() ); + QStringList reg; + uint flags = 0; + QCString key; + bool query_done = FALSE; + bool warn_mismatch = TRUE; + + if ( ! query_done ) { + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &cache ) ); +#endif // QT_THREAD_SUPPORT + + if ( ! cache ) { + cache = new QSettings; + cache->insertSearchPath( QSettings::Windows, "/Trolltech" ); + cleanup_cache.set( &cache ); + } + + reg = cache->readListEntry( regkey ); + if ( reg.count() == 4 ) { + // check timestamp + if ( lastModified == reg[3] ) { + qt_version = reg[0].toUInt(0, 16); + flags = reg[1].toUInt(0, 16); + key = reg[2].latin1(); + + query_done = TRUE; + warn_mismatch = FALSE; + } + } + } + +#if defined(Q_OS_UNIX) + if ( ! query_done ) { + // get the query information directly from the plugin without loading + if ( qt_unix_query( library(), &qt_version, &flags, &key ) ) { + // info read succesfully from library + query_done = TRUE; + } + } +#else // !Q_OS_UNIX + if ( ! query_done ) { + // get the query information by loading the plugin + if ( !isLoaded() ) { + Q_ASSERT( entry == 0 ); + if ( !load() ) + return; + } + +# ifdef Q_CC_BOR + typedef const char * __stdcall (*UCMQueryVerificationDataProc)(); +# else + typedef const char * (*UCMQueryVerificationDataProc)(); +# endif + UCMQueryVerificationDataProc ucmQueryVerificationdataProc; + ucmQueryVerificationdataProc = + (UCMQueryVerificationDataProc) resolve( "qt_ucm_query_verification_data" ); + + if ( !ucmQueryVerificationdataProc || + !qt_parse_pattern( ucmQueryVerificationdataProc(), + &qt_version, &flags, &key ) ) { + qt_version = flags = 0; + key = "unknown"; + } else { + query_done = TRUE; + } + } +#endif // Q_OS_UNIX + + QStringList queried; + queried << QString::number( qt_version,16 ) + << QString::number( flags, 16 ) + << key + << lastModified; + + if ( queried != reg ) { + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &cache ) ); +#endif // QT_THREAD_SUPPORT + + cache->writeEntry( regkey, queried ); + // delete the cache, which forces the settings to be written + delete cache; + cache = 0; + } + + if ( ! query_done ) { + if ( warn_mismatch ) { + qWarning( "Conflict in %s:\n Plugin cannot be queried successfully!", + (const char*) QFile::encodeName( library() ) ); + } + unload(); + return; + } + + if ( ! qt_verify( library(), qt_version, flags, key, warn_mismatch ) ) { + unload(); + return; + } else if ( !isLoaded() ) { + Q_ASSERT( entry == 0 ); + if ( !load() ) + return; + } + +#ifdef Q_CC_BOR + typedef QUnknownInterface* __stdcall (*UCMInstanceProc)(); +#else + typedef QUnknownInterface* (*UCMInstanceProc)(); +#endif + UCMInstanceProc ucmInstanceProc; + ucmInstanceProc = (UCMInstanceProc) resolve( "ucm_instantiate" ); +#if defined(QT_DEBUG_COMPONENT) + if ( !ucmInstanceProc ) + qWarning( "%s: Not a UCOM library.", (const char*) QFile::encodeName(library()) ); +#endif + entry = ucmInstanceProc ? ucmInstanceProc() : 0; + + if ( entry ) { + if ( entry->queryInterface( IID_QLibrary, (QUnknownInterface**)&libiface ) == QS_OK ) { + if ( libiface && !libiface->init() ) { + libiface->release(); + libiface = 0; + unload(); + return; + } + } + } else { +#if defined(QT_DEBUG_COMPONENT) + qWarning( "%s: No exported component provided.", (const char*) QFile::encodeName(library()) ); +#endif + unload(); + } +} + +QRESULT QComLibrary::queryInterface( const QUuid& request, QUnknownInterface** iface ) +{ + if ( !entry ) + createInstanceInternal(); + return entry ? entry->queryInterface( request, iface ) : QE_NOCOMPONENT; +} + +uint QComLibrary::qtVersion() +{ + if ( !entry ) + createInstanceInternal(); + return entry ? qt_version : 0; +} + + +#endif // QT_NO_COMPONENT diff --git a/qmake/tools/qcomponentfactory.cpp b/qmake/tools/qcomponentfactory.cpp new file mode 100644 index 0000000..8ea81a8 --- a/dev/null +++ b/qmake/tools/qcomponentfactory.cpp @@ -0,0 +1,352 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of the QComponentFactory class +** +** Created : 990101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qcomponentfactory_p.h" + +#ifndef QT_NO_COMPONENT +#include "qsettings.h" +#include <private/qcomlibrary_p.h> +#include "qdir.h" +#include "qapplication.h" + +/*! + \class QComponentFactory qcomponentfactory.h + \brief The QComponentFactory class provides static functions to create and register components. + + \internal + + The static convenience functions can be used both by applications to instantiate components, + and by component servers to register components. + + The createInstance() function provides a pointer to an interface implemented in a specific + component if the component requested has been installed properly and implements the interface. + + Use registerServer() to load a component server and register its components, and unregisterServer() + to unregister the components. The component exported by the component server has to implement the + QComponentRegistrationInterface. + + The static functions registerComponent() and unregisterComponent() register and unregister a single + component in the system component registry, and should be used when implementing the + \link QComponentRegistrationInterface::registerComponents() registerCompontents() \endlink and + \link QComponentRegistrationInterface::unregisterComponents() unregisterCompontents() \endlink functions + in the QComponentRegistrationInterface. + + A component is registered using a UUID, but can additionally be registered with a name, version and + description. A component registered with a name and a version can be instantiated by client applications + using the name and specific version number, or the highest available version number for that component by + just using the name. A component that is registered calling + + \code + QComponentFactory::registerComponent( QUuid(...), filename, "MyProgram.Component", 1 ); + \endcode + + can be instantiated calling either: + + \code + QComponentFactory::createInstance( QUuid(...), IID_XYZ, (QUnknownInterface**)&iface ); + \endcode + or + \code + QComponentFactory::createInstance( "MyProgram.Component", IID_XYZ, (QUnknownInterface**)&iface ); + \endcode + or + \code + QComponentFactory::createInstance( "MyProgram.Component.1", IID_XYZ, (QUnknownInterface**)&iface ); + \endcode + + The first and the last way will always instantiate exactly the component registered above, while + the second call might also return a later version of the same component. This allows smoother upgrading + of components, and is easier to use in application source code, but should only be used when new versions + of the component are guaranteed to work with the application. + + The component name can be anything, but should be unique on the system the component is being + installed on. A common naming convention for components is \e application.component. + + \sa QComponentRegistrationInterface QComponentFactoryInterface +*/ + + +static QPtrList<QComLibrary> *libraries = 0; + +static void cleanup() +{ + delete libraries; + libraries = 0; +} + +static QPtrList<QComLibrary> *liblist() +{ + if ( !libraries ) { + libraries = new QPtrList<QComLibrary>(); + libraries->setAutoDelete( TRUE ); + qAddPostRoutine( cleanup ); + } + return libraries; +} + +/*! + Searches for the component identifier \a cid in the system component registry, + loads the corresponding component server and queries for the interface \a iid. + \a iface is set to the resulting interface pointer. \a cid can either be the + UUID or the name of the component. + + The parameter \a outer is a pointer to the outer interface used + for containment and aggregation and is propagated to the \link + QComponentFactoryInterface::createInstance() createInstance() \endlink + implementation of the QComponentFactoryInterface in the component server if + provided. + + The function returns QS_OK if the interface was successfully instantiated, QE_NOINTERFACE if + the component does not provide an interface \a iid, or QE_NOCOMPONENT if there was + an error loading the component. + + Example: + \code + QInterfacePtr<MyInterface> iface; + if ( QComponentFactory::createInstance( IID_MyInterface, CID_MyComponent, (QUnknownInterface**)&iface ) == QS_OK ) + iface->doSomething(); + ... + } + \endcode +*/ +QRESULT QComponentFactory::createInstance( const QString &cid, const QUuid &iid, QUnknownInterface** iface, QUnknownInterface *outer ) +{ + QSettings settings; + settings.insertSearchPath( QSettings::Windows, "/Classes" ); + bool ok = FALSE; + QString cidStr = cid; + QRESULT res = QE_NOCOMPONENT; + + QUuid uuid( cidStr ); // try to parse, and resolve CLSID if necessary + if ( uuid.isNull() ) { + uuid = settings.readEntry( "/" + cid + "/CLSID/Default", QString::null, &ok ); + cidStr = uuid.toString().upper(); + } + + if ( cidStr.isEmpty() ) + return res; + + QString file = settings.readEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", QString::null, &ok ); + if ( !ok ) + return res; + + QComLibrary *library = new QComLibrary( file ); + library->setAutoUnload( FALSE ); + + QComponentFactoryInterface *cfIface =0; + library->queryInterface( IID_QComponentFactory, (QUnknownInterface**)&cfIface ); + + if ( cfIface ) { + res = cfIface->createInstance( uuid, iid, iface, outer ); + cfIface->release(); + } else { + res = library->queryInterface( iid, iface ); + } + QLibraryInterface *libiface = 0; + if ( library->queryInterface( IID_QLibrary, (QUnknownInterface**)&libiface ) != QS_OK || !qApp ) { + delete library; // only deletes the object, thanks to QLibrary::Manual + } else { + libiface->release(); + library->setAutoUnload( TRUE ); + liblist()->prepend( library ); + } + return res; +} + +/*! + Loads the shared library \a filename and queries for a + QComponentRegistrationInterface. If the library implements this interface, + the \link QComponentRegistrationInterface::registerComponents() + registerComponents() \endlink function is called. + + Returns TRUE if the interface is found and successfully called, + otherwise returns FALSE. +*/ +QRESULT QComponentFactory::registerServer( const QString &filename ) +{ + QComLibrary lib( filename ); + lib.load(); + QComponentRegistrationInterface *iface = 0; + QRESULT res = lib.queryInterface( IID_QComponentRegistration, (QUnknownInterface**)&iface ); + if ( res != QS_OK ) + return res; + QDir dir( filename ); + bool ok = iface->registerComponents( dir.absPath() ); + iface->release(); + return ok ? QS_OK : QS_FALSE; +} + +/*! + Loads the shared library \a filename and queries for a + QComponentRegistrationInterface. If the library implements this interface, + the \link QComponentRegistrationInterface::unregisterComponents() + unregisterComponents() \endlink function is called. + + Returns TRUE if the interface is found and successfully unregistered, + otherwise returns FALSE. +*/ +QRESULT QComponentFactory::unregisterServer( const QString &filename ) +{ + QComLibrary lib( filename ); + lib.load(); + QComponentRegistrationInterface *iface = 0; + QRESULT res = lib.queryInterface( IID_QComponentRegistration, (QUnknownInterface**)&iface ); + if ( res != QS_OK ) + return res; + bool ok = iface->unregisterComponents(); + iface->release(); + return ok ? QS_OK : QS_FALSE; +} + +/*! + Registers the component with id \a cid in the system component registry and + returns TRUE if the component was registerd successfully, otherwise returns + FALSE. The component is provided by the component server at \a filepath and + registered with an optional \a name, \a version and \a description. + + This function does nothing and returns FALSE if a component with an identical + \a cid does already exist on the system. + + A component that has been registered with a \a name can be created using both the + \a cid and the \a name value using createInstance(). + + Call this function for each component in an implementation of + \link QComponentRegistrationInterface::registerComponents() registerComponents() \endlink. + + \sa unregisterComponent(), registerServer(), createInstance() +*/ +bool QComponentFactory::registerComponent( const QUuid &cid, const QString &filepath, const QString &name, int version, const QString &description ) +{ + bool ok = FALSE; + QSettings settings; + settings.insertSearchPath( QSettings::Windows, "/Classes" ); + + QString cidStr = cid.toString().upper(); + settings.readEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", QString::null, &ok ); + if ( ok ) // don't overwrite existing component + return FALSE; + + ok = settings.writeEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", filepath ); + if ( ok && !!description ) + settings.writeEntry( "/CLSID/" + cidStr + "/Default", description ); + + // register the human readable part + if ( ok && !!name ) { + QString vName = version ? name + "." + QString::number( version ) : name; + settings.writeEntry( "/CLSID/" + cidStr + "/ProgID/Default", vName ); + ok = settings.writeEntry( "/" + vName + "/CLSID/Default", cidStr ); + if ( ok && !!description ) + settings.writeEntry( "/" + vName + "/Default", description ); + + if ( ok && version ) { + settings.writeEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default", name ); + QString curVer = settings.readEntry( "/" + name + "/CurVer/Default" ); + if ( !curVer || curVer < vName ) { // no previous, or a lesser version installed + settings.writeEntry( "/" + name + "/CurVer/Default", vName ); + ok = settings.writeEntry( "/" + name + "/CLSID/Default", cidStr ); + if ( ok && !!description ) + settings.writeEntry( "/" + name + "/Default", description ); + } + } + } + + return ok; +} + +/*! + Unregisters the component with id \a cid from the system component registry and returns + TRUE if the component was unregistered successfully, otherwise returns FALSE. + + Call this function for each component in an implementation of + \link QComponentRegistrationInterface::unregisterComponents() unregisterComponents() \endlink. + + \sa registerComponent(), unregisterServer() +*/ +bool QComponentFactory::unregisterComponent( const QUuid &cid ) +{ + QSettings settings; + bool ok = FALSE; + settings.insertSearchPath( QSettings::Windows, "/Classes" ); + + QString cidStr = cid.toString().upper(); + if ( cidStr.isEmpty() ) + return FALSE; + + // unregister the human readable part + QString vName = settings.readEntry( "/CLSID/" + cidStr + "/ProgID/Default", QString::null, &ok ); + if ( ok ) { + QString name = settings.readEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default", QString::null ); + if ( !!name && settings.readEntry( "/" + name + "/CurVer/Default" ) == vName ) { + // unregistering the current version -> change CurVer to previous version + QString version = vName.right( vName.length() - name.length() - 1 ); + QString newVerName; + QString newCidStr; + if ( version.find( '.' ) == -1 ) { + int ver = version.toInt(); + // see if a lesser version is installed, and make that the CurVer + while ( ver-- ) { + newVerName = name + "." + QString::number( ver ); + newCidStr = settings.readEntry( "/" + newVerName + "/CLSID/Default" ); + if ( !!newCidStr ) + break; + } + } else { + // oh well... + } + if ( !!newCidStr ) { + settings.writeEntry( "/" + name + "/CurVer/Default", newVerName ); + settings.writeEntry( "/" + name + "/CLSID/Default", newCidStr ); + } else { + settings.removeEntry( "/" + name + "/CurVer/Default" ); + settings.removeEntry( "/" + name + "/CLSID/Default" ); + settings.removeEntry( "/" + name + "/Default" ); + } + } + + settings.removeEntry( "/" + vName + "/CLSID/Default" ); + settings.removeEntry( "/" + vName + "/Default" ); + } + + settings.removeEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default" ); + settings.removeEntry( "/CLSID/" + cidStr + "/ProgID/Default" ); + settings.removeEntry( "/CLSID/" + cidStr + "/InprocServer32/Default" ); + ok = settings.removeEntry( "/CLSID/" + cidStr + "/Default" ); + + return ok; +} + +#endif // QT_NO_COMPONENT diff --git a/qmake/tools/qconfig.cpp b/qmake/tools/qconfig.cpp new file mode 100644 index 0000000..433827c --- a/dev/null +++ b/qmake/tools/qconfig.cpp @@ -0,0 +1,17 @@ +/* Install paths from configure */ + +static const char QT_INSTALL_PREFIX [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2"; +static const char QT_INSTALL_BINS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/bin"; +static const char QT_INSTALL_DOCS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/doc"; +static const char QT_INSTALL_HEADERS[256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/include"; +static const char QT_INSTALL_LIBS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/lib"; +static const char QT_INSTALL_PLUGINS[256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/plugins"; +static const char QT_INSTALL_DATA [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2"; + +const char *qInstallPath() { return QT_INSTALL_PREFIX; } +const char *qInstallPathDocs() { return QT_INSTALL_DOCS; } +const char *qInstallPathHeaders() { return QT_INSTALL_HEADERS; } +const char *qInstallPathLibs() { return QT_INSTALL_LIBS; } +const char *qInstallPathBins() { return QT_INSTALL_BINS; } +const char *qInstallPathPlugins() { return QT_INSTALL_PLUGINS; } +const char *qInstallPathData() { return QT_INSTALL_DATA; } diff --git a/qmake/tools/qcriticalsection_p.cpp b/qmake/tools/qcriticalsection_p.cpp new file mode 100644 index 0000000..60fc8bd --- a/dev/null +++ b/qmake/tools/qcriticalsection_p.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QCriticalSection class +** +** Created : +** +** Copyright (C) 2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#if defined(QT_THREAD_SUPPORT) + +#include "qt_windows.h" + +#include <private/qcriticalsection_p.h> + +class QCriticalSectionPrivate +{ +public: + QCriticalSectionPrivate() {} + + CRITICAL_SECTION section; +}; + + +QCriticalSection::QCriticalSection() +{ + d = new QCriticalSectionPrivate; + InitializeCriticalSection( &d->section ); +} + +QCriticalSection::~QCriticalSection() +{ + DeleteCriticalSection( &d->section ); + delete d; +} + +void QCriticalSection::enter() +{ + EnterCriticalSection( &d->section ); +} + +void QCriticalSection::leave() +{ + LeaveCriticalSection( &d->section ); +} + +#endif diff --git a/qmake/tools/qcstring.cpp b/qmake/tools/qcstring.cpp new file mode 100644 index 0000000..cf1b853 --- a/dev/null +++ b/qmake/tools/qcstring.cpp @@ -0,0 +1,2474 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of extended char array operations, and QByteArray and +** QCString classes +** +** Created : 920722 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qstring.h" +#include "qregexp.h" +#include "qdatastream.h" + +#ifdef QT_THREAD_SUPPORT +# include <private/qmutexpool_p.h> +#endif // QT_THREAD_SUPPORT + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <ctype.h> +#include <limits.h> +#ifndef QT_NO_COMPRESS +#include "../3rdparty/zlib/zlib.h" +#endif + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +/*! + \relates QCString + + This function is normally part of the C library. Qt implements + memmove() for platforms that do not provide it. + + memmove() copies \a len bytes from \a src into \a dst. The data + is copied correctly even if \a src and \a dst overlap. +*/ + +void *qmemmove( void *dst, const void *src, uint len ) +{ + register char *d; + register char *s; + if ( dst > src ) { + d = (char *)dst + len - 1; + s = (char *)src + len - 1; + while ( len-- ) + *d-- = *s--; + } else if ( dst < src ) { + d = (char *)dst; + s = (char *)src; + while ( len-- ) + *d++ = *s++; + } + return dst; +} + + +/*! + \relates QCString + + Returns a duplicate string. + + Allocates space for a copy of \a src, copies it, and returns a + pointer to the copy. If \a src is 0, it immediately returns 0. + + The returned string must be deleted using \c delete[]. +*/ + +char *qstrdup( const char *src ) +{ + if ( !src ) + return 0; + char *dst = new char[strlen(src)+1]; + Q_CHECK_PTR( dst ); + return strcpy( dst, src ); +} + +/*! + \fn char *qstrcpy( char *dst, const char *src ) + + \relates QCString + + A safe strcpy() function. + + Copies all characters up to and including the '\0' from \a src + into \a dst and returns a pointer to \a dst. +*/ + +/*! + \relates QCString + + A safe strncpy() function. + + Copies at most \a len bytes from \a src (stopping at \a len or the + terminating '\0' whichever comes first) into \a dst and returns a + pointer to \a dst. Guarantees that \a dst is '\0'-terminated. If + \a src or \a dst is 0, returns 0 immediately. + + \sa qstrcpy() +*/ + +char *qstrncpy( char *dst, const char *src, uint len ) +{ + if ( !src || !dst ) + return 0; + strncpy( dst, src, len ); + if ( len > 0 ) + dst[len-1] = '\0'; + return dst; +} + +/*! + \fn int qstrcmp( const char *str1, const char *str2 ); + + \relates QCString + + A safe strcmp() function. + + Compares \a str1 and \a str2. Returns a negative value if \a str1 + is less than \a str2, 0 if \a str1 is equal to \a str2 or a + positive value if \a str1 is greater than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrncmp() qstricmp() qstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn int qstrncmp( const char *str1, const char *str2, uint len ); + + \relates QCString + + A safe strncmp() function. + + Compares at most \a len bytes of \a str1 and \a str2. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstricmp(), qstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \relates QCString + + A safe stricmp() function. + + Compares \a str1 and \a str2 ignoring the case. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstrncmp(), qstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +int qstricmp( const char *str1, const char *str2 ) +{ + register const uchar *s1 = (const uchar *)str1; + register const uchar *s2 = (const uchar *)str2; + int res; + uchar c; + if ( !s1 || !s2 ) + return s1 ? 1 : ( s2 ? -1 : 0 ); + for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ ) + if ( !c ) // strings are equal + break; + return res; +} + +/*! + \relates QCString + + A safe strnicmp() function. + + Compares at most \a len bytes of \a str1 and \a str2 ignoring the case. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 + is equal to \a str2 or a positive value if \a str1 is greater than \a + str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstrncmp() qstricmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +int qstrnicmp( const char *str1, const char *str2, uint len ) +{ + register const uchar *s1 = (const uchar *)str1; + register const uchar *s2 = (const uchar *)str2; + int res; + uchar c; + if ( !s1 || !s2 ) + return s1 ? 1 : ( s2 ? -1 : 0 ); + for ( ; len--; s1++, s2++ ) { + if ( (res = (c=tolower(*s1)) - tolower(*s2)) ) + return res; + if ( !c ) // strings are equal + break; + } + return 0; +} + + +static Q_UINT16 crc_tbl[16]; +static bool crc_tbl_init = FALSE; + +static void createCRC16Table() // build CRC16 lookup table +{ + register uint i; + register uint j; + uint v0, v1, v2, v3; + for ( i = 0; i < 16; i++ ) { + v0 = i & 1; + v1 = ( i >> 1 ) & 1; + v2 = ( i >> 2 ) & 1; + v3 = ( i >> 3 ) & 1; + j = 0; +#undef SET_BIT +#define SET_BIT(x, b, v) (x) |= (v) << (b) + SET_BIT( j, 0, v0 ); + SET_BIT( j, 7, v0 ); + SET_BIT( j, 12, v0 ); + SET_BIT( j, 1, v1 ); + SET_BIT( j, 8, v1 ); + SET_BIT( j, 13, v1 ); + SET_BIT( j, 2, v2 ); + SET_BIT( j, 9, v2 ); + SET_BIT( j, 14, v2 ); + SET_BIT( j, 3, v3 ); + SET_BIT( j, 10, v3 ); + SET_BIT( j, 15, v3 ); + crc_tbl[i] = j; + } +} + +/*! + \relates QMemArray + + Returns the CRC-16 checksum of \a len bytes starting at \a data. + + The checksum is independent of the byte order (endianness). +*/ + +Q_UINT16 qChecksum( const char *data, uint len ) +{ + if ( !crc_tbl_init ) { // create lookup table + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &crc_tbl_init ) ); +#endif // QT_THREAD_SUPPORT + + if ( !crc_tbl_init ) { + createCRC16Table(); + crc_tbl_init = TRUE; + } + } + register Q_UINT16 crc = 0xffff; + uchar c; + uchar *p = (uchar *)data; + while ( len-- ) { + c = *p++; + crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; + c >>= 4; + crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; + } + return ~crc & 0xffff; +} + +/*! \fn QByteArray qCompress( const QByteArray& data) + \relates QByteArray + \overload +*/ + +/*! + \relates QByteArray + + Compresses the array \a data which is \a nbytes long and returns the + compressed byte array. + + \sa qUncompress() +*/ + +#ifndef QT_NO_COMPRESS +QByteArray qCompress( const uchar* data, int nbytes ) +{ + if ( nbytes == 0 ) { + QByteArray tmp( 4 ); + tmp.fill( 0 ); + return tmp; + } + if ( !data ) { +#if defined(QT_CHECK_RANGE) + qWarning( "qCompress: data is NULL." ); +#endif + return QByteArray(); + } + + ulong len = nbytes * 2; + QByteArray bazip; + int res; + do { + bazip.resize( len + 4 ); + res = ::compress( (uchar*)bazip.data()+4, &len, (uchar*)data, nbytes ); + + switch ( res ) { + case Z_OK: + bazip.resize( len + 4 ); + bazip[0] = ( nbytes & 0xff000000 ) >> 24; + bazip[1] = ( nbytes & 0x00ff0000 ) >> 16; + bazip[2] = ( nbytes & 0x0000ff00 ) >> 8; + bazip[3] = ( nbytes & 0x000000ff ); + break; + case Z_MEM_ERROR: +#if defined(QT_CHECK_RANGE) + qWarning( "qCompress: Z_MEM_ERROR: Not enough memory." ); +#endif + bazip.resize( 0 ); + break; + case Z_BUF_ERROR: + len *= 2; + break; + } + } while ( res == Z_BUF_ERROR ); + + return bazip; +} +#endif + +/*! \fn QByteArray qUncompress( const QByteArray& data ) + \relates QByteArray + \overload +*/ + +/*! + \relates QByteArray + + Uncompresses the array \a data which is \a nbytes long and returns + the uncompressed byte array. + + Returns an empty QByteArray if the input data was corrupt. + + \sa qCompress() +*/ + +#ifndef QT_NO_COMPRESS +QByteArray qUncompress( const uchar* data, int nbytes ) +{ + if ( !data ) { +#if defined(QT_CHECK_RANGE) + qWarning( "qUncompress: data is NULL." ); +#endif + return QByteArray(); + } + if ( nbytes <= 4 ) { +#if defined(QT_CHECK_RANGE) + if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) ) + qWarning( "qUncompress: Input data is corrupted." ); +#endif + return QByteArray(); + } + ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3]; + ulong len = QMAX( expectedSize, 1 ); + QByteArray baunzip; + int res; + do { + baunzip.resize( len ); + res = ::uncompress( (uchar*)baunzip.data(), &len, + (uchar*)data+4, nbytes-4 ); + + switch ( res ) { + case Z_OK: + if ( len != baunzip.size() ) + baunzip.resize( len ); + break; + case Z_MEM_ERROR: +#if defined(QT_CHECK_RANGE) + qWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." ); +#endif + break; + case Z_BUF_ERROR: + len *= 2; + break; + case Z_DATA_ERROR: +#if defined(QT_CHECK_RANGE) + qWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." ); +#endif + break; + } + } while ( res == Z_BUF_ERROR ); + + if ( res != Z_OK ) + baunzip = QByteArray(); + + return baunzip; +} +#endif + +/***************************************************************************** + QByteArray documentation + *****************************************************************************/ + +/*! + \class QByteArray + \reentrant + \brief The QByteArray class provides an array of bytes. + + \ingroup collection + \ingroup tools + + The QByteArray class provides an explicitly shared array of bytes. + It is useful for manipulating memory areas with custom data. + QByteArray is implemented as a QMemArray\<char\>. See the \l + QMemArray documentation for further information. +*/ + +/*! + \fn QByteArray::QByteArray() + + Constructs an empty QByteArray. +*/ + +/*! + \fn QByteArray::QByteArray( int size ) + + Constructs a QByteArray of size \a size. +*/ + +/***************************************************************************** + QByteArray stream functions + *****************************************************************************/ + +/*! + \relates QMemArray + + Writes byte array \a a to the stream \a s and returns a reference + to the stream. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<( QDataStream &s, const QByteArray &a ) +{ + return s.writeBytes( a.data(), a.size() ); +} + +/*! + \relates QMemArray + + Reads a byte array into \a a from the stream \a s and returns a + reference to the stream. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QByteArray &a ) +{ + Q_UINT32 len; + s >> len; // read size of array + if ( len == 0 || s.eof() ) { // end of file reached + a.resize( 0 ); + return s; + } + if ( !a.resize( (uint)len ) ) { // resize array +#if defined(QT_CHECK_NULL) + qWarning( "QDataStream: Not enough memory to read QByteArray" ); +#endif + len = 0; + } + if ( len > 0 ) // not null array + s.readRawBytes( a.data(), (uint)len ); + return s; +} + +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + QCString member functions + *****************************************************************************/ + +/*! + \class QCString qcstring.h + \reentrant + \brief The QCString class provides an abstraction of the classic C + zero-terminated char array (char *). + + \ingroup text + \ingroup collection + \ingroup tools + \ingroup shared + + QCString inherits QByteArray, which is defined as + QMemArray\<char\>. Since QCString is a QMemArray, it uses \link + shclass.html explicit sharing\endlink with a reference count. + + QCString tries to behave like a more convenient \c{const char *}. + The price of doing this is that some algorithms will perform + badly. For example, append() is O(length()) since it scans for a + null terminator. Although you might use QCString for text that is + never exposed to the user, for most purposes, and especially for + user-visible text, you should use QString. QString provides + implicit sharing, Unicode and other internationalization support, + and is well optimized. + + Note that for the QCString methods that take a \c{const char *} + parameter the \c{const char *} must either be 0 (null) or not-null + and '\0' (NUL byte) terminated; otherwise the results are + undefined. + + A QCString that has not been assigned to anything is \e null, i.e. + both the length and the data pointer is 0. A QCString that + references the empty string ("", a single '\0' char) is \e empty. + Both null and empty QCStrings are legal parameters to the methods. + Assigning \c{const char *} 0 to QCString produces a null QCString. + + The length() function returns the length of the string; resize() + resizes the string and truncate() truncates the string. A string + can be filled with a character using fill(). Strings can be left + or right padded with characters using leftJustify() and + rightJustify(). Characters, strings and regular expressions can be + searched for using find() and findRev(), and counted using + contains(). + + Strings and characters can be inserted with insert() and appended + with append(). A string can be prepended with prepend(). + Characters can be removed from the string with remove() and + replaced with replace(). + + Portions of a string can be extracted using left(), right() and + mid(). Whitespace can be removed using stripWhiteSpace() and + simplifyWhiteSpace(). Strings can be converted to uppercase or + lowercase with upper() and lower() respectively. + + Strings that contain numbers can be converted to numbers with + toShort(), toInt(), toLong(), toULong(), toFloat() and toDouble(). + Numbers can be converted to strings with setNum(). + + Many operators are overloaded to work with QCStrings. QCString + also supports some more obscure functions, e.g. sprintf(), + setStr() and setExpand(). + + \target asciinotion + \sidebar Note on Character Comparisons + + In QCString the notion of uppercase and lowercase and of which + character is greater than or less than another character is locale + dependent. This affects functions which support a case insensitive + option or which compare or lowercase or uppercase their arguments. + Case insensitive operations and comparisons will be accurate if + both strings contain only ASCII characters. (If \c $LC_CTYPE is + set, most Unix systems do "the right thing".) Functions that this + affects include contains(), find(), findRev(), \l operator<(), \l + operator<=(), \l operator>(), \l operator>=(), lower() and + upper(). + + This issue does not apply to \l{QString}s since they represent + characters using Unicode. + \endsidebar + + Performance note: The QCString methods for QRegExp searching are + implemented by converting the QCString to a QString and performing + the search on that. This implies a deep copy of the QCString data. + If you are going to perform many QRegExp searches on a large + QCString, you will get better performance by converting the + QCString to a QString yourself, and then searching in the QString. +*/ + +/*! + \fn QCString::QCString() + + Constructs a null string. + + \sa isNull() +*/ + +/*! + \fn QCString::QCString( const QCString &s ) + + Constructs a shallow copy \a s. + + \sa assign() +*/ + +/*! + Constructs a string with room for \a size characters, including + the '\0'-terminator. Makes a null string if \a size == 0. + + If \a size \> 0, then the first and last characters in the string + are initialized to '\0'. All other characters are uninitialized. + + \sa resize(), isNull() +*/ + +QCString::QCString( int size ) + : QByteArray( size ) +{ + if ( size > 0 ) { + *data() = '\0'; // set terminator + *(data()+(size-1)) = '\0'; + } +} + +/*! + Constructs a string that is a deep copy of \a str. + + If \a str is 0 a null string is created. + + \sa isNull() +*/ + +QCString::QCString( const char *str ) +{ + duplicate( str, qstrlen(str) + 1 ); +} + + +/*! + Constructs a string that is a deep copy of \a str. The copy will + be at most \a maxsize bytes long including the '\0'-terminator. + + Example: + \code + QCString str( "helloworld", 6 ); // assigns "hello" to str + \endcode + + If \a str contains a 0 byte within the first \a maxsize bytes, the + resulting QCString will be terminated by this 0. If \a str is 0 a + null string is created. + + \sa isNull() +*/ + +QCString::QCString( const char *str, uint maxsize ) +{ + if ( str == 0 ) + return; + uint len; // index of first '\0' + for ( len = 0; len < maxsize - 1; len++ ) { + if ( str[len] == '\0' ) + break; + } + QByteArray::resize( len + 1 ); + memcpy( data(), str, len ); + data()[len] = 0; +} + +/*! + \reimp +*/ + +QCString::~QCString() +{ +} + +/*! + \fn QCString &QCString::operator=( const QCString &s ) + + Assigns a shallow copy of \a s to this string and returns a + reference to this string. +*/ + +/*! + \overload QCString &QCString::operator=( const char *str ) + + Assigns a deep copy of \a str to this string and returns a + reference to this string. + + If \a str is 0 a null string is created. + + \sa isNull() +*/ + +/*! + \fn bool QCString::isNull() const + + Returns TRUE if the string is null, i.e. if data() == 0; otherwise + returns FALSE. A null string is also an empty string. + + Example: + \code + QCString a; // a.data() == 0, a.size() == 0, a.length() == 0 + QCString b == ""; // b.data() == "", b.size() == 1, b.length() == 0 + a.isNull(); // TRUE because a.data() == 0 + a.isEmpty(); // TRUE because a.length() == 0 + b.isNull(); // FALSE because b.data() == "" + b.isEmpty(); // TRUE because b.length() == 0 + \endcode + + \sa isEmpty(), length(), size() +*/ + +/*! + \fn bool QCString::isEmpty() const + + Returns TRUE if the string is empty, i.e. if length() == 0; + otherwise returns FALSE. An empty string is not always a null + string. + + See example in isNull(). + + \sa isNull(), length(), size() +*/ + +/*! + \fn uint QCString::length() const + + Returns the length of the string, excluding the '\0'-terminator. + Equivalent to calling \c strlen(data()). + + Null strings and empty strings have zero length. + + \sa size(), isNull(), isEmpty() +*/ + +/*! + \fn bool QCString::truncate( uint pos ) + + Truncates the string at position \a pos. + + Equivalent to calling \c resize(pos+1). + + Example: + \code + QCString s = "truncate this string"; + s.truncate( 5 ); // s == "trunc" + \endcode + + \sa resize() +*/ + +/*! + Extends or shrinks the string to \a len bytes, including the + '\0'-terminator. + + A '\0'-terminator is set at position \c{len - 1} unless + \c{len == 0}. + + Example: + \code + QCString s = "resize this string"; + s.resize( 7 ); // s == "resize" + \endcode + + \sa truncate() +*/ + +bool QCString::resize( uint len ) +{ + detach(); + uint wasNull = isNull(); + if ( !QByteArray::resize(len) ) + return FALSE; + if ( len ) + data()[len - 1] = '\0'; + if ( len > 0 && wasNull ) + data()[0] = '\0'; + return TRUE; +} + + +/*! + Implemented as a call to the native vsprintf() (see the manual for + your C library). + + If the string is shorter than 256 characters, this sprintf() calls + resize(256) to decrease the chance of memory corruption. The + string is resized back to its actual length before sprintf() + returns. + + Example: + \code + QCString s; + s.sprintf( "%d - %s", 1, "first" ); // result < 256 chars + + QCString big( 25000 ); // very long string + big.sprintf( "%d - %s", 2, longString ); // result < 25000 chars + \endcode + + \warning All vsprintf() implementations will write past the end of + the target string (*this) if the \a format specification and + arguments happen to be longer than the target string, and some + will also fail if the target string is longer than some arbitrary + implementation limit. + + Giving user-supplied arguments to sprintf() is risky: Sooner or + later someone will paste a huge line into your application. +*/ + +QCString &QCString::sprintf( const char *format, ... ) +{ + detach(); + va_list ap; + va_start( ap, format ); + if ( size() < 256 ) + QByteArray::resize( 256 ); // make string big enough + vsprintf( data(), format, ap ); + resize( qstrlen(data()) + 1 ); // truncate + va_end( ap ); + return *this; +} + + +/*! + Fills the string with \a len bytes of character \a c, followed by + a '\0'-terminator. + + If \a len is negative, then the current string length is used. + + Returns FALSE is \a len is nonnegative and there is not enough + memory to resize the string; otherwise returns TRUE. +*/ + +bool QCString::fill( char c, int len ) +{ + detach(); + if ( len < 0 ) + len = length(); + if ( !QByteArray::fill(c,len+1) ) + return FALSE; + *(data()+len) = '\0'; + return TRUE; +} + + +/*! + \fn QCString QCString::copy() const + + Returns a deep copy of this string. + + \sa detach() +*/ + + +/*! + Finds the first occurrence of the character \a c, starting at + position \a index. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a c, or -1 if \a c could not be found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::find( char c, int index, bool cs ) const +{ + if ( (uint)index >= size() ) // index outside string + return -1; + register const char *d; + if ( cs ) { // case sensitive + d = strchr( data()+index, c ); + } else { + d = data()+index; + c = tolower( (uchar) c ); + while ( *d && tolower((uchar) *d) != c ) + d++; + if ( !*d && c ) // not found + d = 0; + } + return d ? (int)(d - data()) : -1; +} + +#define REHASH( a ) \ + if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \ + hashHaystack -= (a) << sl_minus_1; \ + hashHaystack <<= 1 + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a str, or -1 if \a str could not be + found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::find( const char *str, int index, bool cs ) const +{ + if ( (uint)index >= size() ) + return -1; + if ( !str ) + return -1; + if ( !*str ) + return index; + const uint l = length(); + const uint sl = qstrlen( str ); + if ( sl + index > l ) + return -1; + + if ( sl == 1 ) + return find( *str, index, cs ); + + /* + See QString::find() for details. + */ + const char* needle = str; + const char* haystack = data() + index; + const char* end = data() + (l-sl); + const uint sl_minus_1 = sl-1; + uint hashNeedle = 0, hashHaystack = 0,i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + needle[i] ); + hashHaystack = ((hashHaystack<<1) + haystack[i] ); + } + hashHaystack -= *(haystack+sl_minus_1); + + while ( haystack <= end ) { + hashHaystack += *(haystack+sl_minus_1); + if ( hashHaystack == hashNeedle && *needle == *haystack + && qstrncmp( needle, haystack, sl ) == 0 ) + return haystack - data(); + + REHASH( *haystack ); + ++haystack; + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + tolower( needle[i] ) ); + hashHaystack = ((hashHaystack<<1) + + tolower( haystack[i] ) ); + } + hashHaystack -= tolower(*(haystack+sl_minus_1)); + + while ( haystack <= end ) { + hashHaystack += tolower(*(haystack+sl_minus_1)); + if ( hashHaystack == hashNeedle + && qstrnicmp( needle, haystack, sl ) == 0 ) + return haystack - data(); + + REHASH( tolower(*haystack) ); + ++haystack; + } + } + return -1; +} + + +/*! + Finds the first occurrence of the character \a c, starting at + position \a index and searching backwards. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a c, or -1 if \a c could not be found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::findRev( char c, int index, bool cs ) const +{ + register const char *b = data(); + register const char *d; + if ( index < 0 ) + index = length(); + if ( (uint)index >= size() ) + return -1; + d = b + index; + if ( cs ) { + while ( d >= b && *d != c ) + d--; + } else { + c = tolower( (uchar) c ); + while ( d >= b && tolower((uchar) *d) != c ) + d--; + } + return d >= b ? (int)(d - b) : -1; +} + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index and searching backwards. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a str, or -1 if \a str could not be + found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::findRev( const char *str, int index, bool cs ) const +{ + /* + See QString::find() for explanations. + */ + const uint sl = qstrlen( str ); + const uint l = length(); + int delta = l-sl; + if ( index < 0 ) + index = delta; + if ( index < 0 || index > (int)l ) + return -1; + if ( index > delta ) + index = delta; + + if ( sl == 1 ) + return findRev( *str, index, cs ); + + const char* needle = str; + const char* haystack = data() + index; + const char* end = data(); + const uint sl_minus_1 = sl-1; + const char* n = needle+sl_minus_1; + const char* h = haystack+sl_minus_1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + *(n-i) ); + hashHaystack = ((hashHaystack<<1) + *(h-i) ); + } + hashHaystack -= *haystack; + while ( haystack >= end ) { + hashHaystack += *haystack; + if ( hashHaystack == hashNeedle && qstrncmp( needle, haystack, sl ) == 0 ) + return haystack-data(); + --haystack; + REHASH( *(haystack+sl) ); + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + tolower( *(n-i) ) ); + hashHaystack = ((hashHaystack<<1) + tolower( *(h-i) ) ); + } + hashHaystack -= tolower(*haystack); + while ( haystack >= end ) { + hashHaystack += tolower(*haystack); + if ( hashHaystack == hashNeedle && qstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-data(); + --haystack; + REHASH( tolower(*(haystack+sl)) ); + } + } + return -1; +} + + +/*! + Returns the number of times the character \a c occurs in the + string. + + The match is case sensitive if \a cs is TRUE, or case insensitive + if \a cs if FALSE. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::contains( char c, bool cs ) const +{ + int count = 0; + char *d = data(); + if ( !d ) + return 0; + if ( cs ) { // case sensitive + while ( *d ) + if ( *d++ == c ) + count++; + } else { // case insensitive + c = tolower( (uchar) c ); + while ( *d ) { + if ( tolower((uchar) *d) == c ) + count++; + d++; + } + } + return count; +} + +/*! + \overload + + Returns the number of times \a str occurs in the string. + + The match is case sensitive if \a cs is TRUE, or case insensitive + if \a cs if FALSE. + + This function counts overlapping substrings, for example, "banana" + contains two occurrences of "ana". + + \sa findRev() + \link #asciinotion Note on character comparisons \endlink +*/ + +int QCString::contains( const char *str, bool cs ) const +{ + int count = 0; + int i = -1; + // use find for the faster hashing algorithm + while ( ( i = find ( str, i+1, cs ) ) != -1 ) + count++; + return count; +} + +/*! + Returns a substring that contains the \a len leftmost characters + of the string. + + The whole string is returned if \a len exceeds the length of the + string. + + Example: + \code + QCString s = "Pineapple"; + QCString t = s.left( 4 ); // t == "Pine" + \endcode + + \sa right(), mid() +*/ + +QCString QCString::left( uint len ) const +{ + if ( isEmpty() ) { + QCString empty; + return empty; + } else if ( len >= size() ) { + QCString same( data() ); + return same; + } else { + QCString s( len+1 ); + strncpy( s.data(), data(), len ); + *(s.data()+len) = '\0'; + return s; + } +} + +/*! + Returns a substring that contains the \a len rightmost characters + of the string. + + The whole string is returned if \a len exceeds the length of the + string. + + Example: + \code + QCString s = "Pineapple"; + QCString t = s.right( 5 ); // t == "apple" + \endcode + + \sa left(), mid() +*/ + +QCString QCString::right( uint len ) const +{ + if ( isEmpty() ) { + QCString empty; + return empty; + } else { + uint l = length(); + if ( len > l ) + len = l; + char *p = data() + (l - len); + return QCString( p ); + } +} + +/*! + Returns a substring that contains at most \a len characters from + this string, starting at position \a index. + + Returns a null string if the string is empty or if \a index is out + of range. Returns the whole string from \a index if \a index+len + exceeds the length of the string. + + Example: + \code + QCString s = "Two pineapples"; + QCString t = s.mid( 4, 3 ); // t == "pin" + \endcode + + \sa left(), right() +*/ + +QCString QCString::mid( uint index, uint len ) const +{ + uint slen = qstrlen( data() ); + if ( isEmpty() || index >= slen ) { + QCString empty; + return empty; + } else { + if ( len > slen-index ) + len = slen - index; + register char *p = data()+index; + QCString s( len+1 ); + strncpy( s.data(), p, len ); + *(s.data()+len) = '\0'; + return s; + } +} + +/*! + Returns a string of length \a width (plus one for the terminating + '\0') that contains this string padded with the \a fill character. + + If the length of the string exceeds \a width and \a truncate is + FALSE (the default), then the returned string is a copy of the + string. If the length of the string exceeds \a width and \a + truncate is TRUE, then the returned string is a left(\a width). + + Example: + \code + QCString s("apple"); + QCString t = s.leftJustify(8, '.'); // t == "apple..." + \endcode + + \sa rightJustify() +*/ + +QCString QCString::leftJustify( uint width, char fill, bool truncate ) const +{ + QCString result; + int len = qstrlen(data()); + int padlen = width - len; + if ( padlen > 0 ) { + result.QByteArray::resize( len+padlen+1 ); + memcpy( result.data(), data(), len ); + memset( result.data()+len, fill, padlen ); + result[len+padlen] = '\0'; + } else { + if ( truncate ) + result = left( width ); + else + result = copy(); + } + return result; +} + +/*! + Returns a string of length \a width (plus one for the terminating + '\0') that contains zero or more of the \a fill character followed + by this string. + + If the length of the string exceeds \a width and \a truncate is + FALSE (the default), then the returned string is a copy of the + string. If the length of the string exceeds \a width and \a + truncate is TRUE, then the returned string is a left(\a width). + + Example: + \code + QCString s("pie"); + QCString t = s.rightJustify(8, '.'); // t == ".....pie" + \endcode + + \sa leftJustify() +*/ + +QCString QCString::rightJustify( uint width, char fill, bool truncate ) const +{ + QCString result; + int len = qstrlen(data()); + int padlen = width - len; + if ( padlen > 0 ) { + result.QByteArray::resize( len+padlen+1 ); + memset( result.data(), fill, padlen ); + memcpy( result.data()+padlen, data(), len ); + result[len+padlen] = '\0'; + } else { + if ( truncate ) + result = left( width ); + else + result = copy(); + } + return result; +} + +/*! + Returns a new string that is a copy of this string converted to lower + case. + + Example: + \code + QCString s("Credit"); + QCString t = s.lower(); // t == "credit" + \endcode + + \sa upper() + \link #asciinotion Note on character comparisons \endlink +*/ + +QCString QCString::lower() const +{ + QCString s( data() ); + register char *p = s.data(); + if ( p ) { + while ( *p ) { + *p = tolower( (uchar) *p ); + p++; + } + } + return s; +} + +/*! + Returns a new string that is a copy of this string converted to upper case. + + Example: + \code + QCString s( "Debit" ); + QCString t = s.upper(); // t == "DEBIT" + \endcode + + \sa lower() + \link #asciinotion Note on character comparisons \endlink +*/ + +QCString QCString::upper() const +{ + QCString s( data() ); + register char *p = s.data(); + if ( p ) { + while ( *p ) { + *p = toupper(*p); + p++; + } + } + return s; +} + + +/*! + Returns a new string that has white space removed from the start + and the end. + + White space means the decimal ASCII codes 9, 10, 11, 12, 13 and + 32. + + Example: + \code + QCString s = " space "; + QCString t = s.stripWhiteSpace(); // t == "space" + \endcode + + \sa simplifyWhiteSpace() +*/ + +QCString QCString::stripWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return copy(); + + register char *s = data(); + QCString result = s; + int reslen = result.length(); + if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) ) + return result; // returns a copy + + s = result.data(); + int start = 0; + int end = reslen - 1; + while ( isspace((uchar) s[start]) ) // skip white space from start + start++; + if ( s[start] == '\0' ) { // only white space + result.resize( 1 ); + return result; + } + while ( end && isspace((uchar) s[end]) ) // skip white space from end + end--; + end -= start - 1; + memmove( result.data(), &s[start], end ); + result.resize( end + 1 ); + return result; +} + + +/*! + Returns a new string that has white space removed from the start + and the end, plus any sequence of internal white space replaced + with a single space (ASCII 32). + + White space means the decimal ASCII codes 9, 10, 11, 12, 13 and + 32. + + \code + QCString s = " lots\t of\nwhite space "; + QCString t = s.simplifyWhiteSpace(); // t == "lots of white space" + \endcode + + \sa stripWhiteSpace() +*/ + +QCString QCString::simplifyWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return copy(); + QCString result( size() ); + char *from = data(); + char *to = result.data(); + char *first = to; + for ( ;; ) { + while ( isspace((uchar) *from) ) + from++; + while ( *from && !isspace((uchar) *from) ) + *to++ = *from++; + if ( *from ) + *to++ = 0x20; // ' ' + else + break; + } + if ( to > first && *(to-1) == 0x20 ) + to--; + *to = '\0'; + result.resize( (int)(to - result.data()) + 1 ); + return result; +} + + +/*! + \overload + + Inserts string \a s into the string at position \a index. + + If \a index is beyond the end of the string, the string is + padded with spaces (ASCII 32) to length \a index and then \a s + is appended. + + \code + QCString s = "I like fish"; + s.insert( 2, "don't "); // s == "I don't like fish" + + s = "x"; // index 01234 + s.insert( 3, "yz" ); // s == "x yz" + \endcode +*/ + +QCString &QCString::insert( uint index, const char *s ) +{ + int len = qstrlen(s); + if ( len == 0 ) + return *this; + uint olen = length(); + int nlen = olen + len; + if ( index >= olen ) { // insert after end of string + detach(); + if ( QByteArray::resize(nlen+index-olen+1) ) { + memset( data()+olen, ' ', index-olen ); + memcpy( data()+index, s, len+1 ); + } + } else if ( QByteArray::resize(nlen+1) ) { // normal insert + detach(); + memmove( data()+index+len, data()+index, olen-index+1 ); + memcpy( data()+index, s, len ); + } + return *this; +} + +/*! + Inserts character \a c into the string at position \a index and + returns a reference to the string. + + If \a index is beyond the end of the string, the string is + padded with spaces (ASCII 32) to length \a index and then \a c + is appended. + + Example: + \code + QCString s = "Yes"; + s.insert( 3, '!'); // s == "Yes!" + \endcode + + \sa remove(), replace() +*/ + +QCString &QCString::insert( uint index, char c ) // insert char +{ + char buf[2]; + buf[0] = c; + buf[1] = '\0'; + return insert( index, buf ); +} + +/*! + \fn QCString &QCString::prepend( const char *s ) + + Prepend \a s to the string. Equivalent to insert(0, s). + + \sa insert() +*/ + +/*! + Removes \a len characters from the string, starting at position \a + index, and returns a reference to the string. + + If \a index is out of range, nothing happens. If \a index is + valid, but \a index + \a len is larger than the length of the + string, the string is truncated at position \a index. + + \code + QCString s = "Montreal"; + s.remove( 1, 4 ); // s == "Meal" + \endcode + + \sa insert(), replace() +*/ + +QCString &QCString::remove( uint index, uint len ) +{ + uint olen = length(); + if ( index + len >= olen ) { // range problems + if ( index < olen ) { // index ok + detach(); + resize( index+1 ); + } + } else if ( len != 0 ) { + detach(); + memmove( data()+index, data()+index+len, olen-index-len+1 ); + QByteArray::resize(olen-len+1); + } + return *this; +} + +/*! + Replaces \a len characters from the string, starting at position + \a index, with \a str, and returns a reference to the string. + + If \a index is out of range, nothing is removed and \a str is + appended at the end of the string. If \a index is valid, but \a + index + \a len is larger than the length of the string, \a str + replaces the rest of the string from position \a index. + + \code + QCString s = "Say yes!"; + s.replace( 4, 3, "NO" ); // s == "Say NO!" + \endcode + + \sa insert(), remove() +*/ + +QCString &QCString::replace( uint index, uint len, const char *str ) +{ + remove( index, len ); + insert( index, str ); + return *this; +} + + +/*! \overload + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. + + Example: + \code + QCString s = "a,b,c"; + s.replace( ',', " or " ); + // s == "a or b or c" + \endcode +*/ +QCString &QCString::replace( char c, const char *after ) +{ + char str[2]; + str[0] = c; + str[1] = '\0'; + return replace( str, after ); +} + +/*! \overload + + Replaces every occurrence of the string \a before in the string + with the string \a after. Returns a reference to the string. + + Example: + \code + QCString s = "Greek is Greek"; + s.replace( "Greek", "English" ); + // s == "English is English" + \endcode +*/ +QCString &QCString::replace( const char *before, const char *after ) +{ + if ( before == after || isNull() ) + return *this; + + detach(); + + int index = 0; + const int bl = before ? strlen( before ) : 0; + const int al = after ? strlen( after ) : 0; + char *d = data(); + uint len = length(); + + if ( bl == al ) { + if ( bl ) { + while( (index = find( before, index ) ) != -1 ) { + memcpy( d+index, after, al ); + index += bl; + } + } + } else if ( al < bl ) { + uint to = 0; + uint movestart = 0; + uint num = 0; + while( (index = find( before, index ) ) != -1 ) { + if ( num ) { + int msize = index - movestart; + if ( msize > 0 ) { + memmove( d + to, d + movestart, msize ); + to += msize; + } + } else { + to = index; + } + if ( al ) { + memcpy( d + to, after, al ); + to += al; + } + index += bl; + movestart = index; + num++; + } + if ( num ) { + int msize = len - movestart; + if ( msize > 0 ) + memmove( d + to, d + movestart, msize ); + resize( len - num*(bl-al) + 1 ); + } + } else { + // the most complex case. We don't want to loose performance by doing repeated + // copies and reallocs of the string. + while( index != -1 ) { + uint indices[4096]; + uint pos = 0; + while( pos < 4095 ) { + index = find(before, index); + if ( index == -1 ) + break; + indices[pos++] = index; + index += bl; + // avoid infinite loop + if ( !bl ) + index++; + } + if ( !pos ) + break; + + // we have a table of replacement positions, use them for fast replacing + int adjust = pos*(al-bl); + // index has to be adjusted in case we get back into the loop above. + if ( index != -1 ) + index += adjust; + uint newlen = len + adjust; + int moveend = len; + if ( newlen > len ) { + resize( newlen + 1 ); + len = newlen; + } + d = data(); + + while( pos ) { + pos--; + int movestart = indices[pos] + bl; + int insertstart = indices[pos] + pos*(al-bl); + int moveto = insertstart + al; + memmove( d + moveto, d + movestart, (moveend - movestart) ); + if ( after ) + memcpy( d + insertstart, after, al ); + moveend = movestart - bl; + } + } + } + return *this; +} + +/*! \overload + + Replaces every occurrence of \a c1 with the char \a c2. + Returns a reference to the string. +*/ +QCString &QCString::replace( char c1, char c2 ) +{ + detach(); + uint i = 0; + char *d = data(); + uint len = length(); + while ( i < len ) { + if ( d[i] == c1 ) + d[i] = c2; + i++; + } + return *this; +} + + +#ifndef QT_NO_REGEXP_CAPTURE +/*! + \overload + + Finds the first occurrence of the regular expression \a rx, + starting at position \a index. + + Returns the position of the next match, or -1 if \a rx was not + found. + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a QString and + apply the function to that. +*/ + +int QCString::find( const QRegExp& rx, int index ) const +{ + QString d = QString::fromLatin1( data() ); + return d.find( rx, index ); +} + +/*! + \overload + + Finds the first occurrence of the regular expression \a rx, + starting at position \a index and searching backwards. + + Returns the position of the next match (backwards), or -1 if \a rx + was not found. + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a QString and + apply the function to that. +*/ + +int QCString::findRev( const QRegExp& rx, int index ) const +{ + QString d = QString::fromLatin1( data() ); + return d.findRev( rx, index ); +} + +/*! + \overload + + Counts the number of overlapping occurrences of \a rx in the string. + + Example: + \code + QString s = "banana and panama"; + QRegExp r = QRegExp( "a[nm]a", TRUE, FALSE ); + s.contains( r ); // 4 matches + \endcode + + \sa find(), findRev() + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a QString and + apply the function to that. +*/ + +int QCString::contains( const QRegExp &rx ) const +{ + QString d = QString::fromLatin1( data() ); + return d.contains( rx ); +} + + +/*! + \overload + + Replaces every occurrence of \a rx in the string with \a str. + Returns a reference to the string. + + Example: + \code + QString s = "banana"; + s.replace( QRegExp("a.*a"), "" ); // becomes "b" + + s = "banana"; + s.replace( QRegExp("^[bn]a"), "X" ); // becomes "Xnana" + + s = "banana"; + s.replace( QRegExp("^[bn]a"), "" ); // becomes "nana" + \endcode + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a QString and + apply the function to that. +*/ + +QCString &QCString::replace( const QRegExp &rx, const char *str ) +{ + QString d = QString::fromLatin1( data() ); + QString r = QString::fromLatin1( str ); + d.replace( rx, r ); + setStr( d.ascii() ); + return *this; +} +#endif //QT_NO_REGEXP + +/*! + Returns the string converted to a \c long value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +long QCString::toLong( bool *ok ) const +{ + char *p = data(); + long val=0; + const long max_mult = 214748364; + bool is_ok = FALSE; + int neg = 0; + if ( !p ) + goto bye; + while ( isspace((uchar) *p) ) // skip leading space + p++; + if ( *p == '-' ) { + p++; + neg = 1; + } else if ( *p == '+' ) { + p++; + } + if ( !isdigit((uchar) *p) ) + goto bye; + while ( isdigit((uchar) *p) ) { + if ( val > max_mult || (val == max_mult && (*p-'0') > 7+neg) ) + goto bye; + val = 10*val + (*p++ - '0'); + } + if ( neg ) + val = -val; + while ( isspace((uchar) *p) ) // skip trailing space + p++; + if ( *p == '\0' ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to an \c{unsigned long} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +ulong QCString::toULong( bool *ok ) const +{ + char *p = data(); + ulong val=0; + const ulong max_mult = 429496729; + bool is_ok = FALSE; + if ( !p ) + goto bye; + while ( isspace((uchar) *p) ) // skip leading space + p++; + if ( *p == '+' ) + p++; + if ( !isdigit((uchar) *p) ) + goto bye; + while ( isdigit((uchar) *p) ) { + if ( val > max_mult || (val == max_mult && (*p-'0') > 5) ) + goto bye; + val = 10*val + (*p++ - '0'); + } + while ( isspace((uchar) *p) ) // skip trailing space + p++; + if ( *p == '\0' ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to a \c{short} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, is out of range, or if it has trailing garbage; otherwise + \a *ok is set to TRUE. +*/ + +short QCString::toShort( bool *ok ) const +{ + long v = toLong( ok ); + if ( ok && *ok && (v < -32768 || v > 32767) ) + *ok = FALSE; + return (short)v; +} + +/*! + Returns the string converted to an \c{unsigned short} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, is out of range, or if it has trailing garbage; otherwise + \a *ok is set to TRUE. +*/ + +ushort QCString::toUShort( bool *ok ) const +{ + ulong v = toULong( ok ); + if ( ok && *ok && (v > 65535) ) + *ok = FALSE; + return (ushort)v; +} + + +/*! + Returns the string converted to a \c{int} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +int QCString::toInt( bool *ok ) const +{ + return (int)toLong( ok ); +} + +/*! + Returns the string converted to an \c{unsigned int} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +uint QCString::toUInt( bool *ok ) const +{ + return (uint)toULong( ok ); +} + +/*! + Returns the string converted to a \c{double} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +double QCString::toDouble( bool *ok ) const +{ + char *end; + double val = strtod( data() ? data() : "", &end ); + if ( ok ) + *ok = ( data() && *data() && ( end == 0 || *end == '\0' ) ); + return val; +} + +/*! + Returns the string converted to a \c{float} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +float QCString::toFloat( bool *ok ) const +{ + return (float)toDouble( ok ); +} + + +/*! + Makes a deep copy of \a str. Returns a reference to the string. +*/ + +QCString &QCString::setStr( const char *str ) +{ + detach(); + if ( str ) // valid string + store( str, qstrlen(str)+1 ); + else // empty + resize( 0 ); + return *this; +} + +/*! + \overload + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +QCString &QCString::setNum( long n ) +{ + detach(); + char buf[20]; + register char *p = &buf[19]; + bool neg; + if ( n < 0 ) { + neg = TRUE; + n = -n; + } else { + neg = FALSE; + } + *p = '\0'; + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + if ( neg ) + *--p = '-'; + store( p, qstrlen(p)+1 ); + return *this; +} + +/*! + \overload + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +QCString &QCString::setNum( ulong n ) +{ + detach(); + char buf[20]; + register char *p = &buf[19]; + *p = '\0'; + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + store( p, qstrlen(p)+1 ); + return *this; +} + +/*! + \overload QCString &QCString::setNum( int n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload QCString &QCString::setNum( uint n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload QCString &QCString::setNum( short n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload QCString &QCString::setNum( ushort n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + Sets the string to the string representation of the number \a n + and returns a reference to the string. + + The format of the string representation is specified by the format + character \a f, and the precision (number of digits after the + decimal point) is specified with \a prec. + + The valid formats for \a f are 'e', 'E', 'f', 'g' and 'G'. The + formats are the same as for sprintf(); they are explained in \l + QString::arg(). +*/ + +QCString &QCString::setNum( double n, char f, int prec ) +{ +#if defined(QT_CHECK_RANGE) + if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) + qWarning( "QCString::setNum: Invalid format char '%c'", f ); +#endif + char format[20]; + register char *fs = format; // generate format string + *fs++ = '%'; // "%.<prec>l<f>" + if ( prec > 99 ) + prec = 99; + *fs++ = '.'; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + *fs++ = 'l'; + *fs++ = f; + *fs = '\0'; + return sprintf( format, n ); +} + +/*! \overload QCString &QCString::setNum( float n, char f, int prec ) */ + + +/*! + Sets the character at position \a index to \a c and expands the + string if necessary, padding with spaces. + + Returns FALSE if \a index was out of range and the string could + not be expanded; otherwise returns TRUE. +*/ + +bool QCString::setExpand( uint index, char c ) +{ + detach(); + uint oldlen = length(); + if ( index >= oldlen ) { + if ( !QByteArray::resize( index+2 ) ) // no memory + return FALSE; + if ( index > oldlen ) + memset( data() + oldlen, ' ', index - oldlen ); + *(data() + index+1) = '\0'; // terminate padded string + } + *(data() + index) = c; + return TRUE; +} + + +/*! + \fn QCString::operator const char *() const + + Returns the string data. +*/ + + +/*! + \fn QCString& QCString::append( const char *str ) + + Appends string \a str to the string and returns a reference to the + string. Equivalent to operator+=(). +*/ + +/*! + Appends string \a str to the string and returns a reference to the string. +*/ + +QCString& QCString::operator+=( const char *str ) +{ + if ( !str ) + return *this; // nothing to append + detach(); + uint len1 = length(); + uint len2 = qstrlen(str); + if ( !QByteArray::resize( len1 + len2 + 1 ) ) + return *this; // no memory + memcpy( data() + len1, str, len2 + 1 ); + return *this; +} + +/*! + \overload + + Appends character \a c to the string and returns a reference to the string. +*/ + +QCString &QCString::operator+=( char c ) +{ + detach(); + uint len = length(); + if ( !QByteArray::resize( len + 2 ) ) + return *this; // no memory + *(data() + len) = c; + *(data() + len+1) = '\0'; + return *this; +} + + +/***************************************************************************** + QCString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \relates QCString + + Writes string \a str to the stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ +QDataStream &operator<<( QDataStream &s, const QCString &str ) +{ + return s.writeBytes( str.data(), str.size() ); +} + +/*! + \relates QCString + + Reads a string into \a str from the stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QCString &str ) +{ + str.detach(); + Q_UINT32 len; + s >> len; // read size of string + if ( len == 0 || s.eof() ) { // end of file reached + str.resize( 0 ); + return s; + } + if ( !str.QByteArray::resize( (uint)len )) {// resize string +#if defined(QT_CHECK_NULL) + qWarning( "QDataStream: Not enough memory to read QCString" ); +#endif + len = 0; + } + if ( len > 0 ) // not null array + s.readRawBytes( str.data(), (uint)len ); + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + Documentation for related functions + *****************************************************************************/ + +/*! + \fn bool operator==( const QCString &s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \overload bool operator==( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \overload bool operator==( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \fn bool operator!=( const QCString &s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \overload bool operator!=( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \overload bool operator!=( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \fn bool operator<( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \< 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator<( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \< 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator<=( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 is less than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \<= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator<=( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 is less than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \<= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator>( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \> 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator>( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \> 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator>=( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \>= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator>=( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \>= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn const QCString operator+( const QCString &s1, const QCString &s2 ) + + \relates QCString + + Returns a string which consists of the concatenation of \a s1 and + \a s2. +*/ + +/*! + \overload const QCString operator+( const QCString &s1, const char *s2 ) + + \relates QCString + + Returns a string which consists of the concatenation of \a s1 and \a s2. +*/ + +/*! + \overload const QCString operator+( const char *s1, const QCString &s2 ) + + \relates QCString + + Returns a string which consists of the concatenation of \a s1 and \a s2. +*/ + +/*! + \overload const QCString operator+( const QCString &s, char c ) + + \relates QCString + + Returns a string which consists of the concatenation of \a s and \a c. +*/ + +/*! + \overload const QCString operator+( char c, const QCString &s ) + + \relates QCString + + Returns a string which consists of the concatenation of \a c and \a s. +*/ diff --git a/qmake/tools/qdatastream.cpp b/qmake/tools/qdatastream.cpp new file mode 100644 index 0000000..9c573c7 --- a/dev/null +++ b/qmake/tools/qdatastream.cpp @@ -0,0 +1,1024 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QDataStream class +** +** Created : 930831 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qdatastream.h" + +#ifndef QT_NO_DATASTREAM +#include "qbuffer.h" +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +/*! + \class QDataStream qdatastream.h + \reentrant + \brief The QDataStream class provides serialization of binary data + to a QIODevice. + + \ingroup io + + A data stream is a binary stream of encoded information which is + 100% independent of the host computer's operating system, CPU or + byte order. For example, a data stream that is written by a PC + under Windows can be read by a Sun SPARC running Solaris. + + You can also use a data stream to read/write \link #raw raw + unencoded binary data\endlink. If you want a "parsing" input + stream, see QTextStream. + + The QDataStream class implements serialization of primitive types, + like \c char, \c short, \c int, \c char* etc. Serialization of + more complex data is accomplished by breaking up the data into + primitive units. + + A data stream cooperates closely with a QIODevice. A QIODevice + represents an input/output medium one can read data from and write + data to. The QFile class is an example of an IO device. + + Example (write binary data to a stream): + \code + QFile file( "file.dat" ); + file.open( IO_WriteOnly ); + QDataStream stream( &file ); // we will serialize the data into the file + stream << "the answer is"; // serialize a string + stream << (Q_INT32)42; // serialize an integer + \endcode + + Example (read binary data from a stream): + \code + QFile file( "file.dat" ); + file.open( IO_ReadOnly ); + QDataStream stream( &file ); // read the data serialized from the file + QString str; + Q_INT32 a; + stream >> str >> a; // extract "the answer is" and 42 + \endcode + + Each item written to the stream is written in a predefined binary + format that varies depending on the item's type. Supported Qt + types include QBrush, QColor, QDateTime, QFont, QPixmap, QString, + QVariant and many others. For the complete list of all Qt types + supporting data streaming see the \link datastreamformat.html + Format of the QDataStream operators \endlink. + + To take one example, a \c char* string is written as a 32-bit + integer equal to the length of the string including the NUL byte + ('\0'), followed by all the characters of the string including the + NUL byte. When reading a \c char* string, 4 bytes are read to + create the 32-bit length value, then that many characters for the + \c char* string including the NUL are read. + + The initial IODevice is usually set in the constructor, but can be + changed with setDevice(). If you've reached the end of the data + (or if there is no IODevice set) atEnd() will return TRUE. + + If you want the data to be compatible with an earlier version of + Qt use setVersion(). + + If you want the data to be human-readable, e.g. for debugging, you + can set the data stream into printable data mode with + setPrintableData(). The data is then written slower, in a bloated + but human readable format. + + If you are producing a new binary data format, such as a file + format for documents created by your application, you could use a + QDataStream to write the data in a portable format. Typically, you + would write a brief header containing a magic string and a version + number to give yourself room for future expansion. For example: + + \code + QFile file( "file.xxx" ); + file.open( IO_WriteOnly ); + QDataStream stream( &file ); + + // Write a header with a "magic number" and a version + stream << (Q_UINT32)0xA0B0C0D0; + stream << (Q_INT32)123; + + // Write the data + stream << [lots of interesting data] + \endcode + + Then read it in with: + + \code + QFile file( "file.xxx" ); + file.open( IO_ReadOnly ); + QDataStream stream( &file ); + + // Read and check the header + Q_UINT32 magic; + stream >> magic; + if ( magic != 0xA0B0C0D0 ) + return XXX_BAD_FILE_FORMAT; + + // Read the version + Q_INT32 version; + stream >> version; + if ( version < 100 ) + return XXX_BAD_FILE_TOO_OLD; + if ( version > 123 ) + return XXX_BAD_FILE_TOO_NEW; + if ( version <= 110 ) + stream.setVersion(1); + + // Read the data + stream >> [lots of interesting data]; + if ( version > 120 ) + stream >> [data new in XXX version 1.2]; + stream >> [other interesting data]; + \endcode + + You can select which byte order to use when serializing data. The + default setting is big endian (MSB first). Changing it to little + endian breaks the portability (unless the reader also changes to + little endian). We recommend keeping this setting unless you have + special requirements. + + \target raw + \section1 Reading and writing raw binary data + + You may wish to read/write your own raw binary data to/from the + data stream directly. Data may be read from the stream into a + preallocated char* using readRawBytes(). Similarly data can be + written to the stream using writeRawBytes(). Notice that any + encoding/decoding of the data must be done by you. + + A similar pair of functions is readBytes() and writeBytes(). These + differ from their \e raw counterparts as follows: readBytes() + reads a Q_UINT32 which is taken to be the length of the data to be + read, then that number of bytes is read into the preallocated + char*; writeBytes() writes a Q_UINT32 containing the length of the + data, followed by the data. Notice that any encoding/decoding of + the data (apart from the length Q_UINT32) must be done by you. + + \sa QTextStream QVariant +*/ + +/*! + \enum QDataStream::ByteOrder + + The byte order used for reading/writing the data. + + \value BigEndian the default + \value LittleEndian +*/ + + +/***************************************************************************** + QDataStream member functions + *****************************************************************************/ + +#if defined(QT_CHECK_STATE) +#undef CHECK_STREAM_PRECOND +#define CHECK_STREAM_PRECOND if ( !dev ) { \ + qWarning( "QDataStream: No device" ); \ + return *this; } +#else +#define CHECK_STREAM_PRECOND +#endif + +static int systemWordSize = 0; +static bool systemBigEndian; + +static const int DefaultStreamVersion = 5; +// 5 is default in Qt 3.1 +// 4 is default in Qt 3.0 +// 3 is default in Qt 2.1 +// 2 is the Qt 2.0.x format +// 1 is the Qt 1.x format + +/*! + Constructs a data stream that has no IO device. + + \sa setDevice() +*/ + +QDataStream::QDataStream() +{ + if ( systemWordSize == 0 ) // get system features + qSysInfo( &systemWordSize, &systemBigEndian ); + dev = 0; // no device set + owndev = FALSE; + byteorder = BigEndian; // default byte order + printable = FALSE; + ver = DefaultStreamVersion; + noswap = systemBigEndian; +} + +/*! + Constructs a data stream that uses the IO device \a d. + + \warning If you use QSocket or QSocketDevice as the IO device \a d + for reading data, you must make sure that enough data is available + on the socket for the operation to successfully proceed; + QDataStream does not have any means to handle or recover from + short-reads. + + \sa setDevice(), device() +*/ + +QDataStream::QDataStream( QIODevice *d ) +{ + if ( systemWordSize == 0 ) // get system features + qSysInfo( &systemWordSize, &systemBigEndian ); + dev = d; // set device + owndev = FALSE; + byteorder = BigEndian; // default byte order + printable = FALSE; + ver = DefaultStreamVersion; + noswap = systemBigEndian; +} + +/*! + Constructs a data stream that operates on a byte array, \a a, + through an internal QBuffer device. The \a mode is a + QIODevice::mode(), usually either \c IO_ReadOnly or \c + IO_WriteOnly. + + Example: + \code + static char bindata[] = { 231, 1, 44, ... }; + QByteArray a; + a.setRawData( bindata, sizeof(bindata) ); // a points to bindata + QDataStream stream( a, IO_ReadOnly ); // open on a's data + stream >> [something]; // read raw bindata + a.resetRawData( bindata, sizeof(bindata) ); // finished + \endcode + + The QByteArray::setRawData() function is not for the inexperienced. +*/ + +QDataStream::QDataStream( QByteArray a, int mode ) +{ + if ( systemWordSize == 0 ) // get system features + qSysInfo( &systemWordSize, &systemBigEndian ); + dev = new QBuffer( a ); // create device + ((QBuffer *)dev)->open( mode ); // open device + owndev = TRUE; + byteorder = BigEndian; // default byte order + printable = FALSE; + ver = DefaultStreamVersion; + noswap = systemBigEndian; +} + +/*! + Destroys the data stream. + + The destructor will not affect the current IO device, unless it is + an internal IO device processing a QByteArray passed in the \e + constructor, in which case the internal IO device is destroyed. +*/ + +QDataStream::~QDataStream() +{ + if ( owndev ) + delete dev; +} + + +/*! + \fn QIODevice *QDataStream::device() const + + Returns the IO device currently set. + + \sa setDevice(), unsetDevice() +*/ + +/*! + void QDataStream::setDevice(QIODevice *d ) + + Sets the IO device to \a d. + + \sa device(), unsetDevice() +*/ + +void QDataStream::setDevice(QIODevice *d ) +{ + if ( owndev ) { + delete dev; + owndev = FALSE; + } + dev = d; +} + +/*! + Unsets the IO device. This is the same as calling setDevice( 0 ). + + \sa device(), setDevice() +*/ + +void QDataStream::unsetDevice() +{ + setDevice( 0 ); +} + + +/*! + \fn bool QDataStream::atEnd() const + + Returns TRUE if the IO device has reached the end position (end of + the stream or file) or if there is no IO device set; otherwise + returns FALSE, i.e. if the current position of the IO device is + before the end position. + + \sa QIODevice::atEnd() +*/ + +/*!\fn bool QDataStream::eof() const + + \obsolete + + Returns TRUE if the IO device has reached the end position (end of + stream or file) or if there is no IO device set. + + Returns FALSE if the current position of the read/write head of the IO + device is somewhere before the end position. + + \sa QIODevice::atEnd() +*/ + +/*! + \fn int QDataStream::byteOrder() const + + Returns the current byte order setting -- either \c BigEndian or + \c LittleEndian. + + \sa setByteOrder() +*/ + +/*! + Sets the serialization byte order to \a bo. + + The \a bo parameter can be \c QDataStream::BigEndian or \c + QDataStream::LittleEndian. + + The default setting is big endian. We recommend leaving this + setting unless you have special requirements. + + \sa byteOrder() +*/ + +void QDataStream::setByteOrder( int bo ) +{ + byteorder = bo; + if ( systemBigEndian ) + noswap = byteorder == BigEndian; + else + noswap = byteorder == LittleEndian; +} + + +/*! + \fn bool QDataStream::isPrintableData() const + + Returns TRUE if the printable data flag has been set; otherwise + returns FALSE. + + \sa setPrintableData() +*/ + +/*! + \fn void QDataStream::setPrintableData( bool enable ) + + If \a enable is TRUE, data will be output in a human readable + format. If \a enable is FALSE, data will be output in a binary + format. + + If \a enable is TRUE, the write functions will generate output + that consists of printable characters (7 bit ASCII). This output + will typically be a lot larger than the default binary output, and + consequently slower to write. + + We recommend only enabling printable data for debugging purposes. +*/ + + +/*! + \fn int QDataStream::version() const + + Returns the version number of the data serialization format. In Qt + 3.1, this number is 5. + + \sa setVersion() +*/ + +/*! + \fn void QDataStream::setVersion( int v ) + + Sets the version number of the data serialization format to \a v. + + You don't need to set a version if you are using the current + version of Qt. + + In order to accommodate new functionality, the datastream + serialization format of some Qt classes has changed in some + versions of Qt. If you want to read data that was created by an + earlier version of Qt, or write data that can be read by a program + that was compiled with an earlier version of Qt, use this function + to modify the serialization format of QDataStream. + + \table + \header \i Qt Version \i QDataStream Version + \row \i Qt 3.1 \i11 5 + \row \i Qt 3.0 \i11 4 + \row \i Qt 2.1.x and Qt 2.2.x \i11 3 + \row \i Qt 2.0.x \i11 2 + \row \i Qt 1.x \i11 1 + \endtable + + \sa version() +*/ + +/***************************************************************************** + QDataStream read functions + *****************************************************************************/ + + +static Q_INT32 read_int_ascii( QDataStream *s ) +{ + register int n = 0; + char buf[40]; + for ( ;; ) { + buf[n] = s->device()->getch(); + if ( buf[n] == '\n' || n > 38 ) // $-terminator + break; + n++; + } + buf[n] = '\0'; + return atol( buf ); +} + + +/*! + \overload QDataStream &QDataStream::operator>>( Q_UINT8 &i ) + + Reads an unsigned byte from the stream into \a i, and returns a + reference to the stream. +*/ + +/*! + Reads a signed byte from the stream into \a i, and returns a + reference to the stream. +*/ + +QDataStream &QDataStream::operator>>( Q_INT8 &i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + i = (Q_INT8)dev->getch(); + if ( i == '\\' ) { // read octal code + char buf[4]; + dev->readBlock( buf, 3 ); + i = (buf[2] & 0x07)+((buf[1] & 0x07) << 3)+((buf[0] & 0x07) << 6); + } + } else { // data or text + i = (Q_INT8)dev->getch(); + } + return *this; +} + + +/*! + \overload QDataStream &QDataStream::operator>>( Q_UINT16 &i ) + + Reads an unsigned 16-bit integer from the stream into \a i, and + returns a reference to the stream. +*/ + +/*! + \overload + + Reads a signed 16-bit integer from the stream into \a i, and + returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator>>( Q_INT16 &i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + i = (Q_INT16)read_int_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&i, sizeof(Q_INT16) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[2]; + dev->readBlock( b, 2 ); + *p++ = b[1]; + *p = b[0]; + } + return *this; +} + + +/*! + \overload QDataStream &QDataStream::operator>>( Q_UINT32 &i ) + + Reads an unsigned 32-bit integer from the stream into \a i, and + returns a reference to the stream. +*/ + +/*! + \overload + + Reads a signed 32-bit integer from the stream into \a i, and + returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator>>( Q_INT32 &i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + i = read_int_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&i, sizeof(Q_INT32) ); + } else { // swap bytes + uchar *p = (uchar *)(&i); + char b[4]; + dev->readBlock( b, 4 ); + *p++ = b[3]; + *p++ = b[2]; + *p++ = b[1]; + *p = b[0]; + } + return *this; +} + +/*! + \overload QDataStream &QDataStream::operator>>( Q_ULONG &i ) + + Reads an unsigned integer of the system's word length from the + stream, into \a i, and returns a reference to the stream. +*/ + +/*! + \overload + + Reads a signed integer of the system's word length from the stream + into \a i, and returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator>>( Q_LONG &i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + i = read_int_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&i, sizeof(Q_LONG) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[sizeof(Q_LONG)]; + dev->readBlock( b, sizeof(Q_LONG) ); + for ( int j = sizeof(Q_LONG); j; ) + *p++ = b[--j]; + } + return *this; +} + +static double read_double_ascii( QDataStream *s ) +{ + register int n = 0; + char buf[80]; + for ( ;; ) { + buf[n] = s->device()->getch(); + if ( buf[n] == '\n' || n > 78 ) // $-terminator + break; + n++; + } + buf[n] = '\0'; + return atof( buf ); +} + + +/*! + \overload + + Reads a 32-bit floating point number from the stream into \a f, + using the standard IEEE754 format. Returns a reference to the + stream. +*/ + +QDataStream &QDataStream::operator>>( float &f ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + f = (float)read_double_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&f, sizeof(float) ); + } else { // swap bytes + uchar *p = (uchar *)(&f); + char b[4]; + dev->readBlock( b, 4 ); + *p++ = b[3]; + *p++ = b[2]; + *p++ = b[1]; + *p = b[0]; + } + return *this; +} + + +/*! + \overload + + Reads a 64-bit floating point number from the stream into \a f, + using the standard IEEE754 format. Returns a reference to the + stream. +*/ + +QDataStream &QDataStream::operator>>( double &f ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + f = read_double_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&f, sizeof(double) ); + } else { // swap bytes + register uchar *p = (uchar *)(&f); + char b[8]; + dev->readBlock( b, 8 ); + *p++ = b[7]; + *p++ = b[6]; + *p++ = b[5]; + *p++ = b[4]; + *p++ = b[3]; + *p++ = b[2]; + *p++ = b[1]; + *p = b[0]; + } + return *this; +} + + +/*! + \overload + + Reads the '\0'-terminated string \a s from the stream and returns + a reference to the stream. + + Space for the string is allocated using \c new -- the caller must + destroy it with delete[]. +*/ + +QDataStream &QDataStream::operator>>( char *&s ) +{ + uint len = 0; + return readBytes( s, len ); +} + + +/*! + Reads the buffer \a s from the stream and returns a reference to + the stream. + + The buffer \a s is allocated using \c new. Destroy it with the \c + delete[] operator. If the length is zero or \a s cannot be + allocated, \a s is set to 0. + + The \a l parameter will be set to the length of the buffer. + + The serialization format is a Q_UINT32 length specifier first, + then \a l bytes of data. Note that the data is \e not encoded. + + \sa readRawBytes(), writeBytes() +*/ + +QDataStream &QDataStream::readBytes( char *&s, uint &l ) +{ + CHECK_STREAM_PRECOND + Q_UINT32 len; + *this >> len; // first read length spec + l = (uint)len; + if ( len == 0 || eof() ) { + s = 0; + return *this; + } else { + s = new char[len]; // create char array + Q_CHECK_PTR( s ); + if ( !s ) // no memory + return *this; + return readRawBytes( s, (uint)len ); + } +} + + +/*! + Reads \a len bytes from the stream into \a s and returns a + reference to the stream. + + The buffer \a s must be preallocated. The data is \e not encoded. + + \sa readBytes(), QIODevice::readBlock(), writeRawBytes() +*/ + +QDataStream &QDataStream::readRawBytes( char *s, uint len ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + register Q_INT8 *p = (Q_INT8*)s; + while ( len-- ) + *this >> *p++; + } else { // read data char array + dev->readBlock( s, len ); + } + return *this; +} + + +/***************************************************************************** + QDataStream write functions + *****************************************************************************/ + + +/*! + \overload QDataStream &QDataStream::operator<<( Q_UINT8 i ) + + Writes an unsigned byte, \a i, to the stream and returns a + reference to the stream. +*/ + +/*! + Writes a signed byte, \a i, to the stream and returns a reference + to the stream. +*/ + +QDataStream &QDataStream::operator<<( Q_INT8 i ) +{ + CHECK_STREAM_PRECOND + if ( printable && (i == '\\' || !isprint((uchar) i)) ) { + char buf[6]; // write octal code + buf[0] = '\\'; + buf[1] = '0' + ((i >> 6) & 0x07); + buf[2] = '0' + ((i >> 3) & 0x07); + buf[3] = '0' + (i & 0x07); + buf[4] = '\0'; + dev->writeBlock( buf, 4 ); + } else { + dev->putch( i ); + } + return *this; +} + + +/*! + \overload QDataStream &QDataStream::operator<<( Q_UINT16 i ) + + Writes an unsigned 16-bit integer, \a i, to the stream and returns + a reference to the stream. +*/ + +/*! + \overload + + Writes a signed 16-bit integer, \a i, to the stream and returns a + reference to the stream. +*/ + +QDataStream &QDataStream::operator<<( Q_INT16 i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + char buf[16]; + sprintf( buf, "%d\n", i ); + dev->writeBlock( buf, strlen(buf) ); + } else if ( noswap ) { // no conversion needed + dev->writeBlock( (char *)&i, sizeof(Q_INT16) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[2]; + b[1] = *p++; + b[0] = *p; + dev->writeBlock( b, 2 ); + } + return *this; +} + +/*! + \overload + + Writes a signed 32-bit integer, \a i, to the stream and returns a + reference to the stream. +*/ + +QDataStream &QDataStream::operator<<( Q_INT32 i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + char buf[16]; + sprintf( buf, "%d\n", i ); + dev->writeBlock( buf, strlen(buf) ); + } else if ( noswap ) { // no conversion needed + dev->writeBlock( (char *)&i, sizeof(Q_INT32) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[4]; + b[3] = *p++; + b[2] = *p++; + b[1] = *p++; + b[0] = *p; + dev->writeBlock( b, 4 ); + } + return *this; +} + +/*! + \overload QDataStream &QDataStream::operator<<( Q_ULONG i ) + + Writes an unsigned integer \a i, of the system's word length, to + the stream and returns a reference to the stream. +*/ + +/*! + \overload + + Writes a signed integer \a i, of the system's word length, to the + stream and returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator<<( Q_LONG i ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + char buf[20]; + sprintf( buf, "%ld\n", i ); + dev->writeBlock( buf, strlen(buf) ); + } else if ( noswap ) { // no conversion needed + dev->writeBlock( (char *)&i, sizeof(Q_LONG) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[sizeof(Q_LONG)]; + for ( int j = sizeof(Q_LONG); j; ) + b[--j] = *p++; + dev->writeBlock( b, sizeof(Q_LONG) ); + } + return *this; +} + +/*! + \overload QDataStream &QDataStream::operator<<( Q_UINT32 i ) + + Writes an unsigned integer, \a i, to the stream as a 32-bit + unsigned integer (Q_UINT32). Returns a reference to the stream. +*/ + +/*! + \overload + + Writes a 32-bit floating point number, \a f, to the stream using + the standard IEEE754 format. Returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator<<( float f ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + char buf[32]; + sprintf( buf, "%g\n", (double)f ); + dev->writeBlock( buf, strlen(buf) ); + } else { + float g = f; // fixes float-on-stack problem + if ( noswap ) { // no conversion needed + dev->writeBlock( (char *)&g, sizeof(float) ); + } else { // swap bytes + register uchar *p = (uchar *)(&g); + char b[4]; + b[3] = *p++; + b[2] = *p++; + b[1] = *p++; + b[0] = *p; + dev->writeBlock( b, 4 ); + } + } + return *this; +} + + +/*! + \overload + + Writes a 64-bit floating point number, \a f, to the stream using + the standard IEEE754 format. Returns a reference to the stream. +*/ + +QDataStream &QDataStream::operator<<( double f ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // printable data + char buf[32]; + sprintf( buf, "%g\n", f ); + dev->writeBlock( buf, strlen(buf) ); + } else if ( noswap ) { // no conversion needed + dev->writeBlock( (char *)&f, sizeof(double) ); + } else { // swap bytes + register uchar *p = (uchar *)(&f); + char b[8]; + b[7] = *p++; + b[6] = *p++; + b[5] = *p++; + b[4] = *p++; + b[3] = *p++; + b[2] = *p++; + b[1] = *p++; + b[0] = *p; + dev->writeBlock( b, 8 ); + } + return *this; +} + + +/*! + \overload + + Writes the '\0'-terminated string \a s to the stream and returns a + reference to the stream. + + The string is serialized using writeBytes(). +*/ + +QDataStream &QDataStream::operator<<( const char *s ) +{ + if ( !s ) { + *this << (Q_UINT32)0; + return *this; + } + uint len = qstrlen( s ) + 1; // also write null terminator + *this << (Q_UINT32)len; // write length specifier + return writeRawBytes( s, len ); +} + + +/*! + Writes the length specifier \a len and the buffer \a s to the + stream and returns a reference to the stream. + + The \a len is serialized as a Q_UINT32, followed by \a len bytes + from \a s. Note that the data is \e not encoded. + + \sa writeRawBytes(), readBytes() +*/ + +QDataStream &QDataStream::writeBytes(const char *s, uint len) +{ + CHECK_STREAM_PRECOND + *this << (Q_UINT32)len; // write length specifier + if ( len ) + writeRawBytes( s, len ); + return *this; +} + + +/*! + Writes \a len bytes from \a s to the stream and returns a + reference to the stream. The data is \e not encoded. + + \sa writeBytes(), QIODevice::writeBlock(), readRawBytes() +*/ + +QDataStream &QDataStream::writeRawBytes( const char *s, uint len ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // write printable + register Q_INT8 *p = (Q_INT8*)s; + while ( len-- ) + *this << *p++; + } else { // write data char array + dev->writeBlock( s, len ); + } + return *this; +} + +#endif // QT_NO_DATASTREAM diff --git a/qmake/tools/qdatetime.cpp b/qmake/tools/qdatetime.cpp new file mode 100644 index 0000000..93e40a8 --- a/dev/null +++ b/qmake/tools/qdatetime.cpp @@ -0,0 +1,2490 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of date and time classes +** +** Created : 940124 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +// Get the system specific includes and defines +#include "qplatformdefs.h" + +#include "qdatetime.h" +#include "qdatastream.h" +#include "qregexp.h" + +#include <stdio.h> +#ifndef Q_OS_TEMP +#include <time.h> +#endif + +#if defined(Q_OS_WIN32) +#include <windows.h> +#endif + +static const uint FIRST_DAY = 2361222; // Julian day for 1752-09-14 +static const int FIRST_YEAR = 1752; // ### wrong for many countries +static const uint SECS_PER_DAY = 86400; +static const uint MSECS_PER_DAY = 86400000; +static const uint SECS_PER_HOUR = 3600; +static const uint MSECS_PER_HOUR= 3600000; +static const uint SECS_PER_MIN = 60; +static const uint MSECS_PER_MIN = 60000; + +static const short monthDays[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static const char * const qt_shortMonthNames[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +#ifndef QT_NO_DATESTRING +/***************************************************************************** + Some static function used by QDate, QTime and QDateTime + *****************************************************************************/ + +// Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens +static QString getFmtString( const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = FALSE ) +{ + if ( f.isEmpty() ) + return QString::null; + + QString buf = f; + + if ( dt ) { + if ( f == "h" ) { + if ( ( am_pm ) && ( dt->hour() > 12 ) ) + buf = QString::number( dt->hour() - 12 ); + else if ( ( am_pm ) && ( dt->hour() == 0 ) ) + buf = "12"; + else + buf = QString::number( dt->hour() ); + } else if ( f == "hh" ) { + if ( ( am_pm ) && ( dt->hour() > 12 ) ) + buf = QString::number( dt->hour() - 12 ).rightJustify( 2, '0', TRUE ); + else if ( ( am_pm ) && ( dt->hour() == 0 ) ) + buf = "12"; + else + buf = QString::number( dt->hour() ).rightJustify( 2, '0', TRUE ); + } else if ( f == "m" ) { + buf = QString::number( dt->minute() ); + } else if ( f == "mm" ) { + buf = QString::number( dt->minute() ).rightJustify( 2, '0', TRUE ); + } else if ( f == "s" ) { + buf = QString::number( dt->second() ); + } else if ( f == "ss" ) { + buf = QString::number( dt->second() ).rightJustify( 2, '0', TRUE ); + } else if ( f == "z" ) { + buf = QString::number( dt->msec() ); + } else if ( f == "zzz" ) { + buf = QString::number( dt->msec() ).rightJustify( 3, '0', TRUE ); + } else if ( f == "ap" ) { + buf = dt->hour() < 12 ? "am" : "pm"; + } else if ( f == "AP" ) { + buf = dt->hour() < 12 ? "AM" : "PM"; + } + } + + if ( dd ) { + if ( f == "d" ) { + buf = QString::number( dd->day() ); + } else if ( f == "dd" ) { + buf = QString::number( dd->day() ).rightJustify( 2, '0', TRUE ); + } else if ( f == "M" ) { + buf = QString::number( dd->month() ); + } else if ( f == "MM" ) { + buf = QString::number( dd->month() ).rightJustify( 2, '0', TRUE ); +#ifndef QT_NO_TEXTDATE + } else if ( f == "ddd" ) { + buf = dd->shortDayName( dd->dayOfWeek() ); + } else if ( f == "dddd" ) { + buf = dd->longDayName( dd->dayOfWeek() ); + } else if ( f == "MMM" ) { + buf = dd->shortMonthName( dd->month() ); + } else if ( f == "MMMM" ) { + buf = dd->longMonthName( dd->month() ); +#endif + } else if ( f == "yy" ) { + buf = QString::number( dd->year() ).right( 2 ); + } else if ( f == "yyyy" ) { + buf = QString::number( dd->year() ); + } + } + + return buf; +} + +// Parses the format string and uses getFmtString to get the values for the tokens. Ret +static QString fmtDateTime( const QString& f, const QTime* dt = 0, const QDate* dd = 0 ) +{ + if ( f.isEmpty() ) { + return QString::null; + } + + bool ap = ( f.contains( "AP" ) || f.contains( "ap" ) ); + + QString buf; + QString frm; + QChar status = '0'; + + for ( int i = 0; i < (int)f.length(); ++i ) { + + if ( f[ i ] == status ) { + if ( ( ap ) && ( ( f[ i ] == 'P' ) || ( f[ i ] == 'p' ) ) ) + status = '0'; + frm += f[ i ]; + } else { + buf += getFmtString( frm, dt, dd, ap ); + frm = QString::null; + if ( ( f[ i ] == 'h' ) || ( f[ i ] == 'm' ) || ( f[ i ] == 's' ) || ( f[ i ] == 'z' ) ) { + status = f[ i ]; + frm += f[ i ]; + } else if ( ( f[ i ] == 'd' ) || ( f[ i ] == 'M' ) || ( f[ i ] == 'y' ) ) { + status = f[ i ]; + frm += f[ i ]; + } else if ( ( ap ) && ( f[ i ] == 'A' ) ) { + status = 'P'; + frm += f[ i ]; + } else if( ( ap ) && ( f[ i ] == 'a' ) ) { + status = 'p'; + frm += f[ i ]; + } else { + buf += f[ i ]; + status = '0'; + } + } + } + + buf += getFmtString( frm, dt, dd, ap ); + + return buf; +} +#endif // QT_NO_DATESTRING + +/***************************************************************************** + QDate member functions + *****************************************************************************/ + +/*! + \class QDate qdatetime.h + \reentrant + \brief The QDate class provides date functions. + + \ingroup time + \mainclass + + A QDate object contains a calendar date, i.e. year, month, and day + numbers, in the modern Western (Gregorian) calendar. It can read + the current date from the system clock. It provides functions for + comparing dates and for manipulating dates, e.g. by adding a + number of days or months or years. + + A QDate object is typically created either by giving the year, + month and day numbers explicitly, or by using the static function + currentDate(), which creates a QDate object containing the system + clock's date. An explicit date can also be set using setYMD(). The + fromString() function returns a QDate given a string and a date + format which is used to interpret the date within the string. + + The year(), month(), and day() functions provide access to the + year, month, and day numbers. Also, dayOfWeek() and dayOfYear() + functions are provided. The same information is provided in + textual format by the toString(), shortDayName(), longDayName(), + shortMonthName() and longMonthName() functions. + + QDate provides a full set of operators to compare two QDate + objects where smaller means earlier and larger means later. + + You can increment (or decrement) a date by a given number of days + using addDays(). Similarly you can use addMonths() and addYears(). + The daysTo() function returns the number of days between two + dates. + + The daysInMonth() and daysInYear() functions return how many days + there are in this date's month and year, respectively. The + leapYear() function indicates whether this date is in a leap year. + + Note that QDate should not be used for date calculations for dates + prior to the introduction of the Gregorian calendar. This calendar + was adopted by England from the 14<sup><small>th</small></sup> + September 1752 (hence this is the earliest valid QDate), and + subsequently by most other Western countries, until 1923. + + The end of time is reached around the year 8000, by which time we + expect Qt to be obsolete. + + \sa QTime QDateTime QDateEdit QDateTimeEdit +*/ + +/*! + \enum Qt::DateFormat + + \value TextDate (default) Qt format + \value ISODate ISO 8601 extended format (YYYY-MM-DD, or with time, + YYYY-MM-DDTHH:MM:SS) + \value LocalDate locale dependent format +*/ + + +/*! + \enum Qt::TimeSpec + + \value LocalTime Locale dependent time (Timezones and Daylight Savings Time) + \value UTC Coordinated Universal Time, replaces Greenwich Time +*/ + +/*! + \fn QDate::QDate() + + Constructs a null date. Null dates are invalid. + + \sa isNull(), isValid() +*/ + + +/*! + Constructs a date with year \a y, month \a m and day \a d. + + \a y must be in the range 1752..8000, \a m must be in the range + 1..12, and \a d must be in the range 1..31. + + \warning If \a y is in the range 0..99, it is interpreted as + 1900..1999. + + \sa isValid() +*/ + +QDate::QDate( int y, int m, int d ) +{ + jd = 0; + setYMD( y, m, d ); +} + + +/*! + \fn bool QDate::isNull() const + + Returns TRUE if the date is null; otherwise returns FALSE. A null + date is invalid. + + \sa isValid() +*/ + + +/*! + Returns TRUE if this date is valid; otherwise returns FALSE. + + \sa isNull() +*/ + +bool QDate::isValid() const +{ + return jd >= FIRST_DAY; +} + + +/*! + Returns the year (1752..8000) of this date. + + \sa month(), day() +*/ + +int QDate::year() const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + return y; +} + +/*! + Returns the month (January=1..December=12) of this date. + + \sa year(), day() +*/ + +int QDate::month() const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + return m; +} + +/*! + Returns the day of the month (1..31) of this date. + + \sa year(), month(), dayOfWeek() +*/ + +int QDate::day() const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + return d; +} + +/*! + Returns the weekday (Monday=1..Sunday=7) for this date. + + \sa day(), dayOfYear() +*/ + +int QDate::dayOfWeek() const +{ + return ( jd % 7 ) + 1; +} + +/*! + Returns the day of the year (1..365) for this date. + + \sa day(), dayOfWeek() +*/ + +int QDate::dayOfYear() const +{ + return jd - gregorianToJulian(year(), 1, 1) + 1; +} + +/*! + Returns the number of days in the month (28..31) for this date. + + \sa day(), daysInYear() +*/ + +int QDate::daysInMonth() const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + if ( m == 2 && leapYear(y) ) + return 29; + else + return monthDays[m]; +} + +/*! + Returns the number of days in the year (365 or 366) for this date. + + \sa day(), daysInMonth() +*/ + +int QDate::daysInYear() const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + return leapYear( y ) ? 366 : 365; +} + +/*! + Returns the week number (1 to 53), and stores the year in \a + *yearNumber unless \a yearNumber is null (the default). + + Returns 0 if the date is invalid. + + In accordance with ISO 8601, weeks start on Monday and the first + Thursday of a year is always in week 1 of that year. Most years + have 52 weeks, but some have 53. + + \a *yearNumber is not always the same as year(). For example, 1 + January 2000 has week number 52 in the year 1999, and 31 December + 2002 has week number 1 in the year 2003. + + \sa isValid() +*/ + +int QDate::weekNumber( int *yearNumber ) const +{ + if ( !isValid() ) + return 0; + + int dow = dayOfWeek(); + int doy = dayOfYear(); + int currYear = year(); + int jan1WeekDay = QDate( currYear, 1, 1 ).dayOfWeek(); + int yearNum; + int weekNum; + + if ( doy <= (8 - jan1WeekDay) && jan1WeekDay > 4 ) { + yearNum = currYear - 1; + weekNum = 52; + if ( jan1WeekDay == 5 || + (jan1WeekDay == 6 && QDate::leapYear(yearNum)) ) + weekNum++; + } else { + int totalDays = 365; + if ( QDate::leapYear(currYear) ) + totalDays++; + + if ( (totalDays - doy < 4 - dow) + || (jan1WeekDay == 7 && totalDays - doy < 3) ) { + yearNum = currYear + 1; + weekNum = 1; + } else { + int j = doy + ( 7 - dow ) + ( jan1WeekDay - 1 ); + yearNum = currYear; + weekNum = j / 7; + if ( jan1WeekDay > 4 ) + weekNum--; + } + } + if ( yearNumber ) + *yearNumber = yearNum; + return weekNum; +} + +/*! + \fn QString QDate::monthName( int month ) + \obsolete + + Use shortMonthName() instead. +*/ +#ifndef QT_NO_TEXTDATE +/*! + Returns the name of the \a month. + + 1 = "Jan", 2 = "Feb", ... 12 = "Dec" + + The month names will be localized according to the system's locale + settings. + + \sa toString(), longMonthName(), shortDayName(), longDayName() +*/ + +QString QDate::shortMonthName( int month ) +{ +#if defined(QT_CHECK_RANGE) + if ( month < 1 || month > 12 ) { + qWarning( "QDate::shortMonthName: Parameter out ouf range." ); + month = 1; + } +#endif +#ifndef Q_WS_WIN + char buffer[255]; + tm tt; + memset( &tt, 0, sizeof( tm ) ); + tt.tm_mon = month - 1; + if ( strftime( buffer, sizeof( buffer ), "%b", &tt ) ) + return QString::fromLocal8Bit( buffer ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wYear = 2000; + st.wMonth = month; + st.wDay = 1; + const wchar_t mmm_t[] = L"MMM"; // workaround for Borland + QT_WA( { + TCHAR buf[255]; + if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, mmm_t, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "MMM", (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ); +#endif + return QString::null; +} + +/*! + Returns the long name of the \a month. + + 1 = "January", 2 = "February", ... 12 = "December" + + The month names will be localized according to the system's locale + settings. + + \sa toString(), shortMonthName(), shortDayName(), longDayName() +*/ + +QString QDate::longMonthName( int month ) +{ +#if defined(QT_CHECK_RANGE) + if ( month < 1 || month > 12 ) { + qWarning( "QDate::longMonthName: Parameter out ouf range." ); + month = 1; + } +#endif +#ifndef Q_WS_WIN + char buffer[255]; + tm tt; + memset( &tt, 0, sizeof( tm ) ); + tt.tm_mon = month - 1; + if ( strftime( buffer, sizeof( buffer ), "%B", &tt ) ) + return QString::fromLocal8Bit( buffer ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wYear = 2000; + st.wMonth = month; + st.wDay = 1 ; + const wchar_t mmmm_t[] = L"MMMM"; // workaround for Borland + QT_WA( { + TCHAR buf[255]; + if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, mmmm_t, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "MMMM", (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ) +#endif + + return QString::null; +} + +/*! + \fn QString QDate::dayName( int weekday ) + \obsolete + + Use shortDayName() instead. +*/ + +/*! + Returns the name of the \a weekday. + + 1 = "Mon", 2 = "Tue", ... 7 = "Sun" + + The day names will be localized according to the system's locale + settings. + + \sa toString(), shortMonthName(), longMonthName(), longDayName() +*/ + +QString QDate::shortDayName( int weekday ) +{ +#if defined(QT_CHECK_RANGE) + if ( weekday < 1 || weekday > 7 ) { + qWarning( "QDate::shortDayName: Parameter out of range." ); + weekday = 1; + } +#endif +#ifndef Q_WS_WIN + char buffer[255]; + tm tt; + memset( &tt, 0, sizeof( tm ) ); + tt.tm_wday = ( weekday == 7 ) ? 0 : weekday; + if ( strftime( buffer, sizeof( buffer ), "%a", &tt ) ) + return QString::fromLocal8Bit( buffer ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wYear = 2001; + st.wMonth = 10; + st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday; + st.wDay = 21 + st.wDayOfWeek; + const wchar_t ddd_t[] = L"ddd"; // workaround for Borland + QT_WA( { + TCHAR buf[255]; + if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, ddd_t, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "ddd", (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ); +#endif + + return QString::null; +} + +/*! + Returns the long name of the \a weekday. + + 1 = "Monday", 2 = "Tuesday", ... 7 = "Sunday" + + The day names will be localized according to the system's locale + settings. + + \sa toString(), shortDayName(), shortMonthName(), longMonthName() +*/ + +QString QDate::longDayName( int weekday ) +{ +#if defined(QT_CHECK_RANGE) + if ( weekday < 1 || weekday > 7 ) { + qWarning( "QDate::longDayName: Parameter out of range." ); + weekday = 1; + } +#endif +#ifndef Q_WS_WIN + char buffer[255]; + tm tt; + memset( &tt, 0, sizeof( tm ) ); + tt.tm_wday = ( weekday == 7 ) ? 0 : weekday; + if ( strftime( buffer, sizeof( buffer ), "%A", &tt ) ) + return QString::fromLocal8Bit( buffer ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wYear = 2001; + st.wMonth = 10; + st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday; + st.wDay = 21 + st.wDayOfWeek; + const wchar_t dddd_t[] = L"dddd"; // workaround for Borland + QT_WA( { + TCHAR buf[255]; + if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, dddd_t, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "dddd", (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ); +#endif + + return QString::null; +} +#endif //QT_NO_TEXTDATE + +#ifndef QT_NO_DATESTRING + +#if !defined(QT_NO_SPRINTF) +/*! + \overload + + Returns the date as a string. The \a f parameter determines the + format of the string. + + If \a f is \c Qt::TextDate, the string format is "Sat May 20 1995" + (using the shortDayName() and shortMonthName() functions to + generate the string, so the day and month names are locale + specific). + + If \a f is \c Qt::ISODate, the string format corresponds to the + ISO 8601 specification for representations of dates, which is + YYYY-MM-DD where YYYY is the year, MM is the month of the year + (between 01 and 12), and DD is the day of the month between 01 and + 31. + + If \a f is \c Qt::LocalDate, the string format depends on the + locale settings of the system. + + \sa shortDayName(), shortMonthName() +*/ +QString QDate::toString( Qt::DateFormat f ) const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + switch ( f ) { + case Qt::LocalDate: + { +#ifndef Q_WS_WIN + tm tt; + memset( &tt, 0, sizeof( tm ) ); + char buf[255]; + tt.tm_mday = day(); + tt.tm_mon = month() - 1; + tt.tm_year = year() - 1900; + + static const char * avoidEgcsWarning = "%x"; + if ( strftime( buf, sizeof(buf), avoidEgcsWarning, &tt ) ) + return QString::fromLocal8Bit( buf ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wYear = year(); + st.wMonth = month(); + st.wDay = day(); + QT_WA( { + TCHAR buf[255]; + if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ); +#endif + return QString::null; + } + default: +#ifndef QT_NO_TEXTDATE + case Qt::TextDate: + { + QString buf = shortDayName( dayOfWeek() ); + buf += ' '; + buf += shortMonthName( m ); + QString t; + t.sprintf( " %d %d", d, y ); + buf += t; + return buf; + } +#endif + case Qt::ISODate: + { + QString month( QString::number( m ).rightJustify( 2, '0' ) ); + QString day( QString::number( d ).rightJustify( 2, '0' ) ); + return QString::number( y ) + "-" + month + "-" + day; + } + } +} +#endif //QT_NO_SPRINTF + +/*! + Returns the date as a string. The \a format parameter determines + the format of the result string. + + These expressions may be used: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1-31) + \row \i dd \i the day as number with a leading zero (01-31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon'..'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday'..'Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan'..'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January'..'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number (1752-8000) + \endtable + + All other input characters will be ignored. + + Example format strings (assuming that the QDate is the + 20<sup><small>th</small></sup> July 1969): + \table + \header \i Format \i Result + \row \i dd.MM.yyyy \i11 20.07.1969 + \row \i ddd MMMM d yy \i11 Sun July 20 69 + \endtable + + \sa QDate::toString() QTime::toString() + +*/ +QString QDate::toString( const QString& format ) const +{ + return fmtDateTime( format, 0, this ); +} +#endif //QT_NO_DATESTRING + +/*! + Sets the date's year \a y, month \a m and day \a d. + + \a y must be in the range 1752..8000, \a m must be in the range + 1..12, and \a d must be in the range 1..31. + + \warning If \a y is in the range 0..99, it is interpreted as + 1900..1999. + + Returns TRUE if the date is valid; otherwise returns FALSE. +*/ + +bool QDate::setYMD( int y, int m, int d ) +{ + if ( year() == y && month() == m && day() == d ) + return isValid(); + if ( !isValid(y,m,d) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QDate::setYMD: Invalid date %04d-%02d-%02d", y, m, d ); +#endif + return FALSE; + } + jd = gregorianToJulian( y, m, d ); + return TRUE; +} + +/*! + Returns a QDate object containing a date \a ndays later than the + date of this object (or earlier if \a ndays is negative). + + \sa addMonths() addYears() daysTo() +*/ + +QDate QDate::addDays( int ndays ) const +{ + QDate d; + d.jd = jd + ndays; + return d; +} + +/*! + Returns a QDate object containing a date \a nmonths later than the + date of this object (or earlier if \a nmonths is negative). + + \sa addDays() addYears() +*/ + +QDate QDate::addMonths( int nmonths ) const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + + while ( nmonths != 0 ) { + if ( nmonths < 0 && nmonths + 12 <= 0 ) { + y--; + nmonths+=12; + } else if ( nmonths < 0 ) { + m+= nmonths; + nmonths = 0; + if ( m <= 0 ) { + --y; + m+=12; + } + } else if ( nmonths - 12 >= 0 ) { + y++; + nmonths-=12; + } else if ( m == 12 ) { + y++; + m = 0; + } else { + m+= nmonths; + nmonths = 0; + if ( m > 12 ) { + ++y; + m -= 12; + } + } + } + + QDate tmp(y,m,1); + + if( d > tmp.daysInMonth() ) + d = tmp.daysInMonth(); + + QDate date(y, m, d); + return date; + +} + +/*! + Returns a QDate object containing a date \a nyears later than the + date of this object (or earlier if \a nyears is negative). + + \sa addDays(), addMonths() +*/ + +QDate QDate::addYears( int nyears ) const +{ + int y, m, d; + julianToGregorian( jd, y, m, d ); + y += nyears; + QDate date(y, m, d); + return date; +} + + + +/*! + Returns the number of days from this date to \a d (which is + negative if \a d is earlier than this date). + + Example: + \code + QDate d1( 1995, 5, 17 ); // May 17th 1995 + QDate d2( 1995, 5, 20 ); // May 20th 1995 + d1.daysTo( d2 ); // returns 3 + d2.daysTo( d1 ); // returns -3 + \endcode + + \sa addDays() +*/ + +int QDate::daysTo( const QDate &d ) const +{ + return d.jd - jd; +} + + +/*! + \fn bool QDate::operator==( const QDate &d ) const + + Returns TRUE if this date is equal to \a d; otherwise returns FALSE. +*/ + +/*! + \fn bool QDate::operator!=( const QDate &d ) const + + Returns TRUE if this date is different from \a d; otherwise returns FALSE. +*/ + +/*! + \fn bool QDate::operator<( const QDate &d ) const + + Returns TRUE if this date is earlier than \a d, otherwise returns FALSE. +*/ + +/*! + \fn bool QDate::operator<=( const QDate &d ) const + + Returns TRUE if this date is earlier than or equal to \a d, + otherwise returns FALSE. +*/ + +/*! + \fn bool QDate::operator>( const QDate &d ) const + + Returns TRUE if this date is later than \a d, otherwise returns FALSE. +*/ + +/*! + \fn bool QDate::operator>=( const QDate &d ) const + + Returns TRUE if this date is later than or equal to \a d, + otherwise returns FALSE. +*/ + +/*! + \overload + Returns the current date, as reported by the system clock. + + \sa QTime::currentTime(), QDateTime::currentDateTime() +*/ + +QDate QDate::currentDate() +{ + return currentDate( Qt::LocalTime ); +} + +/*! + Returns the current date, as reported by the system clock, for the + TimeSpec \a ts. The default TimeSpec is LocalTime. + + \sa QTime::currentTime(), QDateTime::currentDateTime(), Qt::TimeSpec +*/ +QDate QDate::currentDate( Qt::TimeSpec ts ) +{ + QDate d; +#if defined(Q_OS_WIN32) + SYSTEMTIME t; + memset( &t, 0, sizeof(SYSTEMTIME) ); + if ( ts == Qt::LocalTime ) + GetLocalTime( &t ); + else + GetSystemTime( &t ); + d.jd = gregorianToJulian( t.wYear, t.wMonth, t.wDay ); +#else + time_t ltime; + time( <ime ); + tm *t; + if ( ts == Qt::LocalTime ) + t = localtime( <ime ); + else + t = gmtime( <ime ); + d.jd = gregorianToJulian( t->tm_year + 1900, t->tm_mon + 1, t->tm_mday ); +#endif + return d; +} + +#ifndef QT_NO_DATESTRING +/*! + Returns the QDate represented by the string \a s, using the format + \a f, or an invalid date if the string cannot be parsed. + + Note for \c Qt::TextDate: It is recommended that you use the + English short month names (e.g. "Jan"). Although localized month + names can also be used, they depend on the user's locale settings. + + \warning \c Qt::LocalDate cannot be used here. +*/ +QDate QDate::fromString( const QString& s, Qt::DateFormat f ) +{ + if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QDate::fromString: Parameter out of range." ); +#endif + return QDate(); + } + switch ( f ) { + case Qt::ISODate: + { + int year( s.mid( 0, 4 ).toInt() ); + int month( s.mid( 5, 2 ).toInt() ); + int day( s.mid( 8, 2 ).toInt() ); + if ( year && month && day ) + return QDate( year, month, day ); + } + break; + default: +#ifndef QT_NO_TEXTDATE + case Qt::TextDate: + { + /* + This will fail gracefully if the input string doesn't + contain any space. + */ + int monthPos = s.find( ' ' ) + 1; + int dayPos = s.find( ' ', monthPos ) + 1; + + QString monthName( s.mid(monthPos, dayPos - monthPos - 1) ); + int month = -1; + + // try English names first + for ( int i = 0; i < 12; i++ ) { + if ( monthName == qt_shortMonthNames[i] ) { + month = i + 1; + break; + } + } + + // try the localized names + if ( month == -1 ) { + for ( int i = 0; i < 12; i++ ) { + if ( monthName == shortMonthName( i + 1 ) ) { + month = i + 1; + break; + } + } + } +#if defined(QT_CHECK_RANGE) + if ( month < 1 || month > 12 ) { + qWarning( "QDate::fromString: Parameter out of range." ); + month = 1; + } +#endif + int day = s.mid( dayPos, 2 ).stripWhiteSpace().toInt(); + int year = s.right( 4 ).toInt(); + return QDate( year, month, day ); + } +#else + break; +#endif + } + return QDate(); +} +#endif //QT_NO_DATESTRING + +/*! + \overload + + Returns TRUE if the specified date (year \a y, month \a m and day + \a d) is valid; otherwise returns FALSE. + + Example: + \code + QDate::isValid( 2002, 5, 17 ); // TRUE May 17th 2002 is valid + QDate::isValid( 2002, 2, 30 ); // FALSE Feb 30th does not exist + QDate::isValid( 2004, 2, 29 ); // TRUE 2004 is a leap year + QDate::isValid( 1202, 6, 6 ); // FALSE 1202 is pre-Gregorian + \endcode + + \warning A \a y value in the range 00..99 is interpreted as + 1900..1999. + + \sa isNull(), setYMD() +*/ + +bool QDate::isValid( int y, int m, int d ) +{ + if ( y >= 0 && y <= 99 ) + y += 1900; + else if ( y < FIRST_YEAR || (y == FIRST_YEAR && (m < 9 || + (m == 9 && d < 14))) ) + return FALSE; + return (d > 0 && m > 0 && m <= 12) && + (d <= monthDays[m] || (d == 29 && m == 2 && leapYear(y))); +} + +/*! + Returns TRUE if the specified year \a y is a leap year; otherwise + returns FALSE. +*/ + +bool QDate::leapYear( int y ) +{ + return y % 4 == 0 && y % 100 != 0 || y % 400 == 0; +} + +/*! + \internal + Converts a Gregorian date to a Julian day. + This algorithm is taken from Communications of the ACM, Vol 6, No 8. + \sa julianToGregorian() +*/ + +uint QDate::gregorianToJulian( int y, int m, int d ) +{ + uint c, ya; + if ( y <= 99 ) + y += 1900; + if ( m > 2 ) { + m -= 3; + } else { + m += 9; + y--; + } + c = y; // NOTE: Sym C++ 6.0 bug + c /= 100; + ya = y - 100*c; + return 1721119 + d + (146097*c)/4 + (1461*ya)/4 + (153*m+2)/5; +} + +/*! + \internal + Converts a Julian day to a Gregorian date. + This algorithm is taken from Communications of the ACM, Vol 6, No 8. + \sa gregorianToJulian() +*/ + +void QDate::julianToGregorian( uint jd, int &y, int &m, int &d ) +{ + uint x; + uint j = jd - 1721119; + y = (j*4 - 1)/146097; + j = j*4 - 146097*y - 1; + x = j/4; + j = (x*4 + 3) / 1461; + y = 100*y + j; + x = (x*4) + 3 - 1461*j; + x = (x + 4)/4; + m = (5*x - 3)/153; + x = 5*x - 3 - 153*m; + d = (x + 5)/5; + if ( m < 10 ) { + m += 3; + } else { + m -= 9; + y++; + } +} + + +/***************************************************************************** + QTime member functions + *****************************************************************************/ + +/*! + \class QTime qdatetime.h + \reentrant + + \brief The QTime class provides clock time functions. + + \ingroup time + \mainclass + + A QTime object contains a clock time, i.e. the number of hours, + minutes, seconds, and milliseconds since midnight. It can read the + current time from the system clock and measure a span of elapsed + time. It provides functions for comparing times and for + manipulating a time by adding a number of (milli)seconds. + + QTime uses the 24-hour clock format; it has no concept of AM/PM. + It operates in local time; it knows nothing about time zones or + daylight savings time. + + A QTime object is typically created either by giving the number of + hours, minutes, seconds, and milliseconds explicitly, or by using + the static function currentTime(), which creates a QTime object + that contains the system's clock time. Note that the accuracy + depends on the accuracy of the underlying operating system; not + all systems provide 1-millisecond accuracy. + + The hour(), minute(), second(), and msec() functions provide + access to the number of hours, minutes, seconds, and milliseconds + of the time. The same information is provided in textual format by + the toString() function. + + QTime provides a full set of operators to compare two QTime + objects. One time is considered smaller than another if it is + earlier than the other. + + The time a given number of seconds or milliseconds later than a + given time can be found using the addSecs() or addMSecs() + functions. Correspondingly, the number of (milli)seconds between + two times can be found using the secsTo() or msecsTo() functions. + + QTime can be used to measure a span of elapsed time using the + start(), restart(), and elapsed() functions. + + \sa QDate, QDateTime +*/ + +/*! + \fn QTime::QTime() + + Constructs the time 0 hours, minutes, seconds and milliseconds, + i.e. 00:00:00.000 (midnight). This is a valid time. + + \sa isValid() +*/ + +/*! + Constructs a time with hour \a h, minute \a m, seconds \a s and + milliseconds \a ms. + + \a h must be in the range 0..23, \a m and \a s must be in the + range 0..59, and \a ms must be in the range 0..999. + + \sa isValid() +*/ + +QTime::QTime( int h, int m, int s, int ms ) +{ + setHMS( h, m, s, ms ); +} + + +/*! + \fn bool QTime::isNull() const + + Returns TRUE if the time is equal to 00:00:00.000; otherwise + returns FALSE. A null time is valid. + + \sa isValid() +*/ + +/*! + Returns TRUE if the time is valid; otherwise returns FALSE. The + time 23:30:55.746 is valid, whereas 24:12:30 is invalid. + + \sa isNull() +*/ + +bool QTime::isValid() const +{ + return ds < MSECS_PER_DAY; +} + + +/*! + Returns the hour part (0..23) of the time. +*/ + +int QTime::hour() const +{ + return ds / MSECS_PER_HOUR; +} + +/*! + Returns the minute part (0..59) of the time. +*/ + +int QTime::minute() const +{ + return (ds % MSECS_PER_HOUR)/MSECS_PER_MIN; +} + +/*! + Returns the second part (0..59) of the time. +*/ + +int QTime::second() const +{ + return (ds / 1000)%SECS_PER_MIN; +} + +/*! + Returns the millisecond part (0..999) of the time. +*/ + +int QTime::msec() const +{ + return ds % 1000; +} + +#ifndef QT_NO_DATESTRING +#ifndef QT_NO_SPRINTF +/*! + \overload + + Returns the time as a string. Milliseconds are not included. The + \a f parameter determines the format of the string. + + If \a f is \c Qt::TextDate, the string format is HH:MM:SS; e.g. 1 + second before midnight would be "23:59:59". + + If \a f is \c Qt::ISODate, the string format corresponds to the + ISO 8601 extended specification for representations of dates, + which is also HH:MM:SS. + + If \a f is Qt::LocalDate, the string format depends on the locale + settings of the system. +*/ + +QString QTime::toString( Qt::DateFormat f ) const +{ + switch ( f ) { + case Qt::LocalDate: + { +#ifndef Q_WS_WIN + tm tt; + memset( &tt, 0, sizeof( tm ) ); + char buf[255]; + tt.tm_sec = second(); + tt.tm_min = minute(); + tt.tm_hour = hour(); + if ( strftime( buf, sizeof(buf), "%X", &tt ) ) + return QString::fromLocal8Bit( buf ); +#else + SYSTEMTIME st; + memset( &st, 0, sizeof(SYSTEMTIME) ); + st.wHour = hour(); + st.wMinute = minute(); + st.wSecond = second(); + st.wMilliseconds = 0; + QT_WA( { + TCHAR buf[255]; + if ( GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) ) + return QString::fromUcs2( (ushort*)buf ); + } , { + char buf[255]; + if ( GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) ) + return QString::fromLocal8Bit( buf ); + } ); +#endif + return QString::null; + } + default: + case Qt::ISODate: + case Qt::TextDate: + QString buf; + buf.sprintf( "%.2d:%.2d:%.2d", hour(), minute(), second() ); + return buf; + } +} +#endif + +/*! + Returns the time as a string. The \a format parameter determines + the format of the result string. + + These expressions may be used: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0..23 or 1..12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00..23 or 01..12 if AM/PM display) + \row \i m \i the minute without a leading zero (0..59) + \row \i mm \i the minute with a leading zero (00..59) + \row \i s \i the second whithout a leading zero (0..59) + \row \i ss \i the second whith a leading zero (00..59) + \row \i z \i the milliseconds without leading zeroes (0..999) + \row \i zzz \i the milliseconds with leading zeroes (000..999) + \row \i AP + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. + + Example format strings (assuming that the QTime is 14:13:09.042) + + \table + \header \i Format \i Result + \row \i hh:mm:ss.zzz \i11 14:13:09.042 + \row \i h:m:s ap \i11 2:13:9 pm + \endtable + + \sa QDate::toString() QTime::toString() +*/ +QString QTime::toString( const QString& format ) const +{ + return fmtDateTime( format, this, 0 ); +} +#endif //QT_NO_DATESTRING +/*! + Sets the time to hour \a h, minute \a m, seconds \a s and + milliseconds \a ms. + + \a h must be in the range 0..23, \a m and \a s must be in the + range 0..59, and \a ms must be in the range 0..999. Returns TRUE + if the set time is valid; otherwise returns FALSE. + + \sa isValid() +*/ + +bool QTime::setHMS( int h, int m, int s, int ms ) +{ + if ( !isValid(h,m,s,ms) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QTime::setHMS Invalid time %02d:%02d:%02d.%03d", h, m, s, + ms ); +#endif + ds = MSECS_PER_DAY; // make this invalid + return FALSE; + } + ds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms; + return TRUE; +} + +/*! + Returns a QTime object containing a time \a nsecs seconds later + than the time of this object (or earlier if \a nsecs is negative). + + Note that the time will wrap if it passes midnight. + + Example: + \code + QTime n( 14, 0, 0 ); // n == 14:00:00 + QTime t; + t = n.addSecs( 70 ); // t == 14:01:10 + t = n.addSecs( -70 ); // t == 13:58:50 + t = n.addSecs( 10*60*60 + 5 ); // t == 00:00:05 + t = n.addSecs( -15*60*60 ); // t == 23:00:00 + \endcode + + \sa addMSecs(), secsTo(), QDateTime::addSecs() +*/ + +QTime QTime::addSecs( int nsecs ) const +{ + return addMSecs( nsecs * 1000 ); +} + +/*! + Returns the number of seconds from this time to \a t (which is + negative if \a t is earlier than this time). + + Because QTime measures time within a day and there are 86400 + seconds in a day, the result is always between -86400 and 86400. + + \sa addSecs() QDateTime::secsTo() +*/ + +int QTime::secsTo( const QTime &t ) const +{ + return ((int)t.ds - (int)ds)/1000; +} + +/*! + Returns a QTime object containing a time \a ms milliseconds later + than the time of this object (or earlier if \a ms is negative). + + Note that the time will wrap if it passes midnight. See addSecs() + for an example. + + \sa addSecs(), msecsTo() +*/ + +QTime QTime::addMSecs( int ms ) const +{ + QTime t; + if ( ms < 0 ) { + // % not well-defined for -ve, but / is. + int negdays = (MSECS_PER_DAY-ms) / MSECS_PER_DAY; + t.ds = ((int)ds + ms + negdays*MSECS_PER_DAY) + % MSECS_PER_DAY; + } else { + t.ds = ((int)ds + ms) % MSECS_PER_DAY; + } + return t; +} + +/*! + Returns the number of milliseconds from this time to \a t (which + is negative if \a t is earlier than this time). + + Because QTime measures time within a day and there are 86400 + seconds in a day, the result is always between -86400 and 86400s. + + \sa secsTo() +*/ + +int QTime::msecsTo( const QTime &t ) const +{ + return (int)t.ds - (int)ds; +} + + +/*! + \fn bool QTime::operator==( const QTime &t ) const + + Returns TRUE if this time is equal to \a t; otherwise returns FALSE. +*/ + +/*! + \fn bool QTime::operator!=( const QTime &t ) const + + Returns TRUE if this time is different from \a t; otherwise returns FALSE. +*/ + +/*! + \fn bool QTime::operator<( const QTime &t ) const + + Returns TRUE if this time is earlier than \a t; otherwise returns FALSE. +*/ + +/*! + \fn bool QTime::operator<=( const QTime &t ) const + + Returns TRUE if this time is earlier than or equal to \a t; + otherwise returns FALSE. +*/ + +/*! + \fn bool QTime::operator>( const QTime &t ) const + + Returns TRUE if this time is later than \a t; otherwise returns FALSE. +*/ + +/*! + \fn bool QTime::operator>=( const QTime &t ) const + + Returns TRUE if this time is later than or equal to \a t; + otherwise returns FALSE. +*/ + + + +/*! + \overload + + Returns the current time as reported by the system clock. + + Note that the accuracy depends on the accuracy of the underlying + operating system; not all systems provide 1-millisecond accuracy. +*/ + +QTime QTime::currentTime() +{ + return currentTime( Qt::LocalTime ); +} + +/*! + Returns the current time as reported by the system clock, for the + TimeSpec \a ts. The default TimeSpec is LocalTime. + + Note that the accuracy depends on the accuracy of the underlying + operating system; not all systems provide 1-millisecond accuracy. + + \sa Qt::TimeSpec +*/ +QTime QTime::currentTime( Qt::TimeSpec ts ) +{ + QTime t; + currentTime( &t, ts ); + return t; +} + +#ifndef QT_NO_DATESTRING +/*! + Returns the representation \a s as a QTime using the format \a f, + or an invalid time if this is not possible. + + \warning Note that \c Qt::LocalDate cannot be used here. +*/ +QTime QTime::fromString( const QString& s, Qt::DateFormat f ) +{ + if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QTime::fromString: Parameter out of range." ); +#endif + return QTime(); + } + + int hour( s.mid( 0, 2 ).toInt() ); + int minute( s.mid( 3, 2 ).toInt() ); + int second( s.mid( 6, 2 ).toInt() ); + int msec( s.mid( 9, 3 ).toInt() ); + return QTime( hour, minute, second, msec ); +} +#endif + +/*! + \internal + \obsolete + + Fetches the current time and returns TRUE if the time is within one + minute after midnight, otherwise FALSE. The return value is used by + QDateTime::currentDateTime() to ensure that the date there is correct. +*/ + +bool QTime::currentTime( QTime *ct ) +{ + return currentTime( ct, Qt::LocalTime ); +} + + +/*! + \internal + + Fetches the current time, for the TimeSpec \a ts, and returns TRUE + if the time is within one minute after midnight, otherwise FALSE. The + return value is used by QDateTime::currentDateTime() to ensure that + the date there is correct. The default TimeSpec is LocalTime. + + \sa Qt::TimeSpec +*/ +bool QTime::currentTime( QTime *ct, Qt::TimeSpec ts ) +{ + if ( !ct ) { +#if defined(QT_CHECK_NULL) + qWarning( "QTime::currentTime(QTime *): Null pointer not allowed" ); +#endif + return FALSE; + } + +#if defined(Q_OS_WIN32) + SYSTEMTIME t; + if ( ts == Qt::LocalTime ) { + GetLocalTime( &t ); + } else { + GetSystemTime( &t ); + } + ct->ds = (uint)( MSECS_PER_HOUR*t.wHour + MSECS_PER_MIN*t.wMinute + + 1000*t.wSecond + t.wMilliseconds ); +#elif defined(Q_OS_UNIX) + struct timeval tv; + gettimeofday( &tv, 0 ); + time_t ltime = tv.tv_sec; + tm *t; + if ( ts == Qt::LocalTime ) { + t = localtime( <ime ); + } else { + t = gmtime( <ime ); + } + ct->ds = (uint)( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + + 1000 * t->tm_sec + tv.tv_usec / 1000 ); +#else + time_t ltime; // no millisecond resolution + ::time( <ime ); + tm *t; + if ( ts == Qt::LocalTime ) + localtime( <ime ); + else + gmtime( <ime ); + ct->ds = (uint) ( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + + 1000 * t->tm_sec ); +#endif + // 00:00.00 to 00:00.59.999 is considered as "midnight or right after" + return ct->ds < (uint) MSECS_PER_MIN; +} + +/*! + \overload + + Returns TRUE if the specified time is valid; otherwise returns + FALSE. + + The time is valid if \a h is in the range 0..23, \a m and \a s are + in the range 0..59, and \a ms is in the range 0..999. + + Example: + \code + QTime::isValid(21, 10, 30); // returns TRUE + QTime::isValid(22, 5, 62); // returns FALSE + \endcode +*/ + +bool QTime::isValid( int h, int m, int s, int ms ) +{ + return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000; +} + + +/*! + Sets this time to the current time. This is practical for timing: + + \code + QTime t; + t.start(); // start clock + ... // some lengthy task + qDebug( "%d\n", t.elapsed() ); // prints the number of msecs elapsed + \endcode + + \sa restart(), elapsed(), currentTime() +*/ + +void QTime::start() +{ + *this = currentTime(); +} + +/*! + Sets this time to the current time and returns the number of + milliseconds that have elapsed since the last time start() or + restart() was called. + + This function is guaranteed to be atomic and is thus very handy + for repeated measurements. Call start() to start the first + measurement and then restart() for each later measurement. + + Note that the counter wraps to zero 24 hours after the last call + to start() or restart(). + + \warning If the system's clock setting has been changed since the + last time start() or restart() was called, the result is + undefined. This can happen when daylight savings time is turned on + or off. + + \sa start(), elapsed(), currentTime() +*/ + +int QTime::restart() +{ + QTime t = currentTime(); + int n = msecsTo( t ); + if ( n < 0 ) // passed midnight + n += 86400*1000; + *this = t; + return n; +} + +/*! + Returns the number of milliseconds that have elapsed since the + last time start() or restart() was called. + + Note that the counter wraps to zero 24 hours after the last call + to start() or restart. + + Note that the accuracy depends on the accuracy of the underlying + operating system; not all systems provide 1-millisecond accuracy. + + \warning If the system's clock setting has been changed since the + last time start() or restart() was called, the result is + undefined. This can happen when daylight savings time is turned on + or off. + + \sa start(), restart() +*/ + +int QTime::elapsed() const +{ + int n = msecsTo( currentTime() ); + if ( n < 0 ) // passed midnight + n += 86400*1000; + return n; +} + + +/***************************************************************************** + QDateTime member functions + *****************************************************************************/ + +/*! + \class QDateTime qdatetime.h + \reentrant + \brief The QDateTime class provides date and time functions. + + \ingroup time + \mainclass + + A QDateTime object contains a calendar date and a clock time (a + "datetime"). It is a combination of the QDate and QTime classes. + It can read the current datetime from the system clock. It + provides functions for comparing datetimes and for manipulating a + datetime by adding a number of seconds, days, months or years. + + A QDateTime object is typically created either by giving a date + and time explicitly in the constructor, or by using the static + function currentDateTime(), which returns a QDateTime object set + to the system clock's time. The date and time can be changed with + setDate() and setTime(). A datetime can also be set using the + setTime_t() function, which takes a POSIX-standard "number of + seconds since 00:00:00 on January 1, 1970" value. The fromString() + function returns a QDateTime given a string and a date format + which is used to interpret the date within the string. + + The date() and time() functions provide access to the date and + time parts of the datetime. The same information is provided in + textual format by the toString() function. + + QDateTime provides a full set of operators to compare two + QDateTime objects where smaller means earlier and larger means + later. + + You can increment (or decrement) a datetime by a given number of + seconds using addSecs() or days using addDays(). Similarly you can + use addMonths() and addYears(). The daysTo() function returns the + number of days between two datetimes, and secsTo() returns the + number of seconds between two datetimes. + + The range of a datetime object is constrained to the ranges of the + QDate and QTime objects which it embodies. + + \sa QDate QTime QDateTimeEdit +*/ + + +/*! + \fn QDateTime::QDateTime() + + Constructs a null datetime (i.e. null date and null time). A null + datetime is invalid, since the date is invalid. + + \sa isValid() +*/ + + +/*! + Constructs a datetime with date \a date and null (but valid) time + (00:00:00.000). +*/ + +QDateTime::QDateTime( const QDate &date ) + : d(date) +{ +} + +/*! + Constructs a datetime with date \a date and time \a time. +*/ + +QDateTime::QDateTime( const QDate &date, const QTime &time ) + : d(date), t(time) +{ +} + + +/*! + \fn bool QDateTime::isNull() const + + Returns TRUE if both the date and the time are null; otherwise + returns FALSE. A null datetime is invalid. + + \sa QDate::isNull(), QTime::isNull() +*/ + +/*! + \fn bool QDateTime::isValid() const + + Returns TRUE if both the date and the time are valid; otherwise + returns FALSE. + + \sa QDate::isValid(), QTime::isValid() +*/ + +/*! + \fn QDate QDateTime::date() const + + Returns the date part of the datetime. + + \sa setDate(), time() +*/ + +/*! + \fn QTime QDateTime::time() const + + Returns the time part of the datetime. + + \sa setTime(), date() +*/ + +/*! + \fn void QDateTime::setDate( const QDate &date ) + + Sets the date part of this datetime to \a date. + + \sa date(), setTime() +*/ + +/*! + \fn void QDateTime::setTime( const QTime &time ) + + Sets the time part of this datetime to \a time. + + \sa time(), setDate() +*/ + + +/*! + Returns the datetime as the number of seconds that have passed + since 1970-01-01T00:00:00, Coordinated Universal Time (UTC). + + On systems that do not support timezones, this function will + behave as if local time were UTC. + + \sa setTime_t() +*/ + +uint QDateTime::toTime_t() const +{ + tm brokenDown; + brokenDown.tm_sec = t.second(); + brokenDown.tm_min = t.minute(); + brokenDown.tm_hour = t.hour(); + brokenDown.tm_mday = d.day(); + brokenDown.tm_mon = d.month() - 1; + brokenDown.tm_year = d.year() - 1900; + brokenDown.tm_isdst = -1; + int secsSince1Jan1970UTC = (int) mktime( &brokenDown ); + if ( secsSince1Jan1970UTC < -1 ) + secsSince1Jan1970UTC = -1; + return (uint) secsSince1Jan1970UTC; +} + +/*! + \overload + + Convenience function that sets the date and time to local time + based on the given UTC time. +*/ + +void QDateTime::setTime_t( uint secsSince1Jan1970UTC ) +{ + setTime_t( secsSince1Jan1970UTC, Qt::LocalTime ); +} + +/*! + Sets the date and time to \a ts time (\c Qt::LocalTime or \c + Qt::UTC) given the number of seconds that have passed since + 1970-01-01T00:00:00, Coordinated Universal Time (UTC). On systems + that do not support timezones this function will behave as if + local time were UTC. + + On Windows, only a subset of \a secsSince1Jan1970UTC values are + supported, as Windows starts counting from 1980. + + \sa toTime_t() +*/ +void QDateTime::setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec ts ) +{ + time_t tmp = (time_t) secsSince1Jan1970UTC; + tm *brokenDown = 0; + if ( ts == Qt::LocalTime ) + brokenDown = localtime( &tmp ); + if ( !brokenDown ) { + brokenDown = gmtime( &tmp ); + if ( !brokenDown ) { + d.jd = QDate::gregorianToJulian( 1970, 1, 1 ); + t.ds = 0; + return; + } + } + d.jd = QDate::gregorianToJulian( brokenDown->tm_year + 1900, + brokenDown->tm_mon + 1, + brokenDown->tm_mday ); + t.ds = MSECS_PER_HOUR * brokenDown->tm_hour + + MSECS_PER_MIN * brokenDown->tm_min + + 1000 * brokenDown->tm_sec; +} +#ifndef QT_NO_DATESTRING +#ifndef QT_NO_SPRINTF +/*! + \overload + + Returns the datetime as a string. The \a f parameter determines + the format of the string. + + If \a f is \c Qt::TextDate, the string format is "Wed May 20 + 03:40:13 1998" (using QDate::shortDayName(), QDate::shortMonthName(), + and QTime::toString() to generate the string, so the day and month + names will have localized names). + + If \a f is \c Qt::ISODate, the string format corresponds to the + ISO 8601 extended specification for representations of dates and + times, which is YYYY-MM-DDTHH:MM:SS. + + If \a f is \c Qt::LocalDate, the string format depends on the + locale settings of the system. + + If the format \a f is invalid, toString() returns a null string. + + \sa QDate::toString() QTime::toString() +*/ + +QString QDateTime::toString( Qt::DateFormat f ) const +{ + if ( f == Qt::ISODate ) { + return d.toString( Qt::ISODate ) + "T" + t.toString( Qt::ISODate ); + } +#ifndef QT_NO_TEXTDATE + else if ( f == Qt::TextDate ) { +#ifndef Q_WS_WIN + QString buf = d.shortDayName( d.dayOfWeek() ); + buf += ' '; + buf += d.shortMonthName( d.month() ); + buf += ' '; + buf += QString().setNum( d.day() ); + buf += ' '; +#else + QString buf; + QString winstr; + QT_WA( { + TCHAR out[255]; + GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255 ); + winstr = QString::fromUcs2( (ushort*)out ); + } , { + char out[255]; + GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255 ); + winstr = QString::fromLocal8Bit( out ); + } ); + switch ( winstr.toInt() ) { + case 1: + buf = d.shortDayName( d.dayOfWeek() ) + " " + QString().setNum( d.day() ) + ". " + d.shortMonthName( d.month() ) + " "; + break; + default: + buf = d.shortDayName( d.dayOfWeek() ) + " " + d.shortMonthName( d.month() ) + " " + QString().setNum( d.day() ) + " "; + break; + } +#endif + buf += t.toString(); + buf += ' '; + buf += QString().setNum( d.year() ); + return buf; + } +#endif + else if ( f == Qt::LocalDate ) { + return d.toString( Qt::LocalDate ) + " " + t.toString( Qt::LocalDate ); + } + return QString::null; +} +#endif + +/*! + Returns the datetime as a string. The \a format parameter + determines the format of the result string. + + These expressions may be used for the date: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1-31) + \row \i dd \i the day as number with a leading zero (01-31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon'..'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday'..'Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan'..'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January'..'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number (1752-8000) + \endtable + + These expressions may be used for the time: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0..23 or 1..12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00..23 or 01..12 if AM/PM display) + \row \i m \i the minute without a leading zero (0..59) + \row \i mm \i the minute with a leading zero (00..59) + \row \i s \i the second whithout a leading zero (0..59) + \row \i ss \i the second whith a leading zero (00..59) + \row \i z \i the milliseconds without leading zeroes (0..999) + \row \i zzz \i the milliseconds with leading zeroes (000..999) + \row \i AP + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. + + Example format strings (assumed that the QDateTime is + 21<small><sup>st</sup></small> May 2001 14:13:09) + + \table + \header \i Format \i Result + \row \i dd.MM.yyyy \i11 21.05.2001 + \row \i ddd MMMM d yy \i11 Tue May 21 01 + \row \i hh:mm:ss.zzz \i11 14:13:09.042 + \row \i h:m:s ap \i11 2:13:9 pm + \endtable + + \sa QDate::toString() QTime::toString() +*/ +QString QDateTime::toString( const QString& format ) const +{ + return fmtDateTime( format, &t, &d ); +} +#endif //QT_NO_DATESTRING + +/*! + Returns a QDateTime object containing a datetime \a ndays days + later than the datetime of this object (or earlier if \a ndays is + negative). + + \sa daysTo(), addMonths(), addYears(), addSecs() +*/ + +QDateTime QDateTime::addDays( int ndays ) const +{ + return QDateTime( d.addDays(ndays), t ); +} + +/*! + Returns a QDateTime object containing a datetime \a nmonths months + later than the datetime of this object (or earlier if \a nmonths + is negative). + + \sa daysTo(), addDays(), addYears(), addSecs() +*/ + +QDateTime QDateTime::addMonths( int nmonths ) const +{ + return QDateTime( d.addMonths(nmonths), t ); +} + +/*! + Returns a QDateTime object containing a datetime \a nyears years + later than the datetime of this object (or earlier if \a nyears is + negative). + + \sa daysTo(), addDays(), addMonths(), addSecs() +*/ + +QDateTime QDateTime::addYears( int nyears ) const +{ + return QDateTime( d.addYears(nyears), t ); +} + +/*! + Returns a QDateTime object containing a datetime \a nsecs seconds + later than the datetime of this object (or earlier if \a nsecs is + negative). + + \sa secsTo(), addDays(), addMonths(), addYears() +*/ + +QDateTime QDateTime::addSecs( int nsecs ) const +{ + uint dd = d.jd; + int tt = t.ds; + int sign = 1; + if ( nsecs < 0 ) { + nsecs = -nsecs; + sign = -1; + } + if ( nsecs >= (int)SECS_PER_DAY ) { + dd += sign*(nsecs/SECS_PER_DAY); + nsecs %= SECS_PER_DAY; + } + tt += sign*nsecs*1000; + if ( tt < 0 ) { + tt = MSECS_PER_DAY - tt - 1; + dd -= tt / MSECS_PER_DAY; + tt = tt % MSECS_PER_DAY; + tt = MSECS_PER_DAY - tt - 1; + } else if ( tt >= (int)MSECS_PER_DAY ) { + dd += ( tt / MSECS_PER_DAY ); + tt = tt % MSECS_PER_DAY; + } + QDateTime ret; + ret.t.ds = tt; + ret.d.jd = dd; + return ret; +} + +/*! + Returns the number of days from this datetime to \a dt (which is + negative if \a dt is earlier than this datetime). + + \sa addDays(), secsTo() +*/ + +int QDateTime::daysTo( const QDateTime &dt ) const +{ + return d.daysTo( dt.d ); +} + +/*! + Returns the number of seconds from this datetime to \a dt (which + is negative if \a dt is earlier than this datetime). + + Example: + \code + QDateTime dt = QDateTime::currentDateTime(); + QDateTime xmas( QDate(dt.year(),12,24), QTime(17,00) ); + qDebug( "There are %d seconds to Christmas", dt.secsTo(xmas) ); + \endcode + + \sa addSecs(), daysTo(), QTime::secsTo() +*/ + +int QDateTime::secsTo( const QDateTime &dt ) const +{ + return t.secsTo(dt.t) + d.daysTo(dt.d)*SECS_PER_DAY; +} + + +/*! + Returns TRUE if this datetime is equal to \a dt; otherwise returns FALSE. + + \sa operator!=() +*/ + +bool QDateTime::operator==( const QDateTime &dt ) const +{ + return t == dt.t && d == dt.d; +} + +/*! + Returns TRUE if this datetime is different from \a dt; otherwise + returns FALSE. + + \sa operator==() +*/ + +bool QDateTime::operator!=( const QDateTime &dt ) const +{ + return t != dt.t || d != dt.d; +} + +/*! + Returns TRUE if this datetime is earlier than \a dt; otherwise + returns FALSE. +*/ + +bool QDateTime::operator<( const QDateTime &dt ) const +{ + if ( d < dt.d ) + return TRUE; + return d == dt.d ? t < dt.t : FALSE; +} + +/*! + Returns TRUE if this datetime is earlier than or equal to \a dt; + otherwise returns FALSE. +*/ + +bool QDateTime::operator<=( const QDateTime &dt ) const +{ + if ( d < dt.d ) + return TRUE; + return d == dt.d ? t <= dt.t : FALSE; +} + +/*! + Returns TRUE if this datetime is later than \a dt; otherwise + returns FALSE. +*/ + +bool QDateTime::operator>( const QDateTime &dt ) const +{ + if ( d > dt.d ) + return TRUE; + return d == dt.d ? t > dt.t : FALSE; +} + +/*! + Returns TRUE if this datetime is later than or equal to \a dt; + otherwise returns FALSE. +*/ + +bool QDateTime::operator>=( const QDateTime &dt ) const +{ + if ( d > dt.d ) + return TRUE; + return d == dt.d ? t >= dt.t : FALSE; +} + +/*! + \overload + + Returns the current datetime, as reported by the system clock. + + \sa QDate::currentDate(), QTime::currentTime() +*/ + +QDateTime QDateTime::currentDateTime() +{ + return currentDateTime( Qt::LocalTime ); +} + +/*! + Returns the current datetime, as reported by the system clock, for the + TimeSpec \a ts. The default TimeSpec is LocalTime. + + \sa QDate::currentDate(), QTime::currentTime(), Qt::TimeSpec +*/ + +QDateTime QDateTime::currentDateTime( Qt::TimeSpec ts ) +{ + QDateTime dt; + QTime t; + dt.setDate( QDate::currentDate(ts) ); + if ( QTime::currentTime(&t, ts) ) // midnight or right after? + dt.setDate( QDate::currentDate(ts) ); // fetch date again + dt.setTime( t ); + return dt; +} + +#ifndef QT_NO_DATESTRING +/*! + Returns the QDateTime represented by the string \a s, using the + format \a f, or an invalid datetime if this is not possible. + + Note for \c Qt::TextDate: It is recommended that you use the + English short month names (e.g. "Jan"). Although localized month + names can also be used, they depend on the user's locale settings. + + \warning Note that \c Qt::LocalDate cannot be used here. +*/ +QDateTime QDateTime::fromString( const QString& s, Qt::DateFormat f ) +{ + if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QDateTime::fromString: Parameter out of range" ); +#endif + return QDateTime(); + } + if ( f == Qt::ISODate ) { + return QDateTime( QDate::fromString( s.mid(0,10), Qt::ISODate ), + QTime::fromString( s.mid(11), Qt::ISODate ) ); + } +#if !defined(QT_NO_REGEXP) && !defined(QT_NO_TEXTDATE) + else if ( f == Qt::TextDate ) { + QString monthName( s.mid( 4, 3 ) ); + int month = -1; + // Assume that English monthnames are the default + for ( int i = 0; i < 12; ++i ) { + if ( monthName == qt_shortMonthNames[i] ) { + month = i + 1; + break; + } + } + // If English names can't be found, search the localized ones + if ( month == -1 ) { + for ( int i = 1; i <= 12; ++i ) { + if ( monthName == QDate::shortMonthName( i ) ) { + month = i; + break; + } + } + } +#if defined(QT_CHECK_RANGE) + if ( month < 1 || month > 12 ) { + qWarning( "QDateTime::fromString: Parameter out of range." ); + month = 1; + } +#endif + int day = s.mid( 8, 2 ).simplifyWhiteSpace().toInt(); + int year = s.right( 4 ).toInt(); + QDate date( year, month, day ); + QTime time; + int hour, minute, second; + int pivot = s.find( QRegExp("[0-9][0-9]:[0-9][0-9]:[0-9][0-9]") ); + if ( pivot != -1 ) { + hour = s.mid( pivot, 2 ).toInt(); + minute = s.mid( pivot+3, 2 ).toInt(); + second = s.mid( pivot+6, 2 ).toInt(); + time.setHMS( hour, minute, second ); + } + return QDateTime( date, time ); + } +#endif //QT_NO_REGEXP + return QDateTime(); +} +#endif //QT_NO_DATESTRING + + +/***************************************************************************** + Date/time stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +/*! + \relates QDate + + Writes the date, \a d, to the data stream, \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator<<( QDataStream &s, const QDate &d ) +{ + return s << (Q_UINT32)(d.jd); +} + +/*! + \relates QDate + + Reads a date from the stream \a s into \a d. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QDate &d ) +{ + Q_UINT32 jd; + s >> jd; + d.jd = jd; + return s; +} + +/*! + \relates QTime + + Writes time \a t to the stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator<<( QDataStream &s, const QTime &t ) +{ + return s << (Q_UINT32)(t.ds); +} + +/*! + \relates QTime + + Reads a time from the stream \a s into \a t. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QTime &t ) +{ + Q_UINT32 ds; + s >> ds; + t.ds = ds; + return s; +} + +/*! + \relates QDateTime + + Writes the datetime \a dt to the stream \a s. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator<<( QDataStream &s, const QDateTime &dt ) +{ + return s << dt.d << dt.t; +} + +/*! + \relates QDateTime + + Reads a datetime from the stream \a s into \a dt. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QDateTime &dt ) +{ + s >> dt.d >> dt.t; + return s; +} +#endif //QT_NO_DATASTREAM diff --git a/qmake/tools/qdeepcopy.cpp b/qmake/tools/qdeepcopy.cpp new file mode 100644 index 0000000..5008e36 --- a/dev/null +++ b/qmake/tools/qdeepcopy.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QDeepCopy class +** +** Created : 20020613 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qdeepcopy.h" + +/*! + \class QDeepCopy qdeepcopy.h + \brief The QDeepCopy class is a template class which ensures that + implicitly shared and explicitly shared classes reference unique + data. + + \reentrant + + \ingroup tools + \ingroup shared + + Normally, shared copies reference the same data to optimize memory + use and for maximum speed. In the example below, \c s1, \c s2, \c + s3, \c s4 and \c s5 share data. + + \code + // all 5 strings share the same data + QString s1 = "abcd"; + QString s2 = s1; + QString s3 = s2; + QString s4 = s3; + QString s5 = s2; + \endcode + + QDeepCopy can be used several ways to ensure that an object + references unique, unshared data. In the example below, \c s1, \c + s2 and \c s5 share data, while neither \c s3 nor \c s4 share data. + \code + // s1, s2 and s5 share the same data, neither s3 nor s4 are shared + QString s1 = "abcd"; + QString s2 = s1; + QDeepCopy<QString> s3 = s2; // s3 is a deep copy of s2 + QString s4 = s3; // s4 is a deep copy of s3 + QString s5 = s2; + \endcode + + In the example below, \c s1, \c s2 and \c s5 share data, and \c s3 + and \c s4 share data. + \code + // s1, s2 and s5 share the same data, s3 and s4 share the same data + QString s1 = "abcd"; + QString s2 = s1; + QString s3 = QDeepCopy<QString>( s2 ); // s3 is a deep copy of s2 + QString s4 = s3; // s4 is a shallow copy of s3 + QString s5 = s2; + \endcode + + QDeepCopy can also provide safety in multithreaded applications + that use shared classes. In the example below, the variable \c + global_string is used safely since the data contained in \c + global_string is always a deep copy. This ensures that all threads + get a unique copy of the data, and that any assignments to \c + global_string will result in a deep copy. + + \code + QDeepCopy<QString> global_string; // global string data + QMutex global_mutex; // mutex to protext global_string + + ... + + void setGlobalString( const QString &str ) + { + global_mutex.lock(); + global_string = str; // global_string is a deep copy of str + global_mutex.unlock(); + } + + ... + + void MyThread::run() + { + global_mutex.lock(); + QString str = global_string; // str is a deep copy of global_string + global_mutex.unlock(); + + // process the string data + ... + + // update global_string + setGlobalString( str ); + } + \endcode + + \warning It is the application developer's responsibility to + protect the object shared across multiple threads. + + The examples above use QString, which is an implicitly shared + class. The behavior of QDeepCopy is the same when using explicitly + shared classes like QByteArray. + + Currently, QDeepCopy works with the following classes: + \list + \i QMemArray (including subclasses like QByteArray and QCString) + \i QMap + \i QString + \i QValueList (including subclasses like QStringList and QValueStack) + \i QValueVector + \endlist + + \sa \link threads.html Thread Support in Qt \endlink +*/ + +/*! + \fn QDeepCopy::QDeepCopy() + + Constructs an empty instance of type \e T. +*/ + +/*! + \fn QDeepCopy::QDeepCopy( const T &t ) + + Constructs a deep copy of \a t. +*/ + +/*! + \fn QDeepCopy<T>& QDeepCopy::operator=( const T &t ) + + Assigns a deep copy of \a t. +*/ + +/*! + \fn QDeepCopy::operator T () + + Returns a deep copy of the encapsulated data. +*/ + diff --git a/qmake/tools/qdir.cpp b/qmake/tools/qdir.cpp new file mode 100644 index 0000000..418ea49 --- a/dev/null +++ b/qmake/tools/qdir.cpp @@ -0,0 +1,1294 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QDir class +** +** Created : 950427 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" +#include "qdir.h" + +#ifndef QT_NO_DIR +#include <private/qdir_p.h> +#include "qfileinfo.h" +#include "qregexp.h" +#include "qstringlist.h" +#include <stdlib.h> +#include <ctype.h> + + + +/*! + \class QDir + \brief The QDir class provides access to directory structures and their contents in a platform-independent way. + + \ingroup io + \mainclass + + A QDir is used to manipulate path names, access information + regarding paths and files, and manipulate the underlying file + system. + + A QDir can point to a file using either a relative or an absolute + path. Absolute paths begin with the directory separator "/" + (optionally preceded by a drive specification under Windows). If + you always use "/" as a directory separator, Qt will translate + your paths to conform to the underlying operating system. Relative + file names begin with a directory name or a file name and specify + a path relative to the current directory. + + The "current" path refers to the application's working directory. + A QDir's own path is set and retrieved with setPath() and path(). + + An example of an absolute path is the string "/tmp/quartz", a + relative path might look like "src/fatlib". You can use the + function isRelative() to check if a QDir is using a relative or an + absolute file path. Call convertToAbs() to convert a relative QDir + to an absolute one. For a simplified path use cleanDirPath(). To + obtain a path which has no symbolic links or redundant ".." + elements use canonicalPath(). The path can be set with setPath(), + and changed with cd() and cdUp(). + + QDir provides several static functions, for example, setCurrent() + to set the application's working directory and currentDirPath() to + retrieve the application's working directory. Access to some + common paths is provided with the static functions, current(), + home() and root() which return QDir objects or currentDirPath(), + homeDirPath() and rootDirPath() which return the path as a string. + + The number of entries in a directory is returned by count(). + Obtain a string list of the names of all the files and directories + in a directory with entryList(). If you prefer a list of QFileInfo + pointers use entryInfoList(). Both these functions can apply a + name filter, an attributes filter (e.g. read-only, files not + directories, etc.), and a sort order. The filters and sort may be + set with calls to setNameFilter(), setFilter() and setSorting(). + They may also be specified in the entryList() and + entryInfoList()'s arguments. + + Create a new directory with mkdir(), rename a directory with + rename() and remove an existing directory with rmdir(). Remove a + file with remove(). You can interrogate a directory with exists(), + isReadable() and isRoot(). + + To get a path with a filename use filePath(), and to get a + directory name use dirName(); neither of these functions checks + for the existence of the file or directory. + + The list of root directories is provided by drives(); on Unix + systems this returns a list containing one root directory, "/"; on + Windows the list will usually contain "C:/", and possibly "D:/", + etc. + + If you need the path in a form suitable for the underlying + operating system use convertSeparators(). + + Examples: + + See if a directory exists. + \code + QDir d( "example" ); // "./example" + if ( !d.exists() ) + qWarning( "Cannot find the example directory" ); + \endcode + + Traversing directories and reading a file. + \code + QDir d = QDir::root(); // "/" + if ( !d.cd("tmp") ) { // "/tmp" + qWarning( "Cannot find the \"/tmp\" directory" ); + } else { + QFile f( d.filePath("ex1.txt") ); // "/tmp/ex1.txt" + if ( !f.open(IO_ReadWrite) ) + qWarning( "Cannot create the file %s", f.name() ); + } + \endcode + + A program that lists all the files in the current directory + (excluding symbolic links), sorted by size, smallest first: + \code + #include <stdio.h> + #include <qdir.h> + + int main( int argc, char **argv ) + { + QDir d; + d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + d.setSorting( QDir::Size | QDir::Reversed ); + + const QFileInfoList *list = d.entryInfoList(); + QFileInfoListIterator it( *list ); + QFileInfo *fi; + + printf( " Bytes Filename\n" ); + while ( (fi = it.current()) != 0 ) { + printf( "%10li %s\n", fi->size(), fi->fileName().latin1() ); + ++it; + } + return 0; + } + \endcode +*/ + +/*! + Constructs a QDir pointing to the current directory. + + \sa currentDirPath() +*/ + +QDir::QDir() +{ + dPath = QString::fromLatin1("."); + init(); +} + +/*! + Constructs a QDir with path \a path, that filters its entries by + name using \a nameFilter and by attributes using \a filterSpec. It + also sorts the names using \a sortSpec. + + The default \a nameFilter is an empty string, which excludes + nothing; the default \a filterSpec is \c All, which also means + exclude nothing. The default \a sortSpec is \c Name|IgnoreCase, + i.e. sort by name case-insensitively. + + Example that lists all the files in "/tmp": + \code + QDir d( "/tmp" ); + for ( int i = 0; i < d.count(); i++ ) + printf( "%s\n", d[i] ); + \endcode + + If \a path is "" or QString::null, QDir uses "." (the current + directory). If \a nameFilter is "" or QString::null, QDir uses the + name filter "*" (all files). + + Note that \a path need not exist. + + \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting() +*/ + +QDir::QDir( const QString &path, const QString &nameFilter, + int sortSpec, int filterSpec ) +{ + init(); + dPath = cleanDirPath( path ); + if ( dPath.isEmpty() ) + dPath = QString::fromLatin1("."); + nameFilt = nameFilter; + if ( nameFilt.isEmpty() ) + nameFilt = QString::fromLatin1("*"); + filtS = (FilterSpec)filterSpec; + sortS = (SortSpec)sortSpec; +} + +/*! + Constructs a QDir that is a copy of the directory \a d. + + \sa operator=() +*/ + +QDir::QDir( const QDir &d ) +{ + dPath = d.dPath; + fList = 0; + fiList = 0; + nameFilt = d.nameFilt; + dirty = TRUE; + allDirs = d.allDirs; + filtS = d.filtS; + sortS = d.sortS; +} + + +void QDir::init() +{ + fList = 0; + fiList = 0; + nameFilt = QString::fromLatin1("*"); + dirty = TRUE; + allDirs = FALSE; + filtS = All; + sortS = SortSpec(Name | IgnoreCase); +} + +/*! + Destroys the QDir frees up its resources. +*/ + +QDir::~QDir() +{ + delete fList; + delete fiList; +} + + +/*! + Sets the path of the directory to \a path. The path is cleaned of + redundant ".", ".." and of multiple separators. No check is made + to ensure that a directory with this path exists. + + The path can be either absolute or relative. Absolute paths begin + with the directory separator "/" (optionally preceded by a drive + specification under Windows). Relative file names begin with a + directory name or a file name and specify a path relative to the + current directory. An example of an absolute path is the string + "/tmp/quartz", a relative path might look like "src/fatlib". + + \sa path(), absPath(), exists(), cleanDirPath(), dirName(), + absFilePath(), isRelative(), convertToAbs() +*/ + +void QDir::setPath( const QString &path ) +{ + dPath = cleanDirPath( path ); + if ( dPath.isEmpty() ) + dPath = QString::fromLatin1("."); + dirty = TRUE; +} + +/*! + \fn QString QDir::path() const + + Returns the path, this may contain symbolic links, but never + contains redundant ".", ".." or multiple separators. + + The returned path can be either absolute or relative (see + setPath()). + + \sa setPath(), absPath(), exists(), cleanDirPath(), dirName(), + absFilePath(), convertSeparators() +*/ + +/*! + Returns the absolute path (a path that starts with "/" or with a + drive specification), which may contain symbolic links, but never + contains redundant ".", ".." or multiple separators. + + \sa setPath(), canonicalPath(), exists(), cleanDirPath(), + dirName(), absFilePath() +*/ + +QString QDir::absPath() const +{ + if ( QDir::isRelativePath(dPath) ) { + QString tmp = currentDirPath(); + if ( tmp.right(1) != QString::fromLatin1("/") ) + tmp += '/'; + tmp += dPath; + return cleanDirPath( tmp ); + } else { + return cleanDirPath( dPath ); + } +} + +/*! + Returns the name of the directory; this is \e not the same as the + path, e.g. a directory with the name "mail", might have the path + "/var/spool/mail". If the directory has no name (e.g. it is the + root directory) QString::null is returned. + + No check is made to ensure that a directory with this name + actually exists. + + \sa path(), absPath(), absFilePath(), exists(), QString::isNull() +*/ + +QString QDir::dirName() const +{ + int pos = dPath.findRev( '/' ); + if ( pos == -1 ) + return dPath; + return dPath.right( dPath.length() - pos - 1 ); +} + +/*! + Returns the path name of a file in the directory. Does \e not + check if the file actually exists in the directory. If the QDir is + relative the returned path name will also be relative. Redundant + multiple separators or "." and ".." directories in \a fileName + will not be removed (see cleanDirPath()). + + If \a acceptAbsPath is TRUE a \a fileName starting with a + separator "/" will be returned without change. If \a acceptAbsPath + is FALSE an absolute path will be prepended to the fileName and + the resultant string returned. + + \sa absFilePath(), isRelative(), canonicalPath() +*/ + +QString QDir::filePath( const QString &fileName, + bool acceptAbsPath ) const +{ + if ( acceptAbsPath && !isRelativePath(fileName) ) + return QString(fileName); + + QString tmp = dPath; + if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName && + fileName[0] != '/') ) + tmp += '/'; + tmp += fileName; + return tmp; +} + +/*! + Returns the absolute path name of a file in the directory. Does \e + not check if the file actually exists in the directory. Redundant + multiple separators or "." and ".." directories in \a fileName + will not be removed (see cleanDirPath()). + + If \a acceptAbsPath is TRUE a \a fileName starting with a + separator "/" will be returned without change. If \a acceptAbsPath + is FALSE an absolute path will be prepended to the fileName and + the resultant string returned. + + \sa filePath() +*/ + +QString QDir::absFilePath( const QString &fileName, + bool acceptAbsPath ) const +{ + if ( acceptAbsPath && !isRelativePath( fileName ) ) + return fileName; + + QString tmp = absPath(); + if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName && + fileName[0] != '/') ) + tmp += '/'; + tmp += fileName; + return tmp; +} + + +/*! + Returns \a pathName with the '/' separators converted to + separators that are appropriate for the underlying operating + system. + + On Windows, convertSeparators("c:/winnt/system32") returns + "c:\winnt\system32". + + The returned string may be the same as the argument on some + operating systems, for example on Unix. +*/ + +QString QDir::convertSeparators( const QString &pathName ) +{ + QString n( pathName ); +#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) + for ( int i=0; i<(int)n.length(); i++ ) { + if ( n[i] == '/' ) + n[i] = '\\'; + } +#elif defined(Q_OS_MAC9) + while(n.length() && n[0] == '/' ) n = n.right(n.length()-1); + for ( int i=0; i<(int)n.length(); i++ ) { + if ( n[i] == '/' ) + n[i] = ':'; + } + if(n.contains(':') && n.left(1) != ':') + n.prepend(':'); +#endif + return n; +} + + +/*! + Changes the QDir's directory to \a dirName. + + If \a acceptAbsPath is TRUE a path starting with separator "/" + will cause the function to change to the absolute directory. If \a + acceptAbsPath is FALSE any number of separators at the beginning + of \a dirName will be removed and the function will descend into + \a dirName. + + Returns TRUE if the new directory exists and is readable; + otherwise returns FALSE. Note that the logical cd() operation is + not performed if the new directory does not exist. + + Calling cd( ".." ) is equivalent to calling cdUp(). + + \sa cdUp(), isReadable(), exists(), path() +*/ + +bool QDir::cd( const QString &dirName, bool acceptAbsPath ) +{ + if ( dirName.isEmpty() || dirName==QString::fromLatin1(".") ) + return TRUE; + QString old = dPath; + if ( acceptAbsPath && !isRelativePath(dirName) ) { + dPath = cleanDirPath( dirName ); + } else { + if ( !isRoot() ) { + dPath += '/'; + } else if ( dirName == ".." ) { + dPath = old; + return FALSE; + } + dPath += dirName; + if ( dirName.find('/') >= 0 + || old == QString::fromLatin1(".") + || dirName == QString::fromLatin1("..") ) + dPath = cleanDirPath( dPath ); + } + if ( !exists() ) { + dPath = old; // regret + return FALSE; + } + dirty = TRUE; + return TRUE; +} + +/*! + Changes directory by moving one directory up from the QDir's + current directory. + + Returns TRUE if the new directory exists and is readable; + otherwise returns FALSE. Note that the logical cdUp() operation is + not performed if the new directory does not exist. + + \sa cd(), isReadable(), exists(), path() +*/ + +bool QDir::cdUp() +{ + return cd( QString::fromLatin1("..") ); +} + +/*! + \fn QString QDir::nameFilter() const + + Returns the string set by setNameFilter() +*/ + +/*! + Sets the name filter used by entryList() and entryInfoList() to \a + nameFilter. + + The \a nameFilter is a wildcard (globbing) filter that understands + "*" and "?" wildcards. (See \link qregexp.html#wildcard-matching + QRegExp wildcard matching\endlink.) You may specify several filter + entries all separated by a single space " " or by a semi-colon + ";". + + For example, if you want entryList() and entryInfoList() to list + all files ending with either ".cpp" or ".h", you would use either + dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h"). + + \sa nameFilter(), setFilter() +*/ + +void QDir::setNameFilter( const QString &nameFilter ) +{ + nameFilt = nameFilter; + if ( nameFilt.isEmpty() ) + nameFilt = QString::fromLatin1("*"); + dirty = TRUE; +} + +/*! + \fn QDir::FilterSpec QDir::filter() const + + Returns the value set by setFilter() +*/ + +/*! + \enum QDir::FilterSpec + + This enum describes the filtering options available to QDir, e.g. + for entryList() and entryInfoList(). The filter value is specified + by OR-ing together values from the following list: + + \value Dirs List directories only. + \value Files List files only. + \value Drives List disk drives (ignored under Unix). + \value NoSymLinks Do not list symbolic links (ignored by operating + systems that don't support symbolic links). + \value All List directories, files, drives and symlinks (this does not list + broken symlinks unless you specify System). + \value TypeMask A mask for the the Dirs, Files, Drives and + NoSymLinks flags. + \value Readable List files for which the application has read access. + \value Writable List files for which the application has write access. + \value Executable List files for which the application has execute + access. Executables needs to be combined with Dirs or Files. + \value RWEMask A mask for the Readable, Writable and Executable flags. + \value Modified Only list files that have been modified (ignored + under Unix). + \value Hidden List hidden files (on Unix, files starting with a .). + \value System List system files (on Unix, FIFOs, sockets and + device files) + \value AccessMask A mask for the Readable, Writable, Executable + Modified, Hidden and System flags + \value DefaultFilter Internal flag. + + If you do not set any of \c Readable, \c Writable or \c + Executable, QDir will set all three of them. This makes the + default easy to write and at the same time useful. + + Examples: \c Readable|Writable means list all files for which the + application has read access, write access or both. \c Dirs|Drives + means list drives, directories, all files that the application can + read, write or execute, and also symlinks to such + files/directories. +*/ + + +/*! + Sets the filter used by entryList() and entryInfoList() to \a + filterSpec. The filter is used to specify the kind of files that + should be returned by entryList() and entryInfoList(). See + \l{QDir::FilterSpec}. + + \sa filter(), setNameFilter() +*/ + +void QDir::setFilter( int filterSpec ) +{ + if ( filtS == (FilterSpec) filterSpec ) + return; + filtS = (FilterSpec) filterSpec; + dirty = TRUE; +} + +/*! + \fn QDir::SortSpec QDir::sorting() const + + Returns the value set by setSorting() + + \sa setSorting() SortSpec +*/ + +/*! + \enum QDir::SortSpec + + This enum describes the sort options available to QDir, e.g. for + entryList() and entryInfoList(). The sort value is specified by + OR-ing together values from the following list: + + \value Name Sort by name. + \value Time Sort by time (modification time). + \value Size Sort by file size. + \value Unsorted Do not sort. + \value SortByMask A mask for Name, Time and Size. + + \value DirsFirst Put the directories first, then the files. + \value Reversed Reverse the sort order. + \value IgnoreCase Sort case-insensitively. + \value DefaultSort Internal flag. + + You can only specify one of the first four. + + If you specify both \c DirsFirst and \c Reversed, directories are + still put first, but in reverse order; the files will be listed + after the directories, again in reverse order. +*/ + +// ### Unsorted+DirsFirst ? Unsorted+Reversed? + +/*! + Sets the sort order used by entryList() and entryInfoList(). + + The \a sortSpec is specified by OR-ing values from the enum + \l{QDir::SortSpec}. + + \sa sorting() SortSpec +*/ + +void QDir::setSorting( int sortSpec ) +{ + if ( sortS == (SortSpec) sortSpec ) + return; + sortS = (SortSpec) sortSpec; + dirty = TRUE; +} + +/*! + \fn bool QDir::matchAllDirs() const + + Returns the value set by setMatchAllDirs() + + \sa setMatchAllDirs() +*/ + +/*! + If \a enable is TRUE then all directories are included (e.g. in + entryList()), and the nameFilter() is only applied to the files. + If \a enable is FALSE then the nameFilter() is applied to both + directories and files. + + \sa matchAllDirs() +*/ + +void QDir::setMatchAllDirs( bool enable ) +{ + if ( (bool)allDirs == enable ) + return; + allDirs = enable; + dirty = TRUE; +} + + +/*! + Returns the total number of directories and files that were found. + + Equivalent to entryList().count(). + + \sa operator[](), entryList() +*/ + +uint QDir::count() const +{ + return (uint)entryList().count(); +} + +/*! + Returns the file name at position \a index in the list of file + names. Equivalent to entryList().at(index). + + Returns a QString::null if the \a index is out of range or if the + entryList() function failed. + + \sa count(), entryList() +*/ + +QString QDir::operator[]( int index ) const +{ + entryList(); + return fList && index >= 0 && index < (int)fList->count() ? + (*fList)[index] : QString::null; +} + + +/*! + \obsolete + This function is included to easy porting from Qt 1.x to Qt 2.0, + it is the same as entryList(), but encodes the filenames as 8-bit + strings using QFile::encodedName(). + + It is more efficient to use entryList(). +*/ +QStrList QDir::encodedEntryList( int filterSpec, int sortSpec ) const +{ + QStrList r; + QStringList l = entryList(filterSpec,sortSpec); + for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { + r.append( QFile::encodeName(*it) ); + } + return r; +} + +/*! + \obsolete + \overload + This function is included to easy porting from Qt 1.x to Qt 2.0, + it is the same as entryList(), but encodes the filenames as 8-bit + strings using QFile::encodedName(). + + It is more efficient to use entryList(). +*/ +QStrList QDir::encodedEntryList( const QString &nameFilter, + int filterSpec, + int sortSpec ) const +{ + QStrList r; + QStringList l = entryList(nameFilter,filterSpec,sortSpec); + for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { + r.append( QFile::encodeName(*it) ); + } + return r; +} + + + +/*! + \overload + + Returns a list of the names of all the files and directories in + the directory, ordered in accordance with setSorting() and + filtered in accordance with setFilter() and setNameFilter(). + + The filter and sorting specifications can be overridden using the + \a filterSpec and \a sortSpec arguments. + + Returns an empty list if the directory is unreadable or does not + exist. + + \sa entryInfoList(), setNameFilter(), setSorting(), setFilter() +*/ + +QStringList QDir::entryList( int filterSpec, int sortSpec ) const +{ + if ( !dirty && filterSpec == (int)DefaultFilter && + sortSpec == (int)DefaultSort ) + return *fList; + return entryList( nameFilt, filterSpec, sortSpec ); +} + +/*! + Returns a list of the names of all the files and directories in + the directory, ordered in accordance with setSorting() and + filtered in accordance with setFilter() and setNameFilter(). + + The filter and sorting specifications can be overridden using the + \a nameFilter, \a filterSpec and \a sortSpec arguments. + + Returns an empty list if the directory is unreadable or does not + exist. + + \sa entryInfoList(), setNameFilter(), setSorting(), setFilter() +*/ + +QStringList QDir::entryList( const QString &nameFilter, + int filterSpec, int sortSpec ) const +{ + if ( filterSpec == (int)DefaultFilter ) + filterSpec = filtS; + if ( sortSpec == (int)DefaultSort ) + sortSpec = sortS; + QDir *that = (QDir*)this; // mutable function + if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) { + if ( that->fList ) + return *that->fList; + } + return QStringList(); +} + +/*! + \overload + + Returns a list of QFileInfo objects for all the files and + directories in the directory, ordered in accordance with + setSorting() and filtered in accordance with setFilter() and + setNameFilter(). + + The filter and sorting specifications can be overridden using the + \a filterSpec and \a sortSpec arguments. + + Returns 0 if the directory is unreadable or does not exist. + + The returned pointer is a const pointer to a QFileInfoList. The + list is owned by the QDir object and will be reused on the next + call to entryInfoList() for the same QDir instance. If you want to + keep the entries of the list after a subsequent call to this + function you must copy them. + + \sa entryList(), setNameFilter(), setSorting(), setFilter() +*/ + +const QFileInfoList *QDir::entryInfoList( int filterSpec, int sortSpec ) const +{ + if ( !dirty && filterSpec == (int)DefaultFilter && + sortSpec == (int)DefaultSort ) + return fiList; + return entryInfoList( nameFilt, filterSpec, sortSpec ); +} + +/*! + Returns a list of QFileInfo objects for all the files and + directories in the directory, ordered in accordance with + setSorting() and filtered in accordance with setFilter() and + setNameFilter(). + + The filter and sorting specifications can be overridden using the + \a nameFilter, \a filterSpec and \a sortSpec arguments. + + Returns 0 if the directory is unreadable or does not exist. + + The returned pointer is a const pointer to a QFileInfoList. The + list is owned by the QDir object and will be reused on the next + call to entryInfoList() for the same QDir instance. If you want to + keep the entries of the list after a subsequent call to this + function you must copy them. + + \sa entryList(), setNameFilter(), setSorting(), setFilter() +*/ + +const QFileInfoList *QDir::entryInfoList( const QString &nameFilter, + int filterSpec, int sortSpec ) const +{ + if ( filterSpec == (int)DefaultFilter ) + filterSpec = filtS; + if ( sortSpec == (int)DefaultSort ) + sortSpec = sortS; + QDir *that = (QDir*)this; // mutable function + if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) + return that->fiList; + else + return 0; +} + +/*! + \overload + + Returns TRUE if the \e directory exists; otherwise returns FALSE. + (If a file with the same name is found this function will return + FALSE). + + \sa QFileInfo::exists(), QFile::exists() +*/ + +bool QDir::exists() const +{ + QFileInfo fi( dPath ); + return fi.exists() && fi.isDir(); +} + +/*! + Returns TRUE if the directory path is relative to the current + directory and returns FALSE if the path is absolute (e.g. under + UNIX a path is relative if it does not start with a "/"). + + \sa convertToAbs() +*/ + +bool QDir::isRelative() const +{ + return isRelativePath( dPath ); +} + +/*! + Converts the directory path to an absolute path. If it is already + absolute nothing is done. + + \sa isRelative() +*/ + +void QDir::convertToAbs() +{ + dPath = absPath(); +} + +/*! + Makes a copy of QDir \a d and assigns it to this QDir. +*/ + +QDir &QDir::operator=( const QDir &d ) +{ + dPath = d.dPath; + delete fList; + fList = 0; + delete fiList; + fiList = 0; + nameFilt = d.nameFilt; + dirty = TRUE; + allDirs = d.allDirs; + filtS = d.filtS; + sortS = d.sortS; + return *this; +} + +/*! + \overload + + Sets the directory path to be the given \a path. +*/ + +QDir &QDir::operator=( const QString &path ) +{ + dPath = cleanDirPath( path ); + dirty = TRUE; + return *this; +} + + +/*! + \fn bool QDir::operator!=( const QDir &d ) const + + Returns TRUE if directory \a d and this directory have different + paths or different sort or filter settings; otherwise returns + FALSE. + + Example: + \code + // The current directory is "/usr/local" + QDir d1( "/usr/local/bin" ); + QDir d2( "bin" ); + if ( d1 != d2 ) qDebug( "They differ\n" ); // This is printed + \endcode +*/ + +/*! + Returns TRUE if directory \a d and this directory have the same + path and their sort and filter settings are the same; otherwise + returns FALSE. + + Example: + \code + // The current directory is "/usr/local" + QDir d1( "/usr/local/bin" ); + QDir d2( "bin" ); + d2.convertToAbs(); + if ( d1 == d2 ) qDebug( "They're the same\n" ); // This is printed + \endcode +*/ + +bool QDir::operator==( const QDir &d ) const +{ + return dPath == d.dPath && + nameFilt == d.nameFilt && + allDirs == d.allDirs && + filtS == d.filtS && + sortS == d.sortS; +} + + +/*! + Removes the file, \a fileName. + + If \a acceptAbsPath is TRUE a path starting with separator "/" + will remove the file with the absolute path. If \a acceptAbsPath + is FALSE any number of separators at the beginning of \a fileName + will be removed and the resultant file name will be removed. + + Returns TRUE if the file is removed successfully; otherwise + returns FALSE. +*/ + +bool QDir::remove( const QString &fileName, bool acceptAbsPath ) +{ + if ( fileName.isEmpty() ) { +#if defined(QT_CHECK_NULL) + qWarning( "QDir::remove: Empty or null file name" ); +#endif + return FALSE; + } + QString p = filePath( fileName, acceptAbsPath ); + return QFile::remove( p ); +} + +/*! + Checks for the existence of the file \a name. + + If \a acceptAbsPath is TRUE a path starting with separator "/" + will check the file with the absolute path. If \a acceptAbsPath is + FALSE any number of separators at the beginning of \a name will be + removed and the resultant file name will be checked. + + Returns TRUE if the file exists; otherwise returns FALSE. + + \sa QFileInfo::exists(), QFile::exists() +*/ + +bool QDir::exists( const QString &name, bool acceptAbsPath ) //### const in 4.0 +{ + if ( name.isEmpty() ) { +#if defined(QT_CHECK_NULL) + qWarning( "QDir::exists: Empty or null file name" ); +#endif + return FALSE; + } + QString tmp = filePath( name, acceptAbsPath ); + return QFile::exists( tmp ); +} + +/*! + Returns the native directory separator; "/" under UNIX (including + Mac OS X) and "\" under Windows. + + You do not need to use this function to build file paths. If you + always use "/", Qt will translate your paths to conform to the + underlying operating system. +*/ + +char QDir::separator() +{ +#if defined(Q_OS_UNIX) + return '/'; +#elif defined (Q_FS_FAT) || defined(Q_WS_WIN) + return '\\'; +#elif defined (Q_OS_MAC) + return ':'; +#else + return '/'; +#endif +} + +/*! + Returns the application's current directory. + + Use path() to access a QDir object's path. + + \sa currentDirPath(), QDir::QDir() +*/ + +QDir QDir::current() +{ + return QDir( currentDirPath() ); +} + +/*! + Returns the home directory. + + Under Windows the \c HOME environment variable is used. If this + does not exist the \c USERPROFILE environment variable is used. If + that does not exist the path is formed by concatenating the \c + HOMEDRIVE and \c HOMEPATH environment variables. If they don't + exist the rootDirPath() is used (this uses the \c SystemDrive + environment variable). If none of these exist "C:\" is used. + + Under non-Windows operating systems the \c HOME environment + variable is used if it exists, otherwise rootDirPath() is used. + + \sa homeDirPath() +*/ + +QDir QDir::home() +{ + return QDir( homeDirPath() ); +} + +/*! + Returns the root directory. + + \sa rootDirPath() drives() +*/ + +QDir QDir::root() +{ + return QDir( rootDirPath() ); +} + +/*! + \fn QString QDir::homeDirPath() + + Returns the absolute path of the user's home directory. + + \sa home() +*/ + +QStringList qt_makeFilterList( const QString &filter ) +{ + if ( filter.isEmpty() ) + return QStringList(); + + QChar sep( ';' ); + int i = filter.find( sep, 0 ); + if ( i == -1 && filter.find( ' ', 0 ) != -1 ) + sep = QChar( ' ' ); + + QStringList list = QStringList::split( sep, filter ); + QStringList::Iterator it = list.begin(); + QStringList list2; + + for ( ; it != list.end(); ++it ) { + QString s = *it; + list2 << s.stripWhiteSpace(); + } + return list2; +} + +/*! + \overload + + Returns TRUE if the \a fileName matches any of the wildcard (glob) + patterns in the list of \a filters; otherwise returns FALSE. + + (See \link qregexp.html#wildcard-matching QRegExp wildcard + matching.\endlink) + \sa QRegExp::match() +*/ + +bool QDir::match( const QStringList &filters, const QString &fileName ) +{ + QStringList::ConstIterator sit = filters.begin(); + while ( sit != filters.end() ) { +#if defined(Q_FS_FAT) && !defined(Q_OS_UNIX) + QRegExp rx( *sit, FALSE, TRUE ); // The FAT FS is not case sensitive.. +#else + QRegExp rx( *sit, TRUE, TRUE ); // ..while others are. +#endif + if ( rx.exactMatch(fileName) ) + return TRUE; + ++sit; + } + return FALSE; +} + +/*! + Returns TRUE if the \a fileName matches the wildcard (glob) + pattern \a filter; otherwise returns FALSE. The \a filter may + contain multiple patterns separated by spaces or semicolons. + + (See \link qregexp.html#wildcard-matching QRegExp wildcard + matching.\endlink) + \sa QRegExp::match() +*/ + +bool QDir::match( const QString &filter, const QString &fileName ) +{ + QStringList lst = qt_makeFilterList( filter ); + return match( lst, fileName ); +} + + +/*! + Removes all multiple directory separators "/" and resolves any + "."s or ".."s found in the path, \a filePath. + + Symbolic links are kept. This function does not return the + canonical path, but rather the simplest version of the input. + For example, "./local" becomes "local", "local/../bin" becomes + "bin" and "/local/usr/../bin" becomes "/local/bin". + + \sa absPath() canonicalPath() +*/ + +QString QDir::cleanDirPath( const QString &filePath ) +{ + QString name = filePath; + QString newPath; + + if ( name.isEmpty() ) + return name; + + slashify( name ); + + bool addedSeparator; + if ( isRelativePath(name) ) { + addedSeparator = TRUE; + name.insert( 0, '/' ); + } else { + addedSeparator = FALSE; + } + + int ePos, pos, upLevel; + + pos = ePos = name.length(); + upLevel = 0; + int len; + + while ( pos && (pos = name.findRev('/',--pos)) != -1 ) { + len = ePos - pos - 1; + if ( len == 2 && name.at(pos + 1) == '.' + && name.at(pos + 2) == '.' ) { + upLevel++; + } else { + if ( len != 0 && (len != 1 || name.at(pos + 1) != '.') ) { + if ( !upLevel ) + newPath = QString::fromLatin1("/") + + name.mid(pos + 1, len) + newPath; + else + upLevel--; + } + } + ePos = pos; + } + if ( addedSeparator ) { + while ( upLevel-- ) + newPath.insert( 0, QString::fromLatin1("/..") ); + if ( !newPath.isEmpty() ) + newPath.remove( 0, 1 ); + else + newPath = QString::fromLatin1("."); + } else { + if ( newPath.isEmpty() ) + newPath = QString::fromLatin1("/"); +#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) + if ( name[0] == '/' ) { + if ( name[1] == '/' ) // "\\machine\x\ ..." + newPath.insert( 0, '/' ); + } else { + newPath = name.left(2) + newPath; + } +#endif + } + return newPath; +} + +int qt_cmp_si_sortSpec; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +#ifdef Q_OS_TEMP +int __cdecl qt_cmp_si( const void *n1, const void *n2 ) +#else +int qt_cmp_si( const void *n1, const void *n2 ) +#endif +{ + if ( !n1 || !n2 ) + return 0; + + QDirSortItem* f1 = (QDirSortItem*)n1; + QDirSortItem* f2 = (QDirSortItem*)n2; + + if ( qt_cmp_si_sortSpec & QDir::DirsFirst ) + if ( f1->item->isDir() != f2->item->isDir() ) + return f1->item->isDir() ? -1 : 1; + + int r = 0; + int sortBy = qt_cmp_si_sortSpec & QDir::SortByMask; + + switch ( sortBy ) { + case QDir::Time: + r = f1->item->lastModified().secsTo(f2->item->lastModified()); + break; + case QDir::Size: + r = f2->item->size() - f1->item->size(); + break; + default: + ; + } + + if ( r == 0 && sortBy != QDir::Unsorted ) { + // Still not sorted - sort by name + bool ic = qt_cmp_si_sortSpec & QDir::IgnoreCase; + + if ( f1->filename_cache.isNull() ) + f1->filename_cache = ic ? f1->item->fileName().lower() + : f1->item->fileName(); + if ( f2->filename_cache.isNull() ) + f2->filename_cache = ic ? f2->item->fileName().lower() + : f2->item->fileName(); + + r = f1->filename_cache.compare(f2->filename_cache); + } + + if ( r == 0 ) { + // Enforce an order - the order the items appear in the array + r = (char*)n1 - (char*)n2; + } + + if ( qt_cmp_si_sortSpec & QDir::Reversed ) + return -r; + else + return r; +} + +#if defined(Q_C_CALLBACKS) +} +#endif + +#endif // QT_NO_DIR diff --git a/qmake/tools/qdir_unix.cpp b/qmake/tools/qdir_unix.cpp new file mode 100644 index 0000000..57fe3c5 --- a/dev/null +++ b/qmake/tools/qdir_unix.cpp @@ -0,0 +1,291 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QDir class +** +** Created : 950628 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance +** with the Qt Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" +#include "qdir.h" + +#ifndef QT_NO_DIR + +#include "qdir_p.h" +#include "qfileinfo.h" +#include "qregexp.h" +#include "qstringlist.h" + +#ifdef QT_THREAD_SUPPORT +# include <private/qmutexpool_p.h> +#endif // QT_THREAD_SUPPORT + +#include <stdlib.h> +#include <limits.h> + + +void QDir::slashify( QString& ) +{ +} + +QString QDir::homeDirPath() +{ + QString d; + d = QFile::decodeName(getenv("HOME")); + slashify( d ); + if ( d.isNull() ) + d = rootDirPath(); + return d; +} + +QString QDir::canonicalPath() const +{ + QString r; + + char cur[PATH_MAX+1]; + if ( ::getcwd( cur, PATH_MAX ) ) + if ( ::chdir(QFile::encodeName(dPath)) >= 0 ) { + char tmp[PATH_MAX+1]; + if ( ::getcwd( tmp, PATH_MAX ) ) + r = QFile::decodeName(tmp); + ::chdir( cur ); + } + + slashify( r ); + return r; +} + +bool QDir::mkdir( const QString &dirName, bool acceptAbsPath ) const +{ +#if defined(Q_OS_MACX) // Mac X doesn't support trailing /'s + QString name = dirName; + if (dirName[dirName.length() - 1] == "/") + name = dirName.left( dirName.length() - 1 ); + return ::mkdir( QFile::encodeName(filePath(name,acceptAbsPath)), 0777 ) + == 0; +#else + return ::mkdir( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ) + == 0; +#endif +} + +bool QDir::rmdir( const QString &dirName, bool acceptAbsPath ) const +{ + return ::rmdir( QFile::encodeName(filePath(dirName,acceptAbsPath)) ) == 0; +} + +bool QDir::isReadable() const +{ + return ::access( QFile::encodeName(dPath), R_OK | X_OK ) == 0; +} + +bool QDir::isRoot() const +{ + return dPath == QString::fromLatin1("/"); +} + +bool QDir::rename( const QString &name, const QString &newName, + bool acceptAbsPaths ) +{ + if ( name.isEmpty() || newName.isEmpty() ) { +#if defined(QT_CHECK_NULL) + qWarning( "QDir::rename: Empty or null file name(s)" ); +#endif + return FALSE; + } + QString fn1 = filePath( name, acceptAbsPaths ); + QString fn2 = filePath( newName, acceptAbsPaths ); + return ::rename( QFile::encodeName(fn1), + QFile::encodeName(fn2) ) == 0; +} + +bool QDir::setCurrent( const QString &path ) +{ + int r; + r = ::chdir( QFile::encodeName(path) ); + return r >= 0; +} + +QString QDir::currentDirPath() +{ + QString result; + + struct stat st; + if ( ::stat( ".", &st ) == 0 ) { + char currentName[PATH_MAX+1]; + if ( ::getcwd( currentName, PATH_MAX ) ) + result = QFile::decodeName(currentName); +#if defined(QT_DEBUG) + if ( result.isNull() ) + qWarning( "QDir::currentDirPath: getcwd() failed" ); +#endif + } else { +#if defined(QT_DEBUG) + qWarning( "QDir::currentDirPath: stat(\".\") failed" ); +#endif + } + slashify( result ); + return result; +} + +QString QDir::rootDirPath() +{ + QString d = QString::fromLatin1( "/" ); + return d; +} + +bool QDir::isRelativePath( const QString &path ) +{ + int len = path.length(); + if ( len == 0 ) + return TRUE; + return path[0] != '/'; +} + +bool QDir::readDirEntries( const QString &nameFilter, + int filterSpec, int sortSpec ) +{ + int i; + if ( !fList ) { + fList = new QStringList; + Q_CHECK_PTR( fList ); + fiList = new QFileInfoList; + Q_CHECK_PTR( fiList ); + fiList->setAutoDelete( TRUE ); + } else { + fList->clear(); + fiList->clear(); + } + + QStringList filters = qt_makeFilterList( nameFilter ); + + bool doDirs = (filterSpec & Dirs) != 0; + bool doFiles = (filterSpec & Files) != 0; + bool noSymLinks = (filterSpec & NoSymLinks) != 0; + bool doReadable = (filterSpec & Readable) != 0; + bool doWritable = (filterSpec & Writable) != 0; + bool doExecable = (filterSpec & Executable) != 0; + bool doHidden = (filterSpec & Hidden) != 0; + bool doSystem = (filterSpec & System) != 0; + +#if defined(Q_OS_OS2EMX) + //QRegExp wc( nameFilter, FALSE, TRUE ); // wild card, case insensitive +#else + //QRegExp wc( nameFilter, TRUE, TRUE ); // wild card, case sensitive +#endif + QFileInfo fi; + DIR *dir; + dirent *file; + + dir = opendir( QFile::encodeName(dPath) ); + if ( !dir ) + return FALSE; // cannot read the directory + + while ( (file = readdir(dir)) ) { + QString fn = QFile::decodeName(file->d_name); + fi.setFile( *this, fn ); + if ( !match( filters, fn ) && !(allDirs && fi.isDir()) ) + continue; + if ( (doDirs && fi.isDir()) || (doFiles && fi.isFile()) || + (doSystem && (!fi.isFile() && !fi.isDir())) ) { + if ( noSymLinks && fi.isSymLink() ) + continue; + if ( (filterSpec & RWEMask) != 0 ) + if ( (doReadable && !fi.isReadable()) || + (doWritable && !fi.isWritable()) || + (doExecable && !fi.isExecutable()) ) + continue; + if ( !doHidden && fn[0] == '.' && + fn != QString::fromLatin1(".") + && fn != QString::fromLatin1("..") ) + continue; + fiList->append( new QFileInfo( fi ) ); + } + } + if ( closedir(dir) != 0 ) { +#if defined(QT_CHECK_NULL) + qWarning( "QDir::readDirEntries: Cannot close the directory: %s", + dPath.local8Bit().data() ); +#endif + } + + // Sort... + if(fiList->count()) { + QDirSortItem* si= new QDirSortItem[fiList->count()]; + QFileInfo* itm; + i=0; + for (itm = fiList->first(); itm; itm = fiList->next()) + si[i++].item = itm; + qt_cmp_si_sortSpec = sortSpec; + qsort( si, i, sizeof(si[0]), qt_cmp_si ); + // put them back in the list + fiList->setAutoDelete( FALSE ); + fiList->clear(); + int j; + for ( j=0; j<i; j++ ) { + fiList->append( si[j].item ); + fList->append( si[j].item->fileName() ); + } + delete [] si; + fiList->setAutoDelete( TRUE ); + } + + if ( filterSpec == (FilterSpec)filtS && sortSpec == (SortSpec)sortS && + nameFilter == nameFilt ) + dirty = FALSE; + else + dirty = TRUE; + return TRUE; +} + +const QFileInfoList * QDir::drives() +{ + // at most one instance of QFileInfoList is leaked, and this variable + // points to that list + static QFileInfoList * knownMemoryLeak = 0; + + if ( !knownMemoryLeak ) { + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &knownMemoryLeak ) ); +#endif // QT_THREAD_SUPPORT + + if ( !knownMemoryLeak ) { + knownMemoryLeak = new QFileInfoList; + // non-win32 versions both use just one root directory + knownMemoryLeak->append( new QFileInfo( rootDirPath() ) ); + } + } + + return knownMemoryLeak; +} +#endif //QT_NO_DIR diff --git a/qmake/tools/qfile.cpp b/qmake/tools/qfile.cpp new file mode 100644 index 0000000..a578b49 --- a/dev/null +++ b/qmake/tools/qfile.cpp @@ -0,0 +1,614 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QFile class +** +** Created : 930812 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +// POSIX Large File Support redefines open -> open64 +#if defined(open) +# undef open +#endif + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#include "qfile.h" + + +extern bool qt_file_access( const QString& fn, int t ); + +/*! + \class QFile qfile.h + \reentrant + \brief The QFile class is an I/O device that operates on files. + + \ingroup io + \mainclass + + QFile is an I/O device for reading and writing binary and text + files. A QFile may be used by itself or more conveniently with a + QDataStream or QTextStream. + + The file name is usually passed in the constructor but can be + changed with setName(). You can check for a file's existence with + exists() and remove a file with remove(). + + The file is opened with open(), closed with close() and flushed + with flush(). Data is usually read and written using QDataStream + or QTextStream, but you can read with readBlock() and readLine() + and write with writeBlock(). QFile also supports getch(), + ungetch() and putch(). + + The size of the file is returned by size(). You can get the + current file position or move to a new file position using the + at() functions. If you've reached the end of the file, atEnd() + returns TRUE. The file handle is returned by handle(). + + Here is a code fragment that uses QTextStream to read a text file + line by line. It prints each line with a line number. + \code + QStringList lines; + QFile file( "file.txt" ); + if ( file.open( IO_ReadOnly ) ) { + QTextStream stream( &file ); + QString line; + int i = 1; + while ( !stream.eof() ) { + line = stream.readLine(); // line of text excluding '\n' + printf( "%3d: %s\n", i++, line.latin1() ); + lines += line; + } + file.close(); + } + \endcode + + Writing text is just as easy. The following example shows how to + write the data we read into the string list from the previous + example: + \code + QFile file( "file.txt" ); + if ( file.open( IO_WriteOnly ) ) { + QTextStream stream( &file ); + for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) + stream << *it << "\n"; + file.close(); + } + \endcode + + The QFileInfo class holds detailed information about a file, such + as access permissions, file dates and file types. + + The QDir class manages directories and lists of file names. + + Qt uses Unicode file names. If you want to do your own I/O on Unix + systems you may want to use encodeName() (and decodeName()) to + convert the file name into the local encoding. + + \important readAll() + + \sa QDataStream, QTextStream +*/ + +/*! + \fn Q_LONG QFile::writeBlock( const QByteArray& data ) + + \overload +*/ + + +/*! + Constructs a QFile with no name. +*/ + +QFile::QFile() +{ + init(); +} + +/*! + Constructs a QFile with a file name \a name. + + \sa setName() +*/ + +QFile::QFile( const QString &name ) + : fn(name) +{ + init(); +} + + +/*! + Destroys a QFile. Calls close(). +*/ + +QFile::~QFile() +{ + close(); +} + + +/*! + \internal + Initialize internal data. +*/ + +void QFile::init() +{ + setFlags( IO_Direct ); + setStatus( IO_Ok ); + fh = 0; + fd = 0; + length = 0; + ioIndex = 0; + ext_f = FALSE; // not an external file handle +} + + +/*! + \fn QString QFile::name() const + + Returns the name set by setName(). + + \sa setName(), QFileInfo::fileName() +*/ + +/*! + Sets the name of the file to \a name. The name can have no path, a + relative path or an absolute absolute path. + + Do not call this function if the file has already been opened. + + If the file name has no path or a relative path, the path used + will be whatever the application's current directory path is + \e{at the time of the open()} call. + + Example: + \code + QFile file; + QDir::setCurrent( "/tmp" ); + file.setName( "readme.txt" ); + QDir::setCurrent( "/home" ); + file.open( IO_ReadOnly ); // opens "/home/readme.txt" under Unix + \endcode + + Note that the directory separator "/" works for all operating + systems supported by Qt. + + \sa name(), QFileInfo, QDir +*/ + +void QFile::setName( const QString &name ) +{ + if ( isOpen() ) { +#if defined(QT_CHECK_STATE) + qWarning( "QFile::setName: File is open" ); +#endif + close(); + } + fn = name; +} + +/*! + \overload + + Returns TRUE if this file exists; otherwise returns FALSE. + + \sa name() +*/ + +bool QFile::exists() const +{ + return qt_file_access( fn, F_OK ); +} + +/*! + Returns TRUE if the file given by \a fileName exists; otherwise + returns FALSE. +*/ + +bool QFile::exists( const QString &fileName ) +{ + return qt_file_access( fileName, F_OK ); +} + + +/*! + Removes the file specified by the file name currently set. Returns + TRUE if successful; otherwise returns FALSE. + + The file is closed before it is removed. +*/ + +bool QFile::remove() +{ + close(); + return remove( fn ); +} + +#if defined(Q_OS_MAC) || defined(Q_OS_MSDOS) || defined(Q_OS_WIN32) || defined(Q_OS_OS2) +# define HAS_TEXT_FILEMODE // has translate/text filemode +#endif +#if defined(O_NONBLOCK) +# define HAS_ASYNC_FILEMODE +# define OPEN_ASYNC O_NONBLOCK +#elif defined(O_NDELAY) +# define HAS_ASYNC_FILEMODE +# define OPEN_ASYNC O_NDELAY +#endif + +/*! + Flushes the file buffer to the disk. + + close() also flushes the file buffer. +*/ + +void QFile::flush() +{ + if ( isOpen() && fh ) // can only flush open/buffered + fflush( fh ); // file +} + +/*! \reimp + \fn QIODevice::Offset QFile::at() const +*/ + +/*! + Returns TRUE if the end of file has been reached; otherwise returns FALSE. + + \sa size() +*/ + +bool QFile::atEnd() const +{ + if ( !isOpen() ) { +#if defined(QT_CHECK_STATE) + qWarning( "QFile::atEnd: File is not open" ); +#endif + return FALSE; + } + if ( isDirectAccess() && !isTranslated() ) { + if ( at() < length ) + return FALSE; + } + return QIODevice::atEnd(); +} + +/*! + Reads a line of text. + + Reads bytes from the file into the char* \a p, until end-of-line + or \a maxlen bytes have been read, whichever occurs first. Returns + the number of bytes read, or -1 if there was an error. Any + terminating newline is not stripped. + + This function is only efficient for buffered files. Avoid + readLine() for files that have been opened with the \c IO_Raw + flag. + + \sa readBlock(), QTextStream::readLine() +*/ + +Q_LONG QFile::readLine( char *p, Q_ULONG maxlen ) +{ + if ( maxlen == 0 ) // application bug? + return 0; +#if defined(QT_CHECK_STATE) + Q_CHECK_PTR( p ); + if ( !isOpen() ) { // file not open + qWarning( "QFile::readLine: File not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QFile::readLine: Read operation not permitted" ); + return -1; + } +#endif + Q_LONG nread; // number of bytes read + if ( isRaw() ) { // raw file + nread = QIODevice::readLine( p, maxlen ); + } else { // buffered file + p = fgets( p, maxlen, fh ); + if ( p ) { + nread = qstrlen( p ); + if ( !isSequentialAccess() ) + ioIndex += nread; + } else { + nread = -1; + setStatus(IO_ReadError); + } + } + return nread; +} + + +/*! + \overload + + Reads a line of text. + + Reads bytes from the file into string \a s, until end-of-line or + \a maxlen bytes have been read, whichever occurs first. Returns + the number of bytes read, or -1 if there was an error, e.g. end of + file. Any terminating newline is not stripped. + + This function is only efficient for buffered files. Avoid using + readLine() for files that have been opened with the \c IO_Raw + flag. + + Note that the string is read as plain Latin1 bytes, not Unicode. + + \sa readBlock(), QTextStream::readLine() +*/ + +Q_LONG QFile::readLine( QString& s, Q_ULONG maxlen ) +{ + QByteArray ba(maxlen); + Q_LONG l = readLine(ba.data(),maxlen); + if ( l >= 0 ) { + ba.truncate(l); + s = QString(ba); + } + return l; +} + + +/*! + Reads a single byte/character from the file. + + Returns the byte/character read, or -1 if the end of the file has + been reached. + + \sa putch(), ungetch() +*/ + +int QFile::getch() +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::getch: File not open" ); + return EOF; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QFile::getch: Read operation not permitted" ); + return EOF; + } +#endif + + int ch; + + if ( !ungetchBuffer.isEmpty() ) { + int len = ungetchBuffer.length(); + ch = ungetchBuffer[ len-1 ]; + ungetchBuffer.truncate( len - 1 ); + return ch; + } + + if ( isRaw() ) { // raw file (inefficient) + char buf[1]; + ch = readBlock( buf, 1 ) == 1 ? buf[0] : EOF; + } else { // buffered file + if ( (ch = getc( fh )) != EOF ) + if ( !isSequentialAccess() ) + ioIndex++; + else + setStatus(IO_ReadError); + } + return ch; +} + +/*! + Writes the character \a ch to the file. + + Returns \a ch, or -1 if some error occurred. + + \sa getch(), ungetch() +*/ + +int QFile::putch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::putch: File not open" ); + return EOF; + } + if ( !isWritable() ) { // writing not permitted + qWarning( "QFile::putch: Write operation not permitted" ); + return EOF; + } +#endif + if ( isRaw() ) { // raw file (inefficient) + char buf[1]; + buf[0] = ch; + ch = writeBlock( buf, 1 ) == 1 ? ch : EOF; + } else { // buffered file + if ( (ch = putc( ch, fh )) != EOF ) { + if ( !isSequentialAccess() ) + ioIndex++; + if ( ioIndex > length ) // update file length + length = ioIndex; + } else { + setStatus(IO_WriteError); + } + } + return ch; +} + +/*! + Puts the character \a ch back into the file and decrements the + index if it is not zero. + + This function is normally called to "undo" a getch() operation. + + Returns \a ch, or -1 if an error occurred. + + \sa getch(), putch() +*/ + +int QFile::ungetch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::ungetch: File not open" ); + return EOF; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QFile::ungetch: Read operation not permitted" ); + return EOF; + } +#endif + if ( ch == EOF ) // cannot unget EOF + return ch; + + if ( isSequentialAccess() && !fh) { + // pipe or similar => we cannot ungetch, so do it manually + ungetchBuffer +=ch; + return ch; + } + + if ( isRaw() ) { // raw file (very inefficient) + char buf[1]; + at( ioIndex-1 ); + buf[0] = ch; + if ( writeBlock(buf, 1) == 1 ) + at ( ioIndex-1 ); + else + ch = EOF; + } else { // buffered file + if ( (ch = ungetc(ch, fh)) != EOF ) + if ( !isSequentialAccess() ) + ioIndex--; + else + setStatus( IO_ReadError ); + } + return ch; +} + + +static QCString locale_encoder( const QString &fileName ) +{ + return fileName.local8Bit(); +} + + +static QFile::EncoderFn encoder = locale_encoder; + +/*! + When you use QFile, QFileInfo, and QDir to access the file system + with Qt, you can use Unicode file names. On Unix, these file names + are converted to an 8-bit encoding. If you want to do your own + file I/O on Unix, you should convert the file name using this + function. On Windows NT/2000, Unicode file names are supported + directly in the file system and this function should be avoided. + On Windows 95, non-Latin1 locales are not supported. + + By default, this function converts \a fileName to the local 8-bit + encoding determined by the user's locale. This is sufficient for + file names that the user chooses. File names hard-coded into the + application should only use 7-bit ASCII filename characters. + + The conversion scheme can be changed using setEncodingFunction(). + This might be useful if you wish to give the user an option to + store file names in UTF-8, etc., but be aware that such file names + would probably then be unrecognizable when seen by other programs. + + \sa decodeName() +*/ + +QCString QFile::encodeName( const QString &fileName ) +{ + return (*encoder)(fileName); +} + +/*! + \enum QFile::EncoderFn + + This is used by QFile::setEncodingFunction(). +*/ + +/*! + \nonreentrant + + Sets the function for encoding Unicode file names to \a f. The + default encodes in the locale-specific 8-bit encoding. + + \sa encodeName() +*/ +void QFile::setEncodingFunction( EncoderFn f ) +{ + encoder = f; +} + +static +QString locale_decoder( const QCString &localFileName ) +{ + return QString::fromLocal8Bit(localFileName); +} + +static QFile::DecoderFn decoder = locale_decoder; + +/*! + This does the reverse of QFile::encodeName() using \a localFileName. + + \sa setDecodingFunction() +*/ +QString QFile::decodeName( const QCString &localFileName ) +{ + return (*decoder)(localFileName); +} + +/*! + \enum QFile::DecoderFn + + This is used by QFile::setDecodingFunction(). +*/ + +/*! + \nonreentrant + + Sets the function for decoding 8-bit file names to \a f. The + default uses the locale-specific 8-bit encoding. + + \sa encodeName(), decodeName() +*/ + +void QFile::setDecodingFunction( DecoderFn f ) +{ + decoder = f; +} + diff --git a/qmake/tools/qfile_unix.cpp b/qmake/tools/qfile_unix.cpp new file mode 100644 index 0000000..2d5a856 --- a/dev/null +++ b/qmake/tools/qfile_unix.cpp @@ -0,0 +1,687 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QFile class +** +** Created : 950628 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance +** with the Qt Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +// POSIX Large File Support redefines open -> open64 +static inline int qt_open(const char *pathname, int flags, mode_t mode) +{ return ::open(pathname, flags, mode); } +#if defined(open) +# undef open +#endif + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#include "qfile.h" +#include <errno.h> +#include <limits.h> + + +bool qt_file_access( const QString& fn, int t ) +{ + if ( fn.isEmpty() ) + return FALSE; + return ::access( QFile::encodeName(fn), t ) == 0; +} + +/*! + \overload + Removes the file \a fileName. + Returns TRUE if successful, otherwise FALSE. +*/ + +bool QFile::remove( const QString &fileName ) +{ + if ( fileName.isEmpty() ) { +#if defined(QT_CHECK_NULL) + qWarning( "QFile::remove: Empty or null file name" ); +#endif + return FALSE; + } + return unlink( QFile::encodeName(fileName) ) == 0; +} + +#if defined(O_NONBLOCK) +# define HAS_ASYNC_FILEMODE +# define OPEN_ASYNC O_NONBLOCK +#elif defined(O_NDELAY) +# define HAS_ASYNC_FILEMODE +# define OPEN_ASYNC O_NDELAY +#endif + +/*! + Opens the file specified by the file name currently set, using the + mode \a m. Returns TRUE if successful, otherwise FALSE. + + \keyword IO_Raw + \keyword IO_ReadOnly + \keyword IO_WriteOnly + \keyword IO_ReadWrite + \keyword IO_Append + \keyword IO_Truncate + \keyword IO_Translate + + The mode parameter \a m must be a combination of the following flags: + \table + \header \i Flag \i Meaning + \row \i IO_Raw + \i Raw (non-buffered) file access. + \row \i IO_ReadOnly + \i Opens the file in read-only mode. + \row \i IO_WriteOnly + \i Opens the file in write-only mode. If this flag is used + with another flag, e.g. \c IO_ReadOnly or \c IO_Raw or \c + IO_Append, the file is \e not truncated; but if used on + its own (or with \c IO_Truncate), the file is truncated. + \row \i IO_ReadWrite + \i Opens the file in read/write mode, equivalent to \c + (IO_ReadOnly | IO_WriteOnly). + \row \i IO_Append + \i Opens the file in append mode. (You must actually use \c + (IO_WriteOnly | IO_Append) to make the file writable and + to go into append mode.) This mode is very useful when you + want to write something to a log file. The file index is + set to the end of the file. Note that the result is + undefined if you position the file index manually using + at() in append mode. + \row \i IO_Truncate + \i Truncates the file. + \row \i IO_Translate + \i Enables carriage returns and linefeed translation for text + files under Windows. + \endtable + + The raw access mode is best when I/O is block-operated using a 4KB + block size or greater. Buffered access works better when reading + small portions of data at a time. + + \warning When working with buffered files, data may not be written + to the file at once. Call flush() to make sure that the data is + really written. + + \warning If you have a buffered file opened for both reading and + writing you must not perform an input operation immediately after + an output operation or vice versa. You should always call flush() + or a file positioning operation, e.g. at(), between input and + output operations, otherwise the buffer may contain garbage. + + If the file does not exist and \c IO_WriteOnly or \c IO_ReadWrite + is specified, it is created. + + Example: + \code + QFile f1( "/tmp/data.bin" ); + f1.open( IO_Raw | IO_ReadWrite ); + + QFile f2( "readme.txt" ); + f2.open( IO_ReadOnly | IO_Translate ); + + QFile f3( "audit.log" ); + f3.open( IO_WriteOnly | IO_Append ); + \endcode + + \sa name(), close(), isOpen(), flush() +*/ + +bool QFile::open( int m ) +{ + if ( isOpen() ) { // file already open +#if defined(QT_CHECK_STATE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + if ( fn.isNull() ) { // no file name defined +#if defined(QT_CHECK_NULL) + qWarning( "QFile::open: No file name specified" ); +#endif + return FALSE; + } + init(); // reset params + setMode( m ); + if ( !(isReadable() || isWritable()) ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QFile::open: File access not specified" ); +#endif + return FALSE; + } + bool ok = TRUE; + struct stat st; + if ( isRaw() ) { + int oflags = O_RDONLY; + if ( isReadable() && isWritable() ) + oflags = O_RDWR; + else if ( isWritable() ) + oflags = O_WRONLY; + if ( flags() & IO_Append ) { // append to end of file? + if ( flags() & IO_Truncate ) + oflags |= (O_CREAT | O_TRUNC); + else + oflags |= (O_APPEND | O_CREAT); + setFlags( flags() | IO_WriteOnly ); // append implies write + } else if ( isWritable() ) { // create/trunc if writable + if ( flags() & IO_Truncate ) + oflags |= (O_CREAT | O_TRUNC); + else + oflags |= O_CREAT; + } +#if defined(HAS_TEXT_FILEMODE) + if ( isTranslated() ) + oflags |= OPEN_TEXT; + else + oflags |= OPEN_BINARY; +#endif +#if defined(HAS_ASYNC_FILEMODE) + if ( isAsynchronous() ) + oflags |= OPEN_ASYNC; +#endif + fd = qt_open( QFile::encodeName(fn), oflags, 0666 ); + + if ( fd != -1 ) { // open successful + ::fstat( fd, &st ); // get the stat for later usage + } else { + ok = FALSE; + } + } else { // buffered file I/O + QCString perm; + char perm2[4]; + bool try_create = FALSE; + if ( flags() & IO_Append ) { // append to end of file? + setFlags( flags() | IO_WriteOnly ); // append implies write + perm = isReadable() ? "a+" : "a"; + } else { + if ( isReadWrite() ) { + if ( flags() & IO_Truncate ) { + perm = "w+"; + } else { + perm = "r+"; + try_create = TRUE; // try to create if not exists + } + } else if ( isReadable() ) { + perm = "r"; + } else if ( isWritable() ) { + perm = "w"; + } + } + qstrcpy( perm2, perm ); +#if defined(HAS_TEXT_FILEMODE) + if ( isTranslated() ) + strcat( perm2, "t" ); + else + strcat( perm2, "b" ); +#endif + for (;;) { // At most twice + + fh = fopen( QFile::encodeName(fn), perm2 ); + + if ( !fh && try_create ) { + perm2[0] = 'w'; // try "w+" instead of "r+" + try_create = FALSE; + } else { + break; + } + } + if ( fh ) { + ::fstat( fileno(fh), &st ); // get the stat for later usage + } else { + ok = FALSE; + } + } + if ( ok ) { + setState( IO_Open ); + // on successful open the file stat was got; now test what type + // of file we have + if ( (st.st_mode & S_IFMT) != S_IFREG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } else { + length = (Offset)st.st_size; + ioIndex = (flags() & IO_Append) == 0 ? 0 : length; + if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { + // try if you can read from it (if you can, it's a sequential + // device; e.g. a file in the /proc filesystem) + int c = getch(); + if ( c != -1 ) { + ungetch(c); + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } + } + } + } else { + init(); + if ( errno == EMFILE ) // no more file handles/descrs + setStatus( IO_ResourceError ); + else + setStatus( IO_OpenError ); + } + return ok; +} + +/*! + \overload + Opens a file in the mode \a m using an existing file handle \a f. + Returns TRUE if successful, otherwise FALSE. + + Example: + \code + #include <stdio.h> + + void printError( const char* msg ) + { + QFile f; + f.open( IO_WriteOnly, stderr ); + f.writeBlock( msg, qstrlen(msg) ); // write to stderr + f.close(); + } + \endcode + + When a QFile is opened using this function, close() does not actually + close the file, only flushes it. + + \warning If \a f is \c stdin, \c stdout, \c stderr, you may not + be able to seek. See QIODevice::isSequentialAccess() for more + information. + + \sa close() +*/ + +bool QFile::open( int m, FILE *f ) +{ + if ( isOpen() ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m &~IO_Raw ); + setState( IO_Open ); + fh = f; + ext_f = TRUE; + struct stat st; + ::fstat( fileno(fh), &st ); +#if defined(QT_LARGEFILE_SUPPORT) + ioIndex = (Offset)ftello( fh ); +#else + ioIndex = (Offset)ftell( fh ); +#endif + if ( (st.st_mode & S_IFMT) != S_IFREG || f == stdin ) { //stdin is non seekable + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } else { + length = (Offset)st.st_size; + if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { + // try if you can read from it (if you can, it's a sequential + // device; e.g. a file in the /proc filesystem) + int c = getch(); + if ( c != -1 ) { + ungetch(c); + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } + } + } + return TRUE; +} + +/*! + \overload + Opens a file in the mode \a m using an existing file descriptor \a f. + Returns TRUE if successful, otherwise FALSE. + + When a QFile is opened using this function, close() does not actually + close the file. + + The QFile that is opened using this function, is automatically set to be in + raw mode; this means that the file input/output functions are slow. If you + run into performance issues, you should try to use one of the other open + functions. + + \warning If \a f is one of 0 (stdin), 1 (stdout) or 2 (stderr), you may not + be able to seek. size() is set to \c INT_MAX (in limits.h). + + \sa close() +*/ + + +bool QFile::open( int m, int f ) +{ + if ( isOpen() ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m |IO_Raw ); + setState( IO_Open ); + fd = f; + ext_f = TRUE; + struct stat st; + ::fstat( fd, &st ); + ioIndex = (Offset)::lseek(fd, 0, SEEK_CUR); + if ( (st.st_mode & S_IFMT) != S_IFREG || f == 0 ) { // stdin is not seekable... + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } else { + length = (Offset)st.st_size; + if ( length == 0 && isReadable() ) { + // try if you can read from it (if you can, it's a sequential + // device; e.g. a file in the /proc filesystem) + int c = getch(); + if ( c != -1 ) { + ungetch(c); + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = 0; + } + resetStatus(); + } + } + return TRUE; +} + +/*! + Returns the file size. + \sa at() +*/ + +QIODevice::Offset QFile::size() const +{ + struct stat st; + if ( isOpen() ) { + ::fstat( fh ? fileno(fh) : fd, &st ); + } else { + ::stat( QFile::encodeName(fn), &st ); + } +#if defined(QT_LARGEFILE_SUPPORT) && !defined(QT_ABI_64BITOFFSET) + return (uint)st.st_size > UINT_MAX ? UINT_MAX : (QIODevice::Offset)st.st_size; +#else + return st.st_size; +#endif +} + + +/*! + \overload + + Sets the file index to \a pos. Returns TRUE if successful; + otherwise returns FALSE. + + Example: + \code + QFile f( "data.bin" ); + f.open( IO_ReadOnly ); // index set to 0 + f.at( 100 ); // set index to 100 + f.at( f.at()+50 ); // set index to 150 + f.at( f.size()-80 ); // set index to 80 before EOF + f.close(); + \endcode + + Use \c at() without arguments to retrieve the file offset. + + \warning The result is undefined if the file was open()'ed using + the \c IO_Append specifier. + + \sa size(), open() +*/ + +bool QFile::at( Offset pos ) +{ + if ( !isOpen() ) { +#if defined(QT_CHECK_STATE) + qWarning( "QFile::at: File is not open" ); +#endif + return FALSE; + } + if ( isSequentialAccess() ) + return FALSE; + bool ok; + if ( isRaw() ) { + off_t l = ::lseek( fd, pos, SEEK_SET ); + ok = ( l != -1 ); + pos = (Offset)l; + } else { // buffered file +#if defined(QT_LARGEFILE_SUPPORT) + ok = ( ::fseeko(fh, pos, SEEK_SET) == 0 ); +#else + ok = ( ::fseek(fh, pos, SEEK_SET) == 0 ); +#endif + } + if ( ok ) + ioIndex = pos; +#if defined(QT_CHECK_RANGE) + else +#if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) + qWarning( "QFile::at: Cannot set file position %llu", pos ); +#else + qWarning( "QFile::at: Cannot set file position %lu", pos ); +#endif +#endif + return ok; +} + +/*! + \reimp + + \warning We have experienced problems with some C libraries when a buffered + file is opened for both reading and writing. If a read operation takes place + immediately after a write operation, the read buffer contains garbage data. + Worse, the same garbage is written to the file. Calling flush() before + readBlock() solved this problem. +*/ + +Q_LONG QFile::readBlock( char *p, Q_ULONG len ) +{ +#if defined(QT_CHECK_NULL) + if ( !p ) + qWarning( "QFile::readBlock: Null pointer error" ); +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + qWarning( "QFile::readBlock: File not open" ); + return -1; + } + if ( !isReadable() ) { + qWarning( "QFile::readBlock: Read operation not permitted" ); + return -1; + } +#endif + Q_ULONG nread = 0; // number of bytes read + if ( !ungetchBuffer.isEmpty() ) { + // need to add these to the returned string. + uint l = ungetchBuffer.length(); + while( nread < l ) { + *p = ungetchBuffer[ l - nread - 1 ]; + p++; + nread++; + } + ungetchBuffer.truncate( l - nread ); + } + + if ( nread < len ) { + if ( isRaw() ) { // raw file + nread += ::read( fd, p, len-nread ); + if ( len && nread <= 0 ) { + nread = 0; + setStatus(IO_ReadError); + } + } else { // buffered file + nread += fread( p, 1, len-nread, fh ); + if ( (uint)nread != len ) { + if ( ferror( fh ) || nread==0 ) + setStatus(IO_ReadError); + } + } + } + if ( !isSequentialAccess() ) + ioIndex += nread; + return nread; +} + + +/*! \reimp + + Writes \a len bytes from \a p to the file and returns the number of + bytes actually written. + + Returns -1 if a serious error occurred. + + \warning When working with buffered files, data may not be written + to the file at once. Call flush() to make sure the data is really + written. + + \sa readBlock() +*/ + +Q_LONG QFile::writeBlock( const char *p, Q_ULONG len ) +{ +#if defined(QT_CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QFile::writeBlock: Null pointer error" ); +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::writeBlock: File not open" ); + return -1; + } + if ( !isWritable() ) { // writing not permitted + qWarning( "QFile::writeBlock: Write operation not permitted" ); + return -1; + } +#endif + Q_ULONG nwritten; // number of bytes written + if ( isRaw() ) // raw file + nwritten = ::write( fd, (void *)p, len ); + else // buffered file + nwritten = fwrite( p, 1, len, fh ); + if ( nwritten != len ) { // write error + if ( errno == ENOSPC ) // disk is full + setStatus( IO_ResourceError ); + else + setStatus( IO_WriteError ); + if ( !isSequentialAccess() ) { + if ( isRaw() ) // recalc file position + ioIndex = (Offset)::lseek( fd, 0, SEEK_CUR ); + else +#if defined(QT_LARGEFILE_SUPPORT) + ioIndex = (Offset)::fseeko( fh, 0, SEEK_CUR ); +#else + ioIndex = (Offset)::fseek( fh, 0, SEEK_CUR ); +#endif + } + } else { + if ( !isSequentialAccess() ) + ioIndex += nwritten; + } + if ( ioIndex > length ) // update file length + length = ioIndex; + return nwritten; +} + +/*! + Returns the file handle of the file. + + This is a small positive integer, suitable for use with C library + functions such as fdopen() and fcntl(), as well as with QSocketNotifier. + + If the file is not open or there is an error, handle() returns -1. + + \sa QSocketNotifier +*/ + +int QFile::handle() const +{ + if ( !isOpen() ) + return -1; + else if ( fh ) + return fileno( fh ); + else + return fd; +} + +/*! + Closes an open file. + + The file is not closed if it was opened with an existing file handle. + If the existing file handle is a \c FILE*, the file is flushed. + If the existing file handle is an \c int file descriptor, nothing + is done to the file. + + Some "write-behind" filesystems may report an unspecified error on + closing the file. These errors only indicate that something may + have gone wrong since the previous open(). In such a case status() + reports IO_UnspecifiedError after close(), otherwise IO_Ok. + + \sa open(), flush() +*/ + + +void QFile::close() +{ + bool ok = FALSE; + if ( isOpen() ) { // file is not open + if ( fh ) { // buffered file + if ( ext_f ) + ok = fflush( fh ) != -1; // flush instead of closing + else + ok = fclose( fh ) != -1; + } else { // raw file + if ( ext_f ) + ok = TRUE; // cannot close + else + ok = ::close( fd ) != -1; + } + init(); // restore internal state + } + if (!ok) + setStatus( IO_UnspecifiedError ); + + return; +} diff --git a/qmake/tools/qfileinfo.cpp b/qmake/tools/qfileinfo.cpp new file mode 100644 index 0000000..3af7932 --- a/dev/null +++ b/qmake/tools/qfileinfo.cpp @@ -0,0 +1,659 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QFileInfo class +** +** Created : 950628 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +#include "qfileinfo.h" +#include "qdatetime.h" +#include "qdir.h" +#include "qfiledefs_p.h" +#if defined(QT_LARGEFILE_SUPPORT) && !defined(QT_ABI_QT4) +#include <limits.h> +#endif + + +extern bool qt_file_access( const QString& fn, int t ); + +/*! + \class QFileInfo + \reentrant + \brief The QFileInfo class provides system-independent file information. + + \ingroup io + + QFileInfo provides information about a file's name and position + (path) in the file system, its access rights and whether it is a + directory or symbolic link, etc. The file's size and last + modified/read times are also available. + + A QFileInfo can point to a file with either a relative or an + absolute file path. Absolute file paths begin with the directory + separator "/" (or with a drive specification on Windows). Relative + file names begin with a directory name or a file name and specify + a path relative to the current working directory. An example of an + absolute path is the string "/tmp/quartz". A relative path might + look like "src/fatlib". You can use the function isRelative() to + check whether a QFileInfo is using a relative or an absolute file + path. You can call the function convertToAbs() to convert a + relative QFileInfo's path to an absolute path. + + The file that the QFileInfo works on is set in the constructor or + later with setFile(). Use exists() to see if the file exists and + size() to get its size. + + To speed up performance, QFileInfo caches information about the + file. Because files can be changed by other users or programs, or + even by other parts of the same program, there is a function that + refreshes the file information: refresh(). If you want to switch + off a QFileInfo's caching and force it to access the file system + every time you request information from it call setCaching(FALSE). + + The file's type is obtained with isFile(), isDir() and + isSymLink(). The readLink() function provides the name of the file + the symlink points to. + + Elements of the file's name can be extracted with dirPath() and + fileName(). The fileName()'s parts can be extracted with + baseName() and extension(). + + The file's dates are returned by created(), lastModified() and + lastRead(). Information about the file's access permissions is + obtained with isReadable(), isWritable() and isExecutable(). The + file's ownership is available from owner(), ownerId(), group() and + groupId(). You can examine a file's permissions and ownership in a + single statement using the permission() function. + + If you need to read and traverse directories, see the QDir class. +*/ + +/*! + \enum QFileInfo::PermissionSpec + + This enum is used by the permission() function to report the + permissions and ownership of a file. The values may be OR-ed + together to test multiple permissions and ownership values. + + \value ReadUser The file is readable by the user. + \value WriteUser The file is writable by the user. + \value ExeUser The file is executable by the user. + \value ReadGroup The file is readable by the group. + \value WriteGroup The file is writable by the group. + \value ExeGroup The file is executable by the group. + \value ReadOther The file is readable by anyone. + \value WriteOther The file is writable by anyone. + \value ExeOther The file is executable by anyone. +*/ + + +/*! + Constructs a new empty QFileInfo. +*/ + +QFileInfo::QFileInfo() +{ + fic = 0; + cache = TRUE; +#if defined(Q_OS_UNIX) + symLink = FALSE; +#endif +} + +/*! + Constructs a new QFileInfo that gives information about the given + file. The \a file can also include an absolute or relative path. + + \sa setFile(), isRelative(), QDir::setCurrent(), QDir::isRelativePath() +*/ + +QFileInfo::QFileInfo( const QString &file ) +{ + fn = file; + slashify( fn ); + fic = 0; + cache = TRUE; +#if defined(Q_OS_UNIX) + symLink = FALSE; +#endif +} + +/*! + Constructs a new QFileInfo that gives information about file \a + file. + + If the \a file has a relative path, the QFileInfo will also have a + relative path. + + \sa isRelative() +*/ + +QFileInfo::QFileInfo( const QFile &file ) +{ + fn = file.name(); + slashify( fn ); + fic = 0; + cache = TRUE; +#if defined(Q_OS_UNIX) + symLink = FALSE; +#endif +} + +/*! + Constructs a new QFileInfo that gives information about the file + called \a fileName in the directory \a d. + + If \a d has a relative path, the QFileInfo will also have a + relative path. + + \sa isRelative() +*/ +#ifndef QT_NO_DIR +QFileInfo::QFileInfo( const QDir &d, const QString &fileName ) +{ + fn = d.filePath( fileName ); + slashify( fn ); + fic = 0; + cache = TRUE; +#if defined(Q_OS_UNIX) + symLink = FALSE; +#endif +} +#endif +/*! + Constructs a new QFileInfo that is a copy of \a fi. +*/ + +QFileInfo::QFileInfo( const QFileInfo &fi ) +{ + fn = fi.fn; + if ( fi.fic ) { + fic = new QFileInfoCache; + *fic = *fi.fic; + } else { + fic = 0; + } + cache = fi.cache; +#if defined(Q_OS_UNIX) + symLink = fi.symLink; +#endif +} + +/*! + Destroys the QFileInfo and frees its resources. +*/ + +QFileInfo::~QFileInfo() +{ + delete fic; +} + + +/*! + Makes a copy of \a fi and assigns it to this QFileInfo. +*/ + +QFileInfo &QFileInfo::operator=( const QFileInfo &fi ) +{ + fn = fi.fn; + if ( !fi.fic ) { + delete fic; + fic = 0; + } else { + if ( !fic ) { + fic = new QFileInfoCache; + Q_CHECK_PTR( fic ); + } + *fic = *fi.fic; + } + cache = fi.cache; +#if defined(Q_OS_UNIX) + symLink = fi.symLink; +#endif + return *this; +} + + +/*! + Sets the file that the QFileInfo provides information about to \a + file. + + The \a file can also include an absolute or relative file path. + Absolute paths begin with the directory separator (e.g. "/" under + Unix) or a drive specification (under Windows). Relative file + names begin with a directory name or a file name and specify a + path relative to the current directory. + + Example: + \code + QString absolute = "/local/bin"; + QString relative = "local/bin"; + QFileInfo absFile( absolute ); + QFileInfo relFile( relative ); + + QDir::setCurrent( QDir::rootDirPath() ); + // absFile and relFile now point to the same file + + QDir::setCurrent( "/tmp" ); + // absFile now points to "/local/bin", + // while relFile points to "/tmp/local/bin" + \endcode + + \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath() +*/ + +void QFileInfo::setFile( const QString &file ) +{ + fn = file; + slashify( fn ); + delete fic; + fic = 0; +} + +/*! + \overload + + Sets the file that the QFileInfo provides information about to \a + file. + + If \a file includes a relative path, the QFileInfo will also have + a relative path. + + \sa isRelative() +*/ + +void QFileInfo::setFile( const QFile &file ) +{ + fn = file.name(); + slashify( fn ); + delete fic; + fic = 0; +} + +/*! + \overload + + Sets the file that the QFileInfo provides information about to \a + fileName in directory \a d. + + If \a fileName includes a relative path, the QFileInfo will also + have a relative path. + + \sa isRelative() +*/ +#ifndef QT_NO_DIR +void QFileInfo::setFile( const QDir &d, const QString &fileName ) +{ + fn = d.filePath( fileName ); + slashify( fn ); + delete fic; + fic = 0; +} +#endif + +/*! + Returns TRUE if the file exists; otherwise returns FALSE. +*/ + +bool QFileInfo::exists() const +{ + return qt_file_access( fn, F_OK ); +} + +/*! + Refreshes the information about the file, i.e. reads in information + from the file system the next time a cached property is fetched. + + \sa setCaching() +*/ + +void QFileInfo::refresh() const +{ + QFileInfo *that = (QFileInfo*)this; // Mutable function + delete that->fic; + that->fic = 0; +} + +/*! + \fn bool QFileInfo::caching() const + + Returns TRUE if caching is enabled; otherwise returns FALSE. + + \sa setCaching(), refresh() +*/ + +/*! + If \a enable is TRUE, enables caching of file information. If \a + enable is FALSE caching is disabled. + + When caching is enabled, QFileInfo reads the file information from + the file system the first time it's needed, but generally not + later. + + Caching is enabled by default. + + \sa refresh(), caching() +*/ + +void QFileInfo::setCaching( bool enable ) +{ + if ( cache == enable ) + return; + cache = enable; + if ( cache ) { + delete fic; + fic = 0; + } +} + + +/*! + Returns the file name, including the path (which may be absolute + or relative). + + \sa isRelative(), absFilePath() +*/ + +QString QFileInfo::filePath() const +{ + return fn; +} + +/*! + Returns the base name of the file. + + If \a complete is FALSE (the default) the base name consists of + all characters in the file name up to (but not including) the \e + first '.' character. + + If \a complete is TRUE the base name consists of all characters in + the file up to (but not including) the \e last '.' character. + + The path is not included in either case. + + Example: + \code + QFileInfo fi( "/tmp/archive.tar.gz" ); + QString base = fi.baseName(); // base = "archive" + base = fi.baseName( TRUE ); // base = "archive.tar" + \endcode + + \sa fileName(), extension() +*/ + +QString QFileInfo::baseName( bool complete ) const +{ + QString tmp = fileName(); + int pos = complete ? tmp.findRev( '.' ) : tmp.find( '.' ); + if ( pos == -1 ) + return tmp; + else + return tmp.left( pos ); +} + +/*! + Returns the file's extension name. + + If \a complete is TRUE (the default), extension() returns the + string of all characters in the file name after (but not + including) the first '.' character. + + If \a complete is FALSE, extension() returns the string of all + characters in the file name after (but not including) the last '.' + character. + + Example: + \code + QFileInfo fi( "/tmp/archive.tar.gz" ); + QString ext = fi.extension(); // ext = "tar.gz" + ext = fi.extension( FALSE ); // ext = "gz" + \endcode + + \sa fileName(), baseName() +*/ + +QString QFileInfo::extension( bool complete ) const +{ + QString s = fileName(); + int pos = complete ? s.find( '.' ) : s.findRev( '.' ); + if ( pos < 0 ) + return QString::fromLatin1( "" ); + else + return s.right( s.length() - pos - 1 ); +} + +/*! + Returns the file's path as a QDir object. + + If the QFileInfo is relative and \a absPath is FALSE, the QDir + will be relative; otherwise it will be absolute. + + \sa dirPath(), filePath(), fileName(), isRelative() +*/ +#ifndef QT_NO_DIR +QDir QFileInfo::dir( bool absPath ) const +{ + return QDir( dirPath(absPath) ); +} +#endif + + +/*! + Returns TRUE if the file is readable; otherwise returns FALSE. + + \sa isWritable(), isExecutable(), permission() +*/ + +bool QFileInfo::isReadable() const +{ + return qt_file_access( fn, R_OK ) && permission( ReadUser ); +} + +/*! + Returns TRUE if the file is writable; otherwise returns FALSE. + + \sa isReadable(), isExecutable(), permission() +*/ + +bool QFileInfo::isWritable() const +{ + return qt_file_access( fn, W_OK ) && permission( WriteUser ); +} + +/*! + Returns TRUE if the file is executable; otherwise returns FALSE. + + \sa isReadable(), isWritable(), permission() +*/ + +bool QFileInfo::isExecutable() const +{ + return qt_file_access( fn, X_OK ) && permission( ExeUser ); +} + +#ifndef Q_WS_WIN +bool QFileInfo::isHidden() const +{ + return fileName()[ 0 ] == QChar( '.' ); +} +#endif + +/*! + Returns TRUE if the file path name is relative. Returns FALSE if + the path is absolute (e.g. under Unix a path is absolute if it + begins with a "/"). +*/ +#ifndef QT_NO_DIR +bool QFileInfo::isRelative() const +{ + return QDir::isRelativePath( fn ); +} + +/*! + Converts the file's path to an absolute path. + + If it is already absolute, nothing is done. + + \sa filePath(), isRelative() +*/ + +bool QFileInfo::convertToAbs() +{ + if ( isRelative() ) + fn = absFilePath(); + return QDir::isRelativePath( fn ); +} +#endif + +/*! + Returns the file size in bytes, or 0 if the file does not exist or + if the size is 0 or if the size cannot be fetched. +*/ +#if defined(QT_ABI_QT4) +QIODevice::Offset QFileInfo::size() const +#else +uint QFileInfo::size() const +#endif +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) +#if defined(QT_ABI_QT4) + return (QIODevice::Offset)fic->st.st_size; +#elif defined(QT_LARGEFILE_SUPPORT) + return (uint)fic->st.st_size > UINT_MAX ? UINT_MAX : (uint)fic->st.st_size; +#else + return (uint)fic->st.st_size; +#endif + else + return 0; +} + +/*! + Returns the date and time when the file was created. + + On platforms where this information is not available, returns the + same as lastModified(). + + \sa created() lastModified() lastRead() +*/ + +QDateTime QFileInfo::created() const +{ + QDateTime dt; + if ( !fic || !cache ) + doStat(); + if ( fic && fic->st.st_ctime != 0 ) { + dt.setTime_t( fic->st.st_ctime ); + return dt; + } else { + return lastModified(); + } +} + +/*! + Returns the date and time when the file was last modified. + + \sa created() lastModified() lastRead() +*/ + +QDateTime QFileInfo::lastModified() const +{ + QDateTime dt; + if ( !fic || !cache ) + doStat(); + if ( fic ) + dt.setTime_t( fic->st.st_mtime ); + return dt; +} + +/*! + Returns the date and time when the file was last read (accessed). + + On platforms where this information is not available, returns the + same as lastModified(). + + \sa created() lastModified() lastRead() +*/ + +QDateTime QFileInfo::lastRead() const +{ + QDateTime dt; + if ( !fic || !cache ) + doStat(); + if ( fic && fic->st.st_atime != 0 ) { + dt.setTime_t( fic->st.st_atime ); + return dt; + } else { + return lastModified(); + } +} + +#ifndef QT_NO_DIR + +/*! + Returns the absolute path including the file name. + + The absolute path name consists of the full path and the file + name. On Unix this will always begin with the root, '/', + directory. On Windows this will always begin 'D:/' where D is a + drive letter, except for network shares that are not mapped to a + drive letter, in which case the path will begin '//sharename/'. + + This function returns the same as filePath(), unless isRelative() + is TRUE. + + This function can be time consuming under Unix (in the order of + milliseconds). + + \sa isRelative(), filePath() +*/ +QString QFileInfo::absFilePath() const +{ + QString tmp; + if ( QDir::isRelativePath(fn) +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) + && fn[1] != ':' +#endif + ) { + tmp = QDir::currentDirPath(); + tmp += '/'; + } + tmp += fn; + makeAbs( tmp ); + return QDir::cleanDirPath( tmp ); +} + +#endif diff --git a/qmake/tools/qfileinfo_unix.cpp b/qmake/tools/qfileinfo_unix.cpp new file mode 100644 index 0000000..f7c3a97 --- a/dev/null +++ b/qmake/tools/qfileinfo_unix.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QFileInfo class +** +** Created : 950628 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance +** with the Qt Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qdatetime.h" +#include "qdir.h" + +#include <limits.h> + + +void QFileInfo::slashify( QString& ) +{ + return; +} + + +void QFileInfo::makeAbs( QString & ) +{ + return; +} + +/*! + Returns TRUE if this object points to a file. Returns FALSE if the + object points to something which isn't a file, e.g. a directory or + a symlink. + + \sa isDir(), isSymLink() +*/ +bool QFileInfo::isFile() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & S_IFMT) == S_IFREG : FALSE; +} + +/*! + Returns TRUE if this object points to a directory or to a symbolic + link to a directory; otherwise returns FALSE. + + \sa isFile(), isSymLink() +*/ +bool QFileInfo::isDir() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & S_IFMT) == S_IFDIR : FALSE; +} + +/*! + Returns TRUE if this object points to a symbolic link (or to a + shortcut on Windows); otherwise returns FALSE. + + \sa isFile(), isDir(), readLink() +*/ + +bool QFileInfo::isSymLink() const +{ + if ( !fic || !cache ) + doStat(); + return symLink; +} + +/*! + Returns the name a symlink (or shortcut on Windows) points to, or + a QString::null if the object isn't a symbolic link. + + This name may not represent an existing file; it is only a string. + QFileInfo::exists() returns TRUE if the symlink points to an + existing file. + + \sa exists(), isSymLink(), isDir(), isFile() +*/ + +QString QFileInfo::readLink() const +{ + QString r; + +#if defined(Q_OS_UNIX) && !defined(Q_OS_OS2EMX) + char s[PATH_MAX+1]; + if ( !isSymLink() ) + return QString(); + int len = readlink( QFile::encodeName(fn).data(), s, PATH_MAX ); + if ( len >= 0 ) { + s[len] = '\0'; + r = QFile::decodeName(s); + } +#endif + + return r; +} + +static const uint nobodyID = (uint) -2; + +/*! + Returns the owner of the file. On Windows, on systems where files + do not have owners, or if an error occurs, QString::null is + returned. + + This function can be time consuming under Unix (in the order of + milliseconds). + + \sa ownerId(), group(), groupId() +*/ + +QString QFileInfo::owner() const +{ + passwd *pw = getpwuid( ownerId() ); + if ( pw ) + return QFile::decodeName( pw->pw_name ); + return QString::null; +} + +/*! + Returns the id of the owner of the file. + + On Windows and on systems where files do not have owners this + function returns ((uint) -2). + + \sa owner(), group(), groupId() +*/ + +uint QFileInfo::ownerId() const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) + return fic->st.st_uid; + return nobodyID; +} + +/*! + Returns the group of the file. On Windows, on systems where files + do not have groups, or if an error occurs, QString::null is + returned. + + This function can be time consuming under Unix (in the order of + milliseconds). + + \sa groupId(), owner(), ownerId() +*/ + +QString QFileInfo::group() const +{ + struct group *gr = getgrgid( groupId() ); + if ( gr ) + return QFile::decodeName( gr->gr_name ); + return QString::null; +} + +/*! + Returns the id of the group the file belongs to. + + On Windows and on systems where files do not have groups this + function always returns (uint) -2. + + \sa group(), owner(), ownerId() +*/ + +uint QFileInfo::groupId() const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) + return fic->st.st_gid; + return nobodyID; +} + + +/*! + Tests for file permissions. The \a permissionSpec argument can be + several flags of type \c PermissionSpec OR-ed together to check + for permission combinations. + + On systems where files do not have permissions this function + always returns TRUE. + + Example: + \code + QFileInfo fi( "/tmp/archive.tar.gz" ); + if ( fi.permission( QFileInfo::WriteUser | QFileInfo::ReadGroup ) ) + qWarning( "I can change the file; my group can read the file."); + if ( fi.permission( QFileInfo::WriteGroup | QFileInfo::WriteOther ) ) + qWarning( "The group or others can change the file!" ); + \endcode + + \sa isReadable(), isWritable(), isExecutable() +*/ + +bool QFileInfo::permission( int permissionSpec ) const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) { + uint mask = 0; + if ( permissionSpec & ReadUser ) + mask |= S_IRUSR; + if ( permissionSpec & WriteUser ) + mask |= S_IWUSR; + if ( permissionSpec & ExeUser ) + mask |= S_IXUSR; + if ( permissionSpec & ReadGroup ) + mask |= S_IRGRP; + if ( permissionSpec & WriteGroup ) + mask |= S_IWGRP; + if ( permissionSpec & ExeGroup ) + mask |= S_IXGRP; + if ( permissionSpec & ReadOther ) + mask |= S_IROTH; + if ( permissionSpec & WriteOther ) + mask |= S_IWOTH; + if ( permissionSpec & ExeOther ) + mask |= S_IXOTH; + if ( mask ) { + return (fic->st.st_mode & mask) == mask; + } else { +#if defined(QT_CHECK_NULL) + qWarning( "QFileInfo::permission: permissionSpec is 0" ); +#endif + return TRUE; + } + } else { + return FALSE; + } +} + +void QFileInfo::doStat() const +{ + QFileInfo *that = ((QFileInfo*)this); // mutable function + if ( !that->fic ) + that->fic = new QFileInfoCache; + that->symLink = FALSE; + struct stat *b = &that->fic->st; +#if defined(Q_OS_UNIX) && defined(S_IFLNK) + if ( ::lstat( QFile::encodeName(fn), b ) == 0 ) { + if ( S_ISLNK( b->st_mode ) ) + that->symLink = TRUE; + else + return; + } +#endif + + int r = ::stat( QFile::encodeName(fn), b ); + if ( r != 0 && !that->symLink ) { + delete that->fic; + that->fic = 0; + } +} + +/*! + Returns the file's path. + + If \a absPath is TRUE an absolute path is returned. + + \sa dir(), filePath(), fileName(), isRelative() +*/ +#ifndef QT_NO_DIR +QString QFileInfo::dirPath( bool absPath ) const +{ + QString s; + if ( absPath ) + s = absFilePath(); + else + s = fn; + int pos = s.findRev( '/' ); + if ( pos == -1 ) { + return QString::fromLatin1( "." ); + } else { + if ( pos == 0 ) + return QString::fromLatin1( "/" ); + return s.left( pos ); + } +} +#endif + +/*! + Returns the name of the file, excluding the path. + + Example: + \code + QFileInfo fi( "/tmp/archive.tar.gz" ); + QString name = fi.fileName(); // name = "archive.tar.gz" + \endcode + + \sa isRelative(), filePath(), baseName(), extension() +*/ + +QString QFileInfo::fileName() const +{ + int p = fn.findRev( '/' ); + if ( p == -1 ) { + return fn; + } else { + return fn.mid( p + 1 ); + } +} diff --git a/qmake/tools/qgarray.cpp b/qmake/tools/qgarray.cpp new file mode 100644 index 0000000..45c45ce --- a/dev/null +++ b/qmake/tools/qgarray.cpp @@ -0,0 +1,754 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGArray class +** +** Created : 930906 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qglobal.h" // needed to define Q_WS_WIN +#ifdef Q_WS_WIN +#include "qt_windows.h" // needed for bsearch on some platforms +#endif + +#define QGARRAY_CPP +#include "qgarray.h" +#include <stdlib.h> +#include <string.h> + +#ifdef QT_THREAD_SUPPORT +# include <private/qmutexpool_p.h> +#endif // QT_THREAD_SUPPORT + +#define USE_MALLOC // comment to use new/delete + +#undef NEW +#undef DELETE + +#if defined(USE_MALLOC) +#define NEW(type,size) ((type*)malloc(size*sizeof(type))) +#define DELETE(array) (free((char*)array)) +#else +#define NEW(type,size) (new type[size]) +#define DELETE(array) (delete[] array) +#define DONT_USE_REALLOC // comment to use realloc() +#endif + +/*! + \class QShared qshared.h + \reentrant + \ingroup shared + \brief The QShared class is used internally for implementing shared classes. + + \internal + + It only contains a reference count and member functions to increment and + decrement it. + + Shared classes normally have internal classes that inherit QShared and + add the shared data. + + \sa \link shclass.html Shared Classes\endlink +*/ + +/*! + \class QGArray qgarray.h + \reentrant + \ingroup shared + \ingroup collection + \brief The QGArray class is an internal class for implementing the QMemArray class. + + \internal + + QGArray is a strictly internal class that acts as base class for the + QMemArray template array. + + It contains an array of bytes and has no notion of an array element. +*/ + + +/*! + Constructs a null array. +*/ + +QGArray::QGArray() +{ + shd = newData(); + Q_CHECK_PTR( shd ); +} + +/*! + Dummy constructor; does not allocate any data. + + This constructor does not initialize any array data so subclasses + must do it. The intention is to make the code more efficient. +*/ + +QGArray::QGArray( int, int ) +{ +} + +/*! + Constructs an array with room for \a size bytes. +*/ + +QGArray::QGArray( int size ) +{ + if ( size < 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QGArray: Cannot allocate array with negative length" ); +#endif + size = 0; + } + shd = newData(); + Q_CHECK_PTR( shd ); + if ( size == 0 ) // zero length + return; + shd->data = NEW(char,size); + Q_CHECK_PTR( shd->data ); + shd->len = size; +} + +/*! + Constructs a shallow copy of \a a. +*/ + +QGArray::QGArray( const QGArray &a ) +{ + shd = a.shd; + shd->ref(); +} + +/*! + Dereferences the array data and deletes it if this was the last + reference. +*/ + +QGArray::~QGArray() +{ + if ( shd && shd->deref() ) { // delete when last reference + if ( shd->data ) // is lost + DELETE(shd->data); + deleteData( shd ); + shd = 0; + } +} + + +/*! + \fn QGArray &QGArray::operator=( const QGArray &a ) + + Assigns a shallow copy of \a a to this array and returns a reference to + this array. Equivalent to assign(). +*/ + +/*! + \fn void QGArray::detach() + + Detaches this array from shared array data. +*/ + +/*! + \fn char *QGArray::data() const + + Returns a pointer to the actual array data. +*/ + +/*! + \fn uint QGArray::nrefs() const + + Returns the reference count. +*/ + +/*! + \fn uint QGArray::size() const + + Returns the size of the array, in bytes. +*/ + + +/*! + Returns TRUE if this array is equal to \a a, otherwise FALSE. + The comparison is bitwise, of course. +*/ + +bool QGArray::isEqual( const QGArray &a ) const +{ + if ( size() != a.size() ) // different size + return FALSE; + if ( data() == a.data() ) // has same data + return TRUE; + return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0; +} + + +/*! + Resizes the array to \a newsize bytes. +*/ + +bool QGArray::resize( uint newsize ) +{ + if ( newsize == shd->len ) // nothing to do + return TRUE; + if ( newsize == 0 ) { // remove array + duplicate( 0, 0 ); + return TRUE; + } + if ( shd->data ) { // existing data +#if defined(DONT_USE_REALLOC) + char *newdata = NEW(char,newsize); // manual realloc + memcpy( newdata, shd->data, QMIN(shd->len,newsize) ); + DELETE(shd->data); + shd->data = newdata; +#else + shd->data = (char *)realloc( shd->data, newsize ); +#endif + } else { + shd->data = NEW(char,newsize); + } + if ( !shd->data ) // no memory + return FALSE; + shd->len = newsize; + return TRUE; +} + +/*! + Fills the array with the repeated occurrences of \a d, which is + \a sz bytes long. + If \a len is specified as different from -1, then the array will be + resized to \a len*sz before it is filled. + + Returns TRUE if successful, or FALSE if the memory cannot be allocated + (only when \a len != -1). + + \sa resize() +*/ + +bool QGArray::fill( const char *d, int len, uint sz ) +{ + if ( len < 0 ) + len = shd->len/sz; // default: use array length + else if ( !resize( len*sz ) ) + return FALSE; + if ( sz == 1 ) // 8 bit elements + memset( data(), *d, len ); + else if ( sz == 4 ) { // 32 bit elements + register Q_INT32 *x = (Q_INT32*)data(); + Q_INT32 v = *((Q_INT32*)d); + while ( len-- ) + *x++ = v; + } else if ( sz == 2 ) { // 16 bit elements + register Q_INT16 *x = (Q_INT16*)data(); + Q_INT16 v = *((Q_INT16*)d); + while ( len-- ) + *x++ = v; + } else { // any other size elements + register char *x = data(); + while ( len-- ) { // more complicated + memcpy( x, d, sz ); + x += sz; + } + } + return TRUE; +} + +/*! + \overload + Shallow copy. Dereference the current array and references the data + contained in \a a instead. Returns a reference to this array. + \sa operator=() +*/ + +QGArray &QGArray::assign( const QGArray &a ) +{ + a.shd->ref(); // avoid 'a = a' + if ( shd->deref() ) { // delete when last reference + if ( shd->data ) // is lost + DELETE(shd->data); + deleteData( shd ); + } + shd = a.shd; + return *this; +} + +/*! + Shallow copy. Dereference the current array and references the + array data \a d, which contains \a len bytes. + Returns a reference to this array. + + Do not delete \a d later, because QGArray takes care of that. +*/ + +QGArray &QGArray::assign( const char *d, uint len ) +{ + if ( shd->count > 1 ) { // disconnect this + shd->count--; + shd = newData(); + Q_CHECK_PTR( shd ); + } else { + if ( shd->data ) + DELETE(shd->data); + } + shd->data = (char *)d; + shd->len = len; + return *this; +} + +/*! + Deep copy. Dereference the current array and obtains a copy of the data + contained in \a a instead. Returns a reference to this array. + \sa assign(), operator=() +*/ + +QGArray &QGArray::duplicate( const QGArray &a ) +{ + if ( a.shd == shd ) { // a.duplicate(a) ! + if ( shd->count > 1 ) { + shd->count--; + register array_data *n = newData(); + Q_CHECK_PTR( n ); + if ( (n->len=shd->len) ) { + n->data = NEW(char,n->len); + Q_CHECK_PTR( n->data ); + if ( n->data ) + memcpy( n->data, shd->data, n->len ); + } else { + n->data = 0; + } + shd = n; + } + return *this; + } + char *oldptr = 0; + if ( shd->count > 1 ) { // disconnect this + shd->count--; + shd = newData(); + Q_CHECK_PTR( shd ); + } else { // delete after copy was made + oldptr = shd->data; + } + if ( a.shd->len ) { // duplicate data + shd->data = NEW(char,a.shd->len); + Q_CHECK_PTR( shd->data ); + if ( shd->data ) + memcpy( shd->data, a.shd->data, a.shd->len ); + } else { + shd->data = 0; + } + shd->len = a.shd->len; + if ( oldptr ) + DELETE(oldptr); + return *this; +} + +/*! + \overload + Deep copy. Dereferences the current array and obtains a copy of + \a len characters from array data \a d instead. Returns a reference + to this array. + \sa assign(), operator=() +*/ + +QGArray &QGArray::duplicate( const char *d, uint len ) +{ + char *data; + if ( d == 0 || len == 0 ) { + data = 0; + len = 0; + } else { + if ( shd->count == 1 && shd->len == len ) { + memcpy( shd->data, d, len ); // use same buffer + return *this; + } + data = NEW(char,len); + Q_CHECK_PTR( data ); + memcpy( data, d, len ); + } + if ( shd->count > 1 ) { // detach + shd->count--; + shd = newData(); + Q_CHECK_PTR( shd ); + } else { // just a single reference + if ( shd->data ) + DELETE(shd->data); + } + shd->data = data; + shd->len = len; + return *this; +} + +/*! + Resizes this array to \a len bytes and copies the \a len bytes at + address \a d into it. + + \warning This function disregards the reference count mechanism. If + other QGArrays reference the same data as this, all will be updated. +*/ + +void QGArray::store( const char *d, uint len ) +{ // store, but not deref + resize( len ); + memcpy( shd->data, d, len ); +} + + +/*! + \fn array_data *QGArray::sharedBlock() const + + Returns a pointer to the shared array block. + + \warning + + Do not use this function. Using it is begging for trouble. We dare + not remove it, for fear of breaking code, but we \e strongly + discourage new use of it. +*/ + +/*! + \fn void QGArray::setSharedBlock( array_data *p ) + + Sets the shared array block to \a p. + + \warning + + Do not use this function. Using it is begging for trouble. We dare + not remove it, for fear of breaking code, but we \e strongly + discourage new use of it. +*/ + + +/*! + Sets raw data and returns a reference to the array. + + Dereferences the current array and sets the new array data to \a d and + the new array size to \a len. Do not attempt to resize or re-assign the + array data when raw data has been set. + Call resetRawData(d,len) to reset the array. + + Setting raw data is useful because it sets QMemArray data without + allocating memory or copying data. + + Example of intended use: + \code + static uchar bindata[] = { 231, 1, 44, ... }; + QByteArray a; + a.setRawData( bindata, sizeof(bindata) ); // a points to bindata + QDataStream s( a, IO_ReadOnly ); // open on a's data + s >> <something>; // read raw bindata + s.close(); + a.resetRawData( bindata, sizeof(bindata) ); // finished + \endcode + + Example of misuse (do not do this): + \code + static uchar bindata[] = { 231, 1, 44, ... }; + QByteArray a, b; + a.setRawData( bindata, sizeof(bindata) ); // a points to bindata + a.resize( 8 ); // will crash + b = a; // will crash + a[2] = 123; // might crash + // forget to resetRawData - will crash + \endcode + + \warning If you do not call resetRawData(), QGArray will attempt to + deallocate or reallocate the raw data, which might not be too good. + Be careful. +*/ + +QGArray &QGArray::setRawData( const char *d, uint len ) +{ + duplicate( 0, 0 ); // set null data + shd->data = (char *)d; + shd->len = len; + return *this; +} + +/*! + Resets raw data. + + The arguments must be the data, \a d, and length \a len, that were + passed to setRawData(). This is for consistency checking. +*/ + +void QGArray::resetRawData( const char *d, uint len ) +{ + if ( d != shd->data || len != shd->len ) { +#if defined(QT_CHECK_STATE) + qWarning( "QGArray::resetRawData: Inconsistent arguments" ); +#endif + return; + } + shd->data = 0; + shd->len = 0; +} + + +/*! + Finds the first occurrence of \a d in the array from position \a index, + where \a sz is the size of the \a d element. + + Note that \a index is given in units of \a sz, not bytes. + + This function only compares whole cells, not bytes. +*/ + +int QGArray::find( const char *d, uint index, uint sz ) const +{ + index *= sz; + if ( index >= shd->len ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QGArray::find: Index %d out of range", index/sz ); +#endif + return -1; + } + register uint i; + uint ii; + switch ( sz ) { + case 1: { // 8 bit elements + register char *x = data() + index; + char v = *d; + for ( i=index; i<shd->len; i++ ) { + if ( *x++ == v ) + break; + } + ii = i; + } + break; + case 2: { // 16 bit elements + register Q_INT16 *x = (Q_INT16*)(data() + index); + Q_INT16 v = *((Q_INT16*)d); + for ( i=index; i<shd->len; i+=2 ) { + if ( *x++ == v ) + break; + } + ii = i/2; + } + break; + case 4: { // 32 bit elements + register Q_INT32 *x = (Q_INT32*)(data() + index); + Q_INT32 v = *((Q_INT32*)d); + for ( i=index; i<shd->len; i+=4 ) { + if ( *x++ == v ) + break; + } + ii = i/4; + } + break; + default: { // any size elements + for ( i=index; i<shd->len; i+=sz ) { + if ( memcmp( d, &shd->data[i], sz ) == 0 ) + break; + } + ii = i/sz; + } + break; + } + return i<shd->len ? (int)ii : -1; +} + +/*! + Returns the number of occurrences of \a d in the array, where \a sz is + the size of the \a d element. + + This function only compares whole cells, not bytes. +*/ + +int QGArray::contains( const char *d, uint sz ) const +{ + register uint i = shd->len; + int count = 0; + switch ( sz ) { + case 1: { // 8 bit elements + register char *x = data(); + char v = *d; + while ( i-- ) { + if ( *x++ == v ) + count++; + } + } + break; + case 2: { // 16 bit elements + register Q_INT16 *x = (Q_INT16*)data(); + Q_INT16 v = *((Q_INT16*)d); + i /= 2; + while ( i-- ) { + if ( *x++ == v ) + count++; + } + } + break; + case 4: { // 32 bit elements + register Q_INT32 *x = (Q_INT32*)data(); + Q_INT32 v = *((Q_INT32*)d); + i /= 4; + while ( i-- ) { + if ( *x++ == v ) + count++; + } + } + break; + default: { // any size elements + for ( i=0; i<shd->len; i+=sz ) { + if ( memcmp(d, &shd->data[i], sz) == 0 ) + count++; + } + } + break; + } + return count; +} + +static int cmp_item_size = 0; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +#ifdef Q_OS_TEMP +static int __cdecl cmp_arr( const void *n1, const void *n2 ) +#else +static int cmp_arr( const void *n1, const void *n2 ) +#endif +{ + return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) + : ( n1 ? 1 : ( n2 ? -1 : 0 ) ); + // ### Qt 3.0: Add a virtual compareItems() method and call that instead +} + +#if defined(Q_C_CALLBACKS) +} +#endif + +/*! + Sorts the first \a sz items of the array. +*/ + +void QGArray::sort( uint sz ) +{ + int numItems = size() / sz; + if ( numItems < 2 ) + return; + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); +#endif // QT_THREAD_SUPPORT + + cmp_item_size = sz; + qsort( shd->data, numItems, sz, cmp_arr ); +} + +/*! + Binary search; assumes that \a d is a sorted array of size \a sz. +*/ + +int QGArray::bsearch( const char *d, uint sz ) const +{ + int numItems = size() / sz; + if ( !numItems ) + return -1; + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); +#endif // QT_THREAD_SUPPORT + + cmp_item_size = sz; + char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr ); + if ( !r ) + return -1; + while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) ) + r -= sz; // search to first of equal elements; bsearch is undef + return (int)(( r - shd->data ) / sz); +} + + +/*! + \fn char *QGArray::at( uint index ) const + + Returns a pointer to the byte at offset \a index in the array. +*/ + +/*! + Expand the array if necessary, and copies (the first part of) its + contents from the \a index * \a sz bytes at \a d. + + Returns TRUE if the operation succeeds, FALSE if it runs out of + memory. + + \warning This function disregards the reference count mechanism. If + other QGArrays reference the same data as this, all will be changed. +*/ + +bool QGArray::setExpand( uint index, const char *d, uint sz ) +{ + index *= sz; + if ( index >= shd->len ) { + if ( !resize( index+sz ) ) // no memory + return FALSE; + } + memcpy( data() + index, d, sz ); + return TRUE; +} + + +/*! + Prints a warning message if at() or [] is given a bad index. +*/ + +void QGArray::msg_index( uint index ) +{ +#if defined(QT_CHECK_RANGE) + qWarning( "QGArray::at: Absolute index %d out of range", index ); +#else + Q_UNUSED( index ) +#endif +} + + +/*! + Returns a new shared array block. +*/ + +QGArray::array_data * QGArray::newData() +{ + return new array_data; +} + + +/*! + Deletes the shared array block, \a p. +*/ + +void QGArray::deleteData( array_data *p ) +{ + delete p; + p = 0; +} diff --git a/qmake/tools/qgcache.cpp b/qmake/tools/qgcache.cpp new file mode 100644 index 0000000..84180b0 --- a/dev/null +++ b/qmake/tools/qgcache.cpp @@ -0,0 +1,863 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGCache and QGCacheIterator classes +** +** Created : 950208 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qgcache.h" +#include "qptrlist.h" +#include "qdict.h" +#include "qstring.h" + +/*! + \class QGCache qgcache.h + \reentrant + \ingroup shared + \ingroup collection + \brief The QGCache class is an internal class for implementing QCache + template classes. + + \internal + + QGCache is a strictly internal class that acts as a base class for the + \link collection.html collection classes\endlink QCache and QIntCache. +*/ + + +/***************************************************************************** + QGCacheItem class (internal cache item) + *****************************************************************************/ + +struct QCacheItem +{ + QCacheItem( void *k, QPtrCollection::Item d, int c, short p ) + : priority(p), skipPriority(p), cost(c), key(k), data(d), node(0) {} + short priority; + short skipPriority; + int cost; + void *key; + QPtrCollection::Item data; + QLNode *node; +}; + + +/***************************************************************************** + QCList class (internal list of cache items) + *****************************************************************************/ + +class QCList : private QPtrList<QCacheItem> +{ +friend class QGCacheIterator; +friend class QCListIt; +public: + QCList() {} + ~QCList(); + + void insert( QCacheItem * ); // insert according to priority + void insert( int, QCacheItem * ); + void take( QCacheItem * ); + void reference( QCacheItem * ); + + void setAutoDelete( bool del ) { QPtrCollection::setAutoDelete(del); } + + bool removeFirst() { return QPtrList<QCacheItem>::removeFirst(); } + bool removeLast() { return QPtrList<QCacheItem>::removeLast(); } + + QCacheItem *first() { return QPtrList<QCacheItem>::first(); } + QCacheItem *last() { return QPtrList<QCacheItem>::last(); } + QCacheItem *prev() { return QPtrList<QCacheItem>::prev(); } + QCacheItem *next() { return QPtrList<QCacheItem>::next(); } + +#if defined(QT_DEBUG) + int inserts; // variables for statistics + int insertCosts; + int insertMisses; + int finds; + int hits; + int hitCosts; + int dumps; + int dumpCosts; +#endif +}; + + +QCList::~QCList() +{ +#if defined(QT_DEBUG) + Q_ASSERT( count() == 0 ); +#endif +} + + +void QCList::insert( QCacheItem *ci ) +{ + QCacheItem *item = first(); + while( item && item->skipPriority > ci->priority ) { + item->skipPriority--; + item = next(); + } + if ( item ) + QPtrList<QCacheItem>::insert( at(), ci ); + else + append( ci ); +#if defined(QT_DEBUG) + Q_ASSERT( ci->node == 0 ); +#endif + ci->node = currentNode(); +} + +inline void QCList::insert( int i, QCacheItem *ci ) +{ + QPtrList<QCacheItem>::insert( i, ci ); +#if defined(QT_DEBUG) + Q_ASSERT( ci->node == 0 ); +#endif + ci->node = currentNode(); +} + + +void QCList::take( QCacheItem *ci ) +{ + if ( ci ) { +#if defined(QT_DEBUG) + Q_ASSERT( ci->node != 0 ); +#endif + takeNode( ci->node ); + ci->node = 0; + } +} + + +inline void QCList::reference( QCacheItem *ci ) +{ +#if defined(QT_DEBUG) + Q_ASSERT( ci != 0 && ci->node != 0 ); +#endif + ci->skipPriority = ci->priority; + relinkNode( ci->node ); // relink as first item +} + + +class QCListIt: public QPtrListIterator<QCacheItem> +{ +public: + QCListIt( const QCList *p ): QPtrListIterator<QCacheItem>( *p ) {} + QCListIt( const QCListIt *p ): QPtrListIterator<QCacheItem>( *p ) {} +}; + + +/***************************************************************************** + QCDict class (internal dictionary of cache items) + *****************************************************************************/ + +// +// Since we need to decide if the dictionary should use an int or const +// char * key (the "bool trivial" argument in the constructor below) +// we cannot use the macro/template dict, but inherit directly from QGDict. +// + +class QCDict : public QGDict +{ +public: + QCDict( uint size, uint kt, bool caseSensitive, bool copyKeys ) + : QGDict( size, (KeyType)kt, caseSensitive, copyKeys ) {} + ~QCDict(); + + void clear() { QGDict::clear(); } + + QCacheItem *find_string(const QString &key) const + { return (QCacheItem*)((QCDict*)this)->look_string(key, 0, 0); } + QCacheItem *find_ascii(const char *key) const + { return (QCacheItem*)((QCDict*)this)->look_ascii(key, 0, 0); } + QCacheItem *find_int(long key) const + { return (QCacheItem*)((QCDict*)this)->look_int(key, 0, 0); } + + QCacheItem *take_string(const QString &key) + { return (QCacheItem*)QGDict::take_string(key); } + QCacheItem *take_ascii(const char *key) + { return (QCacheItem*)QGDict::take_ascii(key); } + QCacheItem *take_int(long key) + { return (QCacheItem*)QGDict::take_int(key); } + + bool insert_string( const QString &key, const QCacheItem *ci ) + { return QGDict::look_string(key,(Item)ci,1)!=0;} + bool insert_ascii( const char *key, const QCacheItem *ci ) + { return QGDict::look_ascii(key,(Item)ci,1)!=0;} + bool insert_int( long key, const QCacheItem *ci ) + { return QGDict::look_int(key,(Item)ci,1)!=0;} + + bool remove_string( QCacheItem *item ) + { return QGDict::remove_string(*((QString*)(item->key)),item); } + bool remove_ascii( QCacheItem *item ) + { return QGDict::remove_ascii((const char *)item->key,item); } + bool remove_int( QCacheItem *item ) + { return QGDict::remove_int((long)item->key,item);} + + void statistics() { QGDict::statistics(); } + +private: + void deleteItem( void *item ) + { if ( del_item ) { QCacheItem *d = (QCacheItem*)item; delete d; } } +}; + +inline QCDict::~QCDict() +{ + clear(); +} + +/***************************************************************************** + QGDict member functions + *****************************************************************************/ + +/*! + Constructs a cache. + The maximum cost of the cache is given by \a maxCost and the size by \a + size. The key type is \a kt which may be \c StringKey, \c AsciiKey, + \c IntKey or \c PtrKey. The case-sensitivity of lookups is set with + \a caseSensitive. Keys are copied if \a copyKeys is TRUE. +*/ + +QGCache::QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive, + bool copyKeys ) +{ + keytype = kt; + lruList = new QCList; + Q_CHECK_PTR( lruList ); + lruList->setAutoDelete( TRUE ); + copyk = ((keytype == AsciiKey) && copyKeys); + dict = new QCDict( size, kt, caseSensitive, FALSE ); + Q_CHECK_PTR( dict ); + mCost = maxCost; + tCost = 0; +#if defined(QT_DEBUG) + lruList->inserts = 0; + lruList->insertCosts = 0; + lruList->insertMisses = 0; + lruList->finds = 0; + lruList->hits = 0; + lruList->hitCosts = 0; + lruList->dumps = 0; + lruList->dumpCosts = 0; +#endif +} + +/*! + Cannot copy a cache. +*/ + +QGCache::QGCache( const QGCache & ) + : QPtrCollection() +{ +#if defined(QT_CHECK_NULL) + qFatal( "QGCache::QGCache(QGCache &): Cannot copy a cache" ); +#endif +} + +/*! + Removes all items from the cache and destroys it. +*/ + +QGCache::~QGCache() +{ + clear(); + delete dict; + delete lruList; +} + +/*! + Cannot assign a cache. +*/ + +QGCache &QGCache::operator=( const QGCache & ) +{ +#if defined(QT_CHECK_NULL) + qFatal( "QGCache::operator=: Cannot copy a cache" ); +#endif + return *this; +} + + +/*! + Returns the number of items in the cache. +*/ + +uint QGCache::count() const +{ + return dict->count(); +} + +/*! + Returns the size of the hash array. +*/ + +uint QGCache::size() const +{ + return dict->size(); +} + +/*! + \fn int QGCache::maxCost() const + + Returns the maximum cache cost. +*/ + +/*! + \fn int QGCache::totalCost() const + + Returns the total cache cost. +*/ + +/*! + Sets the maximum cache cost to \a maxCost. +*/ + +void QGCache::setMaxCost( int maxCost ) +{ + if ( maxCost < tCost ) { + if ( !makeRoomFor(tCost - maxCost) ) // remove excess cost + return; + } + mCost = maxCost; +} + + +/*! + Inserts an item with data \a data into the cache using key \a key. + The item has cost \a cost and priority \a priority. + + \warning If this function returns FALSE, you must delete \a data + yourself. Additionally, be very careful about using \a data after + calling this function, as any other insertions into the cache, from + anywhere in the application, or within Qt itself, could cause the + data to be discarded from the cache, and the pointer to become + invalid. +*/ + +bool QGCache::insert_string( const QString &key, QPtrCollection::Item data, + int cost, int priority) +{ + if ( tCost + cost > mCost ) { + if ( !makeRoomFor(tCost + cost - mCost, priority) ) { +#if defined(QT_DEBUG) + lruList->insertMisses++; +#endif + return FALSE; + } + } +#if defined(QT_DEBUG) + Q_ASSERT( keytype == StringKey ); + lruList->inserts++; + lruList->insertCosts += cost; +#endif + if ( priority < -32768 ) + priority = -32768; + else if ( priority > 32767 ) + priority = 32677; + QCacheItem *ci = new QCacheItem( new QString(key), newItem(data), + cost, (short)priority ); + Q_CHECK_PTR( ci ); + lruList->insert( 0, ci ); + dict->insert_string( key, ci ); + tCost += cost; + return TRUE; +} + +bool QGCache::insert_other( const char *key, QPtrCollection::Item data, + int cost, int priority) +{ + if ( tCost + cost > mCost ) { + if ( !makeRoomFor(tCost + cost - mCost, priority) ) { +#if defined(QT_DEBUG) + lruList->insertMisses++; +#endif + return FALSE; + } + } +#if defined(QT_DEBUG) + Q_ASSERT( keytype != StringKey ); + lruList->inserts++; + lruList->insertCosts += cost; +#endif + if ( keytype == AsciiKey && copyk ) + key = qstrdup( key ); + if ( priority < -32768 ) + priority = -32768; + else if ( priority > 32767 ) + priority = 32677; + QCacheItem *ci = new QCacheItem( (void*)key, newItem(data), cost, + (short)priority ); + Q_CHECK_PTR( ci ); + lruList->insert( 0, ci ); + if ( keytype == AsciiKey ) + dict->insert_ascii( key, ci ); + else + dict->insert_int( (long)key, ci ); + tCost += cost; + return TRUE; +} + + +/*! + Removes the item with key \a key from the cache. Returns TRUE if the + item was removed; otherwise returns FALSE. +*/ + +bool QGCache::remove_string( const QString &key ) +{ + Item d = take_string( key ); + if ( d ) + deleteItem( d ); + return d != 0; +} + +bool QGCache::remove_other( const char *key ) +{ + Item d = take_other( key ); + if ( d ) + deleteItem( d ); + return d != 0; +} + + +/*! + Takes the item with key \a key out of the cache. The item is not + deleted. If no item has this \a key 0 is returned. +*/ + +QPtrCollection::Item QGCache::take_string( const QString &key ) +{ + QCacheItem *ci = dict->take_string( key ); // take from dict + Item d; + if ( ci ) { + d = ci->data; + tCost -= ci->cost; + lruList->take( ci ); // take from list + delete (QString*)ci->key; + delete ci; + } else { + d = 0; + } + return d; +} + +/*! + Takes the item with key \a key out of the cache. The item is not + deleted. If no item has this \a key 0 is returned. +*/ + +QPtrCollection::Item QGCache::take_other( const char *key ) +{ + QCacheItem *ci; + if ( keytype == AsciiKey ) + ci = dict->take_ascii( key ); + else + ci = dict->take_int( (long)key ); + Item d; + if ( ci ) { + d = ci->data; + tCost -= ci->cost; + lruList->take( ci ); // take from list + if ( copyk ) + delete [] (char *)ci->key; + delete ci; + } else { + d = 0; + } + return d; +} + + +/*! + Clears the cache. +*/ + +void QGCache::clear() +{ + QCacheItem *ci; + while ( (ci = lruList->first()) ) { + switch ( keytype ) { + case StringKey: + dict->remove_string( ci ); + delete (QString*)ci->key; + break; + case AsciiKey: + dict->remove_ascii( ci ); + if ( copyk ) + delete [] (char*)ci->key; + break; + case IntKey: + dict->remove_int( ci ); + break; + case PtrKey: // unused + break; + } + deleteItem( ci->data ); // delete data + lruList->removeFirst(); // remove from list + } + tCost = 0; +} + + +/*! + Finds an item for \a key in the cache and adds a reference if \a ref is TRUE. +*/ + +QPtrCollection::Item QGCache::find_string( const QString &key, bool ref ) const +{ + QCacheItem *ci = dict->find_string( key ); +#if defined(QT_DEBUG) + lruList->finds++; +#endif + if ( ci ) { +#if defined(QT_DEBUG) + lruList->hits++; + lruList->hitCosts += ci->cost; +#endif + if ( ref ) + lruList->reference( ci ); + return ci->data; + } + return 0; +} + + +/*! + Finds an item for \a key in the cache and adds a reference if \a ref is TRUE. +*/ + +QPtrCollection::Item QGCache::find_other( const char *key, bool ref ) const +{ + QCacheItem *ci = keytype == AsciiKey ? dict->find_ascii(key) + : dict->find_int((long)key); +#if defined(QT_DEBUG) + lruList->finds++; +#endif + if ( ci ) { +#if defined(QT_DEBUG) + lruList->hits++; + lruList->hitCosts += ci->cost; +#endif + if ( ref ) + lruList->reference( ci ); + return ci->data; + } + return 0; +} + + +/*! + Allocates cache space for one or more items. +*/ + +bool QGCache::makeRoomFor( int cost, int priority ) +{ + if ( cost > mCost ) // cannot make room for more + return FALSE; // than maximum cost + if ( priority == -1 ) + priority = 32767; + register QCacheItem *ci = lruList->last(); + int cntCost = 0; + int dumps = 0; // number of items to dump + while ( cntCost < cost && ci && ci->skipPriority <= priority ) { + cntCost += ci->cost; + ci = lruList->prev(); + dumps++; + } + if ( cntCost < cost ) // can enough cost be dumped? + return FALSE; // no +#if defined(QT_DEBUG) + Q_ASSERT( dumps > 0 ); +#endif + while ( dumps-- ) { + ci = lruList->last(); +#if defined(QT_DEBUG) + lruList->dumps++; + lruList->dumpCosts += ci->cost; +#endif + switch ( keytype ) { + case StringKey: + dict->remove_string( ci ); + delete (QString*)ci->key; + break; + case AsciiKey: + dict->remove_ascii( ci ); + if ( copyk ) + delete [] (char *)ci->key; + break; + case IntKey: + dict->remove_int( ci ); + break; + case PtrKey: // unused + break; + } + deleteItem( ci->data ); // delete data + lruList->removeLast(); // remove from list + } + tCost -= cntCost; + return TRUE; +} + + +/*! + Outputs debug statistics. +*/ + +void QGCache::statistics() const +{ +#if defined(QT_DEBUG) + QString line; + line.fill( '*', 80 ); + qDebug( line.ascii() ); + qDebug( "CACHE STATISTICS:" ); + qDebug( "cache contains %d item%s, with a total cost of %d", + count(), count() != 1 ? "s" : "", tCost ); + qDebug( "maximum cost is %d, cache is %d%% full.", + mCost, (200*tCost + mCost) / (mCost*2) ); + qDebug( "find() has been called %d time%s", + lruList->finds, lruList->finds != 1 ? "s" : "" ); + qDebug( "%d of these were hits, items found had a total cost of %d.", + lruList->hits,lruList->hitCosts ); + qDebug( "%d item%s %s been inserted with a total cost of %d.", + lruList->inserts,lruList->inserts != 1 ? "s" : "", + lruList->inserts != 1 ? "have" : "has", lruList->insertCosts ); + qDebug( "%d item%s %s too large or had too low priority to be inserted.", + lruList->insertMisses, lruList->insertMisses != 1 ? "s" : "", + lruList->insertMisses != 1 ? "were" : "was" ); + qDebug( "%d item%s %s been thrown away with a total cost of %d.", + lruList->dumps, lruList->dumps != 1 ? "s" : "", + lruList->dumps != 1 ? "have" : "has", lruList->dumpCosts ); + qDebug( "Statistics from internal dictionary class:" ); + dict->statistics(); + qDebug( line.ascii() ); +#endif +} + + +/***************************************************************************** + QGCacheIterator member functions + *****************************************************************************/ + +/*! + \class QGCacheIterator qgcache.h + \reentrant + \ingroup shared + \ingroup collection + \brief The QGCacheIterator class is an internal class for implementing QCacheIterator and + QIntCacheIterator. + + \internal + + QGCacheIterator is a strictly internal class that does the heavy work for + QCacheIterator and QIntCacheIterator. +*/ + +/*! + Constructs an iterator that operates on the cache \a c. +*/ + +QGCacheIterator::QGCacheIterator( const QGCache &c ) +{ + it = new QCListIt( c.lruList ); +#if defined(QT_DEBUG) + Q_ASSERT( it != 0 ); +#endif +} + +/*! + Constructs an iterator that operates on the same cache as \a ci. +*/ + +QGCacheIterator::QGCacheIterator( const QGCacheIterator &ci ) +{ + it = new QCListIt( ci.it ); +#if defined(QT_DEBUG) + Q_ASSERT( it != 0 ); +#endif +} + +/*! + Destroys the iterator. +*/ + +QGCacheIterator::~QGCacheIterator() +{ + delete it; +} + +/*! + Assigns the iterator \a ci to this cache iterator. +*/ + +QGCacheIterator &QGCacheIterator::operator=( const QGCacheIterator &ci ) +{ + *it = *ci.it; + return *this; +} + +/*! + Returns the number of items in the cache. +*/ + +uint QGCacheIterator::count() const +{ + return it->count(); +} + +/*! + Returns TRUE if the iterator points to the first item. +*/ + +bool QGCacheIterator::atFirst() const +{ + return it->atFirst(); +} + +/*! + Returns TRUE if the iterator points to the last item. +*/ + +bool QGCacheIterator::atLast() const +{ + return it->atLast(); +} + +/*! + Sets the list iterator to point to the first item in the cache. +*/ + +QPtrCollection::Item QGCacheIterator::toFirst() +{ + QCacheItem *item = it->toFirst(); + return item ? item->data : 0; +} + +/*! + Sets the list iterator to point to the last item in the cache. +*/ + +QPtrCollection::Item QGCacheIterator::toLast() +{ + QCacheItem *item = it->toLast(); + return item ? item->data : 0; +} + +/*! + Returns the current item. +*/ + +QPtrCollection::Item QGCacheIterator::get() const +{ + QCacheItem *item = it->current(); + return item ? item->data : 0; +} + +/*! + Returns the key of the current item. +*/ + +QString QGCacheIterator::getKeyString() const +{ + QCacheItem *item = it->current(); + return item ? *((QString*)item->key) : QString::null; +} + +/*! + Returns the key of the current item, as a \0-terminated C string. +*/ + +const char *QGCacheIterator::getKeyAscii() const +{ + QCacheItem *item = it->current(); + return item ? (const char *)item->key : 0; +} + +/*! + Returns the key of the current item, as a long. +*/ + +long QGCacheIterator::getKeyInt() const +{ + QCacheItem *item = it->current(); + return item ? (long)item->key : 0; +} + +/*! + Moves to the next item (postfix). +*/ + +QPtrCollection::Item QGCacheIterator::operator()() +{ + QCacheItem *item = it->operator()(); + return item ? item->data : 0; +} + +/*! + Moves to the next item (prefix). +*/ + +QPtrCollection::Item QGCacheIterator::operator++() +{ + QCacheItem *item = it->operator++(); + return item ? item->data : 0; +} + +/*! + Moves \a jump positions forward. +*/ + +QPtrCollection::Item QGCacheIterator::operator+=( uint jump ) +{ + QCacheItem *item = it->operator+=(jump); + return item ? item->data : 0; +} + +/*! + Moves to the previous item (prefix). +*/ + +QPtrCollection::Item QGCacheIterator::operator--() +{ + QCacheItem *item = it->operator--(); + return item ? item->data : 0; +} + +/*! + Moves \a jump positions backward. +*/ + +QPtrCollection::Item QGCacheIterator::operator-=( uint jump ) +{ + QCacheItem *item = it->operator-=(jump); + return item ? item->data : 0; +} diff --git a/qmake/tools/qgdict.cpp b/qmake/tools/qgdict.cpp new file mode 100644 index 0000000..c431ff8 --- a/dev/null +++ b/qmake/tools/qgdict.cpp @@ -0,0 +1,1146 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGDict and QGDictIterator classes +** +** Created : 920529 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qgdict.h" +#include "qptrlist.h" +#include "qstring.h" +#include "qdatastream.h" +#include <ctype.h> + +/*! + \class QGDict + \reentrant + \ingroup collection + \brief The QGDict class is an internal class for implementing QDict template classes. + + \internal + + QGDict is a strictly internal class that acts as a base class for the + \link collection.html collection classes\endlink QDict and QIntDict. + + QGDict has some virtual functions that can be reimplemented to customize + the subclasses. + \list + \i read() reads a collection/dictionary item from a QDataStream. + \i write() writes a collection/dictionary item to a QDataStream. + \endlist + Normally, you do not have to reimplement any of these functions. +*/ + +static const int op_find = 0; +static const int op_insert = 1; +static const int op_replace = 2; + + +class QGDItList : public QPtrList<QGDictIterator> +{ +public: + QGDItList() : QPtrList<QGDictIterator>() {} + QGDItList( const QGDItList &list ) : QPtrList<QGDictIterator>(list) {} + ~QGDItList() { clear(); } + QGDItList &operator=(const QGDItList &list) + { return (QGDItList&)QPtrList<QGDictIterator>::operator=(list); } +}; + + +/***************************************************************************** + Default implementation of special and virtual functions + *****************************************************************************/ + +/*! + Returns the hash key for \a key, when key is a string. +*/ + +int QGDict::hashKeyString( const QString &key ) +{ +#if defined(QT_CHECK_NULL) + if ( key.isNull() ) + qWarning( "QGDict::hashKeyString: Invalid null key" ); +#endif + int i; + register uint h=0; + uint g; + const QChar *p = key.unicode(); + if ( cases ) { // case sensitive + for ( i=0; i<(int)key.length(); i++ ) { + h = (h<<4) + p[i].cell(); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } else { // case insensitive + for ( i=0; i<(int)key.length(); i++ ) { + h = (h<<4) + p[i].lower().cell(); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } + int index = h; + if ( index < 0 ) // adjust index to table size + index = -index; + return index; +} + +/*! + Returns the hash key for \a key, which is a C string. +*/ + +int QGDict::hashKeyAscii( const char *key ) +{ +#if defined(QT_CHECK_NULL) + if ( key == 0 ) + qWarning( "QGDict::hashAsciiKey: Invalid null key" ); +#endif + register const char *k = key; + register uint h=0; + uint g; + if ( cases ) { // case sensitive + while ( *k ) { + h = (h<<4) + *k++; + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + } else { // case insensitive + while ( *k ) { + h = (h<<4) + tolower((uchar) *k); + if ( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + k++; + } + } + int index = h; + if ( index < 0 ) // adjust index to table size + index = -index; + return index; +} + +#ifndef QT_NO_DATASTREAM + +/*! + \overload + Reads a collection/dictionary item from the stream \a s and returns a + reference to the stream. + + The default implementation sets \a item to 0. + + \sa write() +*/ + +QDataStream& QGDict::read( QDataStream &s, QPtrCollection::Item &item ) +{ + item = 0; + return s; +} + +/*! + \overload + Writes a collection/dictionary item to the stream \a s and returns a + reference to the stream. + + \sa read() +*/ + +QDataStream& QGDict::write( QDataStream &s, QPtrCollection::Item ) const +{ + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + QGDict member functions + *****************************************************************************/ + +/*! + Constructs a dictionary. + + \a len is the initial size of the dictionary. + The key type is \a kt which may be \c StringKey, \c AsciiKey, + \c IntKey or \c PtrKey. The case-sensitivity of lookups is set with + \a caseSensitive. Keys are copied if \a copyKeys is TRUE. +*/ + +QGDict::QGDict( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) +{ + init( len, kt, caseSensitive, copyKeys ); +} + + +void QGDict::init( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) +{ + vec = new QBaseBucket *[vlen = len]; // allocate hash table + Q_CHECK_PTR( vec ); + memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) ); + numItems = 0; + iterators = 0; + // The caseSensitive and copyKey options don't make sense for + // all dict types. + switch ( (keytype = (uint)kt) ) { + case StringKey: + cases = caseSensitive; + copyk = FALSE; + break; + case AsciiKey: + cases = caseSensitive; + copyk = copyKeys; + break; + default: + cases = FALSE; + copyk = FALSE; + break; + } +} + + +/*! + Constructs a copy of \a dict. +*/ + +QGDict::QGDict( const QGDict & dict ) + : QPtrCollection( dict ) +{ + init( dict.vlen, (KeyType)dict.keytype, dict.cases, dict.copyk ); + QGDictIterator it( dict ); + while ( it.get() ) { // copy from other dict + switch ( keytype ) { + case StringKey: + look_string( it.getKeyString(), it.get(), op_insert ); + break; + case AsciiKey: + look_ascii( it.getKeyAscii(), it.get(), op_insert ); + break; + case IntKey: + look_int( it.getKeyInt(), it.get(), op_insert ); + break; + case PtrKey: + look_ptr( it.getKeyPtr(), it.get(), op_insert ); + break; + } + ++it; + } +} + + +/*! + Removes all items from the dictionary and destroys it. +*/ + +QGDict::~QGDict() +{ + clear(); // delete everything + delete [] vec; + if ( !iterators ) // no iterators for this dict + return; + QGDictIterator *i = iterators->first(); + while ( i ) { // notify all iterators that + i->dict = 0; // this dict is deleted + i = iterators->next(); + } + delete iterators; +} + + +/*! + Assigns \a dict to this dictionary. +*/ + +QGDict &QGDict::operator=( const QGDict &dict ) +{ + if ( &dict == this ) + return *this; + clear(); + QGDictIterator it( dict ); + while ( it.get() ) { // copy from other dict + switch ( keytype ) { + case StringKey: + look_string( it.getKeyString(), it.get(), op_insert ); + break; + case AsciiKey: + look_ascii( it.getKeyAscii(), it.get(), op_insert ); + break; + case IntKey: + look_int( it.getKeyInt(), it.get(), op_insert ); + break; + case PtrKey: + look_ptr( it.getKeyPtr(), it.get(), op_insert ); + break; + } + ++it; + } + return *this; +} + +/*! + \fn uint QGDict::count() const + + Returns the number of items in the dictionary. +*/ + +/*! + \fn uint QGDict::size() const + + Returns the size of the hash array. +*/ + +/*! + The do-it-all function; \a op is one of op_find, op_insert, op_replace. + The key is \a key and the item is \a d. +*/ + +QPtrCollection::Item QGDict::look_string( const QString &key, QPtrCollection::Item d, + int op ) +{ + QStringBucket *n = 0; + int index = hashKeyString(key) % vlen; + if ( op == op_find ) { // find + if ( cases ) { + n = (QStringBucket*)vec[index]; + while( n != 0 ) { + if ( key == n->getKey() ) + return n->getData(); // item found + n = (QStringBucket*)n->getNext(); + } + } else { + QString k = key.lower(); + n = (QStringBucket*)vec[index]; + while( n != 0 ) { + if ( k == n->getKey().lower() ) + return n->getData(); // item found + n = (QStringBucket*)n->getNext(); + } + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_string( key ); + } + // op_insert or op_replace + n = new QStringBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +QPtrCollection::Item QGDict::look_ascii( const char *key, QPtrCollection::Item d, int op ) +{ + QAsciiBucket *n; + int index = hashKeyAscii(key) % vlen; + if ( op == op_find ) { // find + if ( cases ) { + for ( n=(QAsciiBucket*)vec[index]; n; + n=(QAsciiBucket*)n->getNext() ) { + if ( qstrcmp(n->getKey(),key) == 0 ) + return n->getData(); // item found + } + } else { + for ( n=(QAsciiBucket*)vec[index]; n; + n=(QAsciiBucket*)n->getNext() ) { + if ( qstricmp(n->getKey(),key) == 0 ) + return n->getData(); // item found + } + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_ascii( key ); + } + // op_insert or op_replace + n = new QAsciiBucket(copyk ? qstrdup(key) : key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QAsciiDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +QPtrCollection::Item QGDict::look_int( long key, QPtrCollection::Item d, int op ) +{ + QIntBucket *n; + int index = (int)((ulong)key % vlen); // simple hash + if ( op == op_find ) { // find + for ( n=(QIntBucket*)vec[index]; n; + n=(QIntBucket*)n->getNext() ) { + if ( n->getKey() == key ) + return n->getData(); // item found + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_int( key ); + } + // op_insert or op_replace + n = new QIntBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QIntDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + +QPtrCollection::Item QGDict::look_ptr( void *key, QPtrCollection::Item d, int op ) +{ + QPtrBucket *n; + int index = (int)((ulong)key % vlen); // simple hash + if ( op == op_find ) { // find + for ( n=(QPtrBucket*)vec[index]; n; + n=(QPtrBucket*)n->getNext() ) { + if ( n->getKey() == key ) + return n->getData(); // item found + } + return 0; // not found + } + if ( op == op_replace ) { // replace + if ( vec[index] != 0 ) // maybe something there + remove_ptr( key ); + } + // op_insert or op_replace + n = new QPtrBucket(key,newItem(d),vec[index]); + Q_CHECK_PTR( n ); +#if defined(QT_CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QPtrDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! + Changes the size of the hashtable to \a newsize. + The contents of the dictionary are preserved, + but all iterators on the dictionary become invalid. +*/ +void QGDict::resize( uint newsize ) +{ + // Save old information + QBaseBucket **old_vec = vec; + uint old_vlen = vlen; + bool old_copyk = copyk; + + vec = new QBaseBucket *[vlen = newsize]; + Q_CHECK_PTR( vec ); + memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) ); + numItems = 0; + copyk = FALSE; + + // Reinsert every item from vec, deleting vec as we go + for ( uint index = 0; index < old_vlen; index++ ) { + switch ( keytype ) { + case StringKey: + { + QStringBucket *n=(QStringBucket *)old_vec[index]; + while ( n ) { + look_string( n->getKey(), n->getData(), op_insert ); + QStringBucket *t=(QStringBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case AsciiKey: + { + QAsciiBucket *n=(QAsciiBucket *)old_vec[index]; + while ( n ) { + look_ascii( n->getKey(), n->getData(), op_insert ); + QAsciiBucket *t=(QAsciiBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case IntKey: + { + QIntBucket *n=(QIntBucket *)old_vec[index]; + while ( n ) { + look_int( n->getKey(), n->getData(), op_insert ); + QIntBucket *t=(QIntBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + case PtrKey: + { + QPtrBucket *n=(QPtrBucket *)old_vec[index]; + while ( n ) { + look_ptr( n->getKey(), n->getData(), op_insert ); + QPtrBucket *t=(QPtrBucket *)n->getNext(); + delete n; + n = t; + } + } + break; + } + } + delete [] old_vec; + + // Restore state + copyk = old_copyk; + + // Invalidate all iterators, since order is lost + if ( iterators && iterators->count() ) { + QGDictIterator *i = iterators->first(); + while ( i ) { + i->toFirst(); + i = iterators->next(); + } + } +} + +/*! + Unlinks the bucket with the specified key (and specified data pointer, + if it is set). +*/ + +void QGDict::unlink_common( int index, QBaseBucket *node, QBaseBucket *prev ) +{ + if ( iterators && iterators->count() ) { // update iterators + QGDictIterator *i = iterators->first(); + while ( i ) { // invalidate all iterators + if ( i->curNode == node ) // referring to pending node + i->operator++(); + i = iterators->next(); + } + } + if ( prev ) // unlink node + prev->setNext( node->getNext() ); + else + vec[index] = node->getNext(); + numItems--; +} + +QStringBucket *QGDict::unlink_string( const QString &key, QPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + QStringBucket *n; + QStringBucket *prev = 0; + int index = hashKeyString(key) % vlen; + if ( cases ) { + for ( n=(QStringBucket*)vec[index]; n; + n=(QStringBucket*)n->getNext() ) { + bool found = (key == n->getKey()); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + } else { + QString k = key.lower(); + for ( n=(QStringBucket*)vec[index]; n; + n=(QStringBucket*)n->getNext() ) { + bool found = (k == n->getKey().lower()); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + } + return 0; +} + +QAsciiBucket *QGDict::unlink_ascii( const char *key, QPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + QAsciiBucket *n; + QAsciiBucket *prev = 0; + int index = hashKeyAscii(key) % vlen; + for ( n=(QAsciiBucket *)vec[index]; n; n=(QAsciiBucket *)n->getNext() ) { + bool found = (cases ? qstrcmp(n->getKey(),key) + : qstricmp(n->getKey(),key)) == 0; + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + +QIntBucket *QGDict::unlink_int( long key, QPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + QIntBucket *n; + QIntBucket *prev = 0; + int index = (int)((ulong)key % vlen); + for ( n=(QIntBucket *)vec[index]; n; n=(QIntBucket *)n->getNext() ) { + bool found = (n->getKey() == key); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + +QPtrBucket *QGDict::unlink_ptr( void *key, QPtrCollection::Item d ) +{ + if ( numItems == 0 ) // nothing in dictionary + return 0; + QPtrBucket *n; + QPtrBucket *prev = 0; + int index = (int)((ulong)key % vlen); + for ( n=(QPtrBucket *)vec[index]; n; n=(QPtrBucket *)n->getNext() ) { + bool found = (n->getKey() == key); + if ( found && d ) + found = (n->getData() == d); + if ( found ) { + unlink_common(index,n,prev); + return n; + } + prev = n; + } + return 0; +} + + +/*! + Removes the item with the specified \a key. If \a item is not null, + the remove will match the \a item as well (used to remove an + item when several items have the same key). +*/ + +bool QGDict::remove_string( const QString &key, QPtrCollection::Item item ) +{ + QStringBucket *n = unlink_string( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + return TRUE; + } else { + return FALSE; + } +} + +bool QGDict::remove_ascii( const char *key, QPtrCollection::Item item ) +{ + QAsciiBucket *n = unlink_ascii( key, item ); + if ( n ) { + if ( copyk ) + delete [] (char *)n->getKey(); + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +bool QGDict::remove_int( long key, QPtrCollection::Item item ) +{ + QIntBucket *n = unlink_int( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +bool QGDict::remove_ptr( void *key, QPtrCollection::Item item ) +{ + QPtrBucket *n = unlink_ptr( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + +QPtrCollection::Item QGDict::take_string( const QString &key ) +{ + QStringBucket *n = unlink_string( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +QPtrCollection::Item QGDict::take_ascii( const char *key ) +{ + QAsciiBucket *n = unlink_ascii( key ); + Item d; + if ( n ) { + if ( copyk ) + delete [] (char *)n->getKey(); + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +QPtrCollection::Item QGDict::take_int( long key ) +{ + QIntBucket *n = unlink_int( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +QPtrCollection::Item QGDict::take_ptr( void *key ) +{ + QPtrBucket *n = unlink_ptr( key ); + Item d; + if ( n ) { + d = n->getData(); + delete n; + } else { + d = 0; + } + return d; +} + +/*! + Removes all items from the dictionary. +*/ +void QGDict::clear() +{ + if ( !numItems ) + return; + numItems = 0; // disable remove() function + for ( uint j=0; j<vlen; j++ ) { // destroy hash table + if ( vec[j] ) { + switch ( keytype ) { + case StringKey: + { + QStringBucket *n=(QStringBucket *)vec[j]; + while ( n ) { + QStringBucket *next = (QStringBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case AsciiKey: + { + QAsciiBucket *n=(QAsciiBucket *)vec[j]; + while ( n ) { + QAsciiBucket *next = (QAsciiBucket*)n->getNext(); + if ( copyk ) + delete [] (char *)n->getKey(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case IntKey: + { + QIntBucket *n=(QIntBucket *)vec[j]; + while ( n ) { + QIntBucket *next = (QIntBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + case PtrKey: + { + QPtrBucket *n=(QPtrBucket *)vec[j]; + while ( n ) { + QPtrBucket *next = (QPtrBucket*)n->getNext(); + deleteItem( n->getData() ); + delete n; + n = next; + } + } + break; + } + vec[j] = 0; // detach list of buckets + } + } + if ( iterators && iterators->count() ) { // invalidate all iterators + QGDictIterator *i = iterators->first(); + while ( i ) { + i->curNode = 0; + i = iterators->next(); + } + } +} + +/*! + Outputs debug statistics. +*/ +void QGDict::statistics() const +{ +#if defined(QT_DEBUG) + QString line; + line.fill( '-', 60 ); + double real, ideal; + qDebug( line.ascii() ); + qDebug( "DICTIONARY STATISTICS:" ); + if ( count() == 0 ) { + qDebug( "Empty!" ); + qDebug( line.ascii() ); + return; + } + real = 0.0; + ideal = (float)count()/(2.0*size())*(count()+2.0*size()-1); + uint i = 0; + while ( i<size() ) { + QBaseBucket *n = vec[i]; + int b = 0; + while ( n ) { // count number of buckets + b++; + n = n->getNext(); + } + real = real + (double)b * ((double)b+1.0)/2.0; + char buf[80], *pbuf; + if ( b > 78 ) + b = 78; + pbuf = buf; + while ( b-- ) + *pbuf++ = '*'; + *pbuf = '\0'; + qDebug( buf ); + i++; + } + qDebug( "Array size = %d", size() ); + qDebug( "# items = %d", count() ); + qDebug( "Real dist = %g", real ); + qDebug( "Rand dist = %g", ideal ); + qDebug( "Real/Rand = %g", real/ideal ); + qDebug( line.ascii() ); +#endif // QT_DEBUG +} + + +/***************************************************************************** + QGDict stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +QDataStream &operator>>( QDataStream &s, QGDict &dict ) +{ + return dict.read( s ); +} + +QDataStream &operator<<( QDataStream &s, const QGDict &dict ) +{ + return dict.write( s ); +} + +#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001) +#pragma message disable narrowptr +#endif + +/*! + Reads a dictionary from the stream \a s. +*/ + +QDataStream &QGDict::read( QDataStream &s ) +{ + uint num; + s >> num; // read number of items + clear(); // clear dict + while ( num-- ) { // read all items + Item d; + switch ( keytype ) { + case StringKey: + { + QString k; + s >> k; + read( s, d ); + look_string( k, d, op_insert ); + } + break; + case AsciiKey: + { + char *k; + s >> k; + read( s, d ); + look_ascii( k, d, op_insert ); + if ( copyk ) + delete [] k; + } + break; + case IntKey: + { + Q_UINT32 k; + s >> k; + read( s, d ); + look_int( k, d, op_insert ); + } + break; + case PtrKey: + { + Q_UINT32 k; + s >> k; + read( s, d ); + // ### cannot insert 0 - this renders the thing + // useless since all pointers are written as 0, + // but hey, serializing pointers? can it be done + // at all, ever? + if ( k ) + look_ptr( (void *)k, d, op_insert ); + } + break; + } + } + return s; +} + +/*! + Writes the dictionary to the stream \a s. +*/ + +QDataStream& QGDict::write( QDataStream &s ) const +{ + s << count(); // write number of items + uint i = 0; + while ( i<size() ) { + QBaseBucket *n = vec[i]; + while ( n ) { // write all buckets + switch ( keytype ) { + case StringKey: + s << ((QStringBucket*)n)->getKey(); + break; + case AsciiKey: + s << ((QAsciiBucket*)n)->getKey(); + break; + case IntKey: + s << (Q_UINT32)((QIntBucket*)n)->getKey(); + break; + case PtrKey: + s << (Q_UINT32)0; // ### cannot serialize a pointer + break; + } + write( s, n->getData() ); // write data + n = n->getNext(); + } + i++; + } + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + QGDictIterator member functions + *****************************************************************************/ + +/*! + \class QGDictIterator qgdict.h + \reentrant + \ingroup collection + \brief The QGDictIterator class is an internal class for implementing QDictIterator and QIntDictIterator. + + \internal + + QGDictIterator is a strictly internal class that does the heavy work for + QDictIterator and QIntDictIterator. +*/ + +/*! + Constructs an iterator that operates on the dictionary \a d. +*/ + +QGDictIterator::QGDictIterator( const QGDict &d ) +{ + dict = (QGDict *)&d; // get reference to dict + toFirst(); // set to first noe + if ( !dict->iterators ) { + dict->iterators = new QGDItList; // create iterator list + Q_CHECK_PTR( dict->iterators ); + } + dict->iterators->append( this ); // attach iterator to dict +} + +/*! + Constructs a copy of the iterator \a it. +*/ + +QGDictIterator::QGDictIterator( const QGDictIterator &it ) +{ + dict = it.dict; + curNode = it.curNode; + curIndex = it.curIndex; + if ( dict ) + dict->iterators->append( this ); // attach iterator to dict +} + +/*! + Assigns a copy of the iterator \a it and returns a reference to this + iterator. +*/ + +QGDictIterator &QGDictIterator::operator=( const QGDictIterator &it ) +{ + if ( dict ) // detach from old dict + dict->iterators->removeRef( this ); + dict = it.dict; + curNode = it.curNode; + curIndex = it.curIndex; + if ( dict ) + dict->iterators->append( this ); // attach to new list + return *this; +} + +/*! + Destroys the iterator. +*/ + +QGDictIterator::~QGDictIterator() +{ + if ( dict ) // detach iterator from dict + dict->iterators->removeRef( this ); +} + + +/*! + Sets the iterator to point to the first item in the dictionary. +*/ + +QPtrCollection::Item QGDictIterator::toFirst() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGDictIterator::toFirst: Dictionary has been deleted" ); +#endif + return 0; + } + if ( dict->count() == 0 ) { // empty dictionary + curNode = 0; + return 0; + } + register uint i = 0; + register QBaseBucket **v = dict->vec; + while ( !(*v++) ) + i++; + curNode = dict->vec[i]; + curIndex = i; + return curNode->getData(); +} + + +/*! + Moves to the next item (postfix). +*/ + +QPtrCollection::Item QGDictIterator::operator()() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGDictIterator::operator(): Dictionary has been deleted" ); +#endif + return 0; + } + if ( !curNode ) + return 0; + QPtrCollection::Item d = curNode->getData(); + this->operator++(); + return d; +} + +/*! + Moves to the next item (prefix). +*/ + +QPtrCollection::Item QGDictIterator::operator++() +{ + if ( !dict ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGDictIterator::operator++: Dictionary has been deleted" ); +#endif + return 0; + } + if ( !curNode ) + return 0; + curNode = curNode->getNext(); + if ( !curNode ) { // no next bucket + register uint i = curIndex + 1; // look from next vec element + register QBaseBucket **v = &dict->vec[i]; + while ( i < dict->size() && !(*v++) ) + i++; + if ( i == dict->size() ) { // nothing found + curNode = 0; + return 0; + } + curNode = dict->vec[i]; + curIndex = i; + } + return curNode->getData(); +} + +/*! + Moves \a jumps positions forward. +*/ + +QPtrCollection::Item QGDictIterator::operator+=( uint jumps ) +{ + while ( curNode && jumps-- ) + operator++(); + return curNode ? curNode->getData() : 0; +} diff --git a/qmake/tools/qglist.cpp b/qmake/tools/qglist.cpp new file mode 100644 index 0000000..155d585 --- a/dev/null +++ b/qmake/tools/qglist.cpp @@ -0,0 +1,1255 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGList and QGListIterator classes +** +** Created : 920624 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qglist.h" +#include "qgvector.h" +#include "qdatastream.h" +#include "qvaluelist.h" + +/*! + \class QLNode qglist.h + \reentrant + \ingroup collection + \brief The QLNode class is an internal class for the QPtrList template collection. + + \internal + + QLNode is a doubly-linked list node. It has three pointers: + \list 1 + \i Pointer to the previous node. + \i Pointer to the next node. + \i Pointer to the actual data. + \endlist + + It might sometimes be practical to have direct access to the list nodes + in a QPtrList, but it is seldom required. + + Be very careful if you want to access the list nodes. The heap can + easily get corrupted if you make a mistake. + + \sa QPtrList::currentNode(), QPtrList::removeNode(), QPtrList::takeNode() +*/ + +/*! + \fn QPtrCollection::Item QLNode::getData() + Returns a pointer (\c void*) to the actual data in the list node. +*/ + + +/*! + \class QGList qglist.h + \reentrant + \ingroup collection + \brief The QGList class is an internal class for implementing Qt collection classes. + + \internal + + QGList is a strictly internal class that acts as a base class for + several collection classes; QPtrList, QPtrQueue and QPtrStack. + + QGList has some virtual functions that can be reimplemented to + customize the subclasses, namely compareItems(), read() and + write. Normally, you do not have to reimplement any of these + functions. If you still want to reimplement them, see the QStrList + class (qstrlist.h) for an example. +*/ + + +/* Internal helper class for QGList. Contains some optimization for + the typically case where only one iterators is activre on the list. + */ +class QGListIteratorList +{ +public: + QGListIteratorList() + : list(0), iterator(0) { + } + ~QGListIteratorList() { + notifyClear( TRUE ); + delete list; + } + + void add( QGListIterator* i ) { + if ( !iterator ) { + iterator = i; + } else if ( list ) { + list->push_front( i ); + } else { + list = new QValueList<QGListIterator*>; + list->push_front( i ); + } + } + + void remove( QGListIterator* i ) { + if ( iterator == i ) { + iterator = 0; + } else if ( list ) { + list->remove( i ); + if ( list->isEmpty() ) { + delete list; + list = 0; + } + } + } + + void notifyClear( bool zeroList ) { + if ( iterator ) { + if ( zeroList ) + iterator->list = 0; + iterator->curNode = 0; + } + if ( list ) { + for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) { + if ( zeroList ) + (*i)->list = 0; + (*i)->curNode = 0; + } + } + } + + void notifyRemove( QLNode* n, QLNode* curNode ) { + if ( iterator ) { + if ( iterator->curNode == n ) + iterator->curNode = curNode; + } + if ( list ) { + for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) { + if ( (*i)->curNode == n ) + (*i)->curNode = curNode; + } + } + } + +private: + QValueList<QGListIterator*>* list; + QGListIterator* iterator; +}; + + + +/***************************************************************************** + Default implementation of virtual functions + *****************************************************************************/ + +/*! + Documented as QPtrList::compareItems(). + + Compares \a item1 with \a item2. +*/ +int QGList::compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) +{ + return item1 != item2; // compare pointers +} + +#ifndef QT_NO_DATASTREAM +/*! + \overload + Reads a collection/list item from the stream \a s and returns a reference + to the stream. + + The default implementation sets \a item to 0. + + \sa write() +*/ + +QDataStream &QGList::read( QDataStream &s, QPtrCollection::Item &item ) +{ + item = 0; + return s; +} + +/*! + \overload + Writes a collection/list item to the stream \a s and + returns a reference to the stream. + + The default implementation does nothing. + + \sa read() +*/ + +QDataStream &QGList::write( QDataStream &s, QPtrCollection::Item ) const +{ + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QGList member functions + *****************************************************************************/ + +/*! + Constructs an empty list. +*/ + +QGList::QGList() +{ + firstNode = lastNode = curNode = 0; // initialize list + numNodes = 0; + curIndex = -1; + iterators = 0; // initialize iterator list +} + +/*! + Constructs a copy of \a list. +*/ + +QGList::QGList( const QGList & list ) + : QPtrCollection( list ) +{ + firstNode = lastNode = curNode = 0; // initialize list + numNodes = 0; + curIndex = -1; + iterators = 0; // initialize iterator list + QLNode *n = list.firstNode; + while ( n ) { // copy all items from list + append( n->data ); + n = n->next; + } +} + +/*! + Removes all items from the list and destroys the list. +*/ + +QGList::~QGList() +{ + clear(); + delete iterators; + // Workaround for GCC 2.7.* bug. Compiler constructs 'static' QGList + // instances twice on the same address and therefore tries to destruct + // twice on the same address! This is insane but let's try not to crash + // here. + iterators = 0; +} + + +/*! + Assigns \a list to this list. +*/ + +QGList& QGList::operator=( const QGList &list ) +{ + if ( &list == this ) + return *this; + + clear(); + if ( list.count() > 0 ) { + QLNode *n = list.firstNode; + while ( n ) { // copy all items from list + append( n->data ); + n = n->next; + } + curNode = firstNode; + curIndex = 0; + } + return *this; +} + +/*! + Compares this list with \a list. Returns TRUE if the lists + contain the same data, otherwise FALSE. +*/ + +bool QGList::operator==( const QGList &list ) const +{ + if ( count() != list.count() ) + return FALSE; + + if ( count() == 0 ) + return TRUE; + + QLNode *n1 = firstNode; + QLNode *n2 = list.firstNode; + while ( n1 && n2 ) { + // should be mutable + if ( ( (QGList*)this )->compareItems( n1->data, n2->data ) != 0 ) + return FALSE; + n1 = n1->next; + n2 = n2->next; + } + + return TRUE; +} + +/*! + \fn uint QGList::count() const + + Returns the number of items in the list. +*/ + + +/*! + Returns the node at position \a index. Sets this node to current. +*/ + +QLNode *QGList::locate( uint index ) +{ + if ( index == (uint)curIndex ) // current node ? + return curNode; + if ( !curNode && firstNode ) { // set current node + curNode = firstNode; + curIndex = 0; + } + register QLNode *node; + int distance = index - curIndex; // node distance to cur node + bool forward; // direction to traverse + + if ( index >= numNodes ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QGList::locate: Index %d out of range", index ); +#endif + return 0; + } + + if ( distance < 0 ) + distance = -distance; + if ( (uint)distance < index && (uint)distance < numNodes - index ) { + node = curNode; // start from current node + forward = index > (uint)curIndex; + } else if ( index < numNodes - index ) { // start from first node + node = firstNode; + distance = index; + forward = TRUE; + } else { // start from last node + node = lastNode; + distance = numNodes - index - 1; + if ( distance < 0 ) + distance = 0; + forward = FALSE; + } + if ( forward ) { // now run through nodes + while ( distance-- ) + node = node->next; + } else { + while ( distance-- ) + node = node->prev; + } + curIndex = index; // must update index + return curNode = node; +} + + +/*! + Inserts item \a d at its sorted position in the list. +*/ + +void QGList::inSort( QPtrCollection::Item d ) +{ + int index = 0; + register QLNode *n = firstNode; + while ( n && compareItems(n->data,d) < 0 ){ // find position in list + n = n->next; + index++; + } + insertAt( index, d ); +} + + +/*! + Inserts item \a d at the start of the list. +*/ + +void QGList::prepend( QPtrCollection::Item d ) +{ + register QLNode *n = new QLNode( newItem(d) ); + Q_CHECK_PTR( n ); + n->prev = 0; + if ( (n->next = firstNode) ) // list is not empty + firstNode->prev = n; + else // initialize list + lastNode = n; + firstNode = curNode = n; // curNode affected + numNodes++; + curIndex = 0; +} + + +/*! + Inserts item \a d at the end of the list. +*/ + +void QGList::append( QPtrCollection::Item d ) +{ + register QLNode *n = new QLNode( newItem(d) ); + Q_CHECK_PTR( n ); + n->next = 0; + if ( (n->prev = lastNode) ) // list is not empty + lastNode->next = n; + else // initialize list + firstNode = n; + lastNode = curNode = n; // curNode affected + curIndex = numNodes; + numNodes++; +} + + +/*! + Inserts item \a d at position \a index in the list. +*/ + +bool QGList::insertAt( uint index, QPtrCollection::Item d ) +{ + if ( index == 0 ) { + prepend( d ); + return TRUE; + } else if ( index == numNodes ) { + append( d ); + return TRUE; + } + QLNode *nextNode = locate( index ); + if ( !nextNode ) + return FALSE; + QLNode *prevNode = nextNode->prev; + register QLNode *n = new QLNode( newItem(d) ); + Q_CHECK_PTR( n ); + nextNode->prev = n; + prevNode->next = n; + n->prev = prevNode; // link new node into list + n->next = nextNode; + curNode = n; // curIndex set by locate() + numNodes++; + return TRUE; +} + + +/*! + Relinks node \a n and makes it the first node in the list. +*/ + +void QGList::relinkNode( QLNode *n ) +{ + if ( n == firstNode ) // already first + return; + curNode = n; + unlink(); + n->prev = 0; + if ( (n->next = firstNode) ) // list is not empty + firstNode->prev = n; + else // initialize list + lastNode = n; + firstNode = curNode = n; // curNode affected + numNodes++; + curIndex = 0; +} + + +/*! + Unlinks the current list node and returns a pointer to this node. +*/ + +QLNode *QGList::unlink() +{ + if ( curNode == 0 ) // null current node + return 0; + register QLNode *n = curNode; // unlink this node + if ( n == firstNode ) { // removing first node ? + if ( (firstNode = n->next) ) { + firstNode->prev = 0; + } else { + lastNode = curNode = 0; // list becomes empty + curIndex = -1; + } + } else { + if ( n == lastNode ) { // removing last node ? + lastNode = n->prev; + lastNode->next = 0; + } else { // neither last nor first node + n->prev->next = n->next; + n->next->prev = n->prev; + } + } + + if ( n->next ) { // change current node + curNode = n->next; + } else if ( n->prev ) { + curNode = n->prev; + curIndex--; + } + + if ( iterators ) + iterators->notifyRemove( n, curNode ); + numNodes--; + return n; +} + + +/*! + Removes the node \a n from the list. +*/ + +bool QGList::removeNode( QLNode *n ) +{ +#if defined(QT_CHECK_NULL) + if ( n == 0 || (n->prev && n->prev->next != n) || + (n->next && n->next->prev != n) ) { + qWarning( "QGList::removeNode: Corrupted node" ); + return FALSE; + } +#endif + curNode = n; + unlink(); // unlink node + deleteItem( n->data ); // deallocate this node + delete n; + curNode = firstNode; + curIndex = curNode ? 0 : -1; + return TRUE; +} + +/*! + Removes the item \a d from the list. Uses compareItems() to find the item. + + If \a d is 0, removes the current item. +*/ + +bool QGList::remove( QPtrCollection::Item d ) +{ + if ( d && find(d) == -1 ) + return FALSE; + QLNode *n = unlink(); + if ( !n ) + return FALSE; + deleteItem( n->data ); + delete n; + return TRUE; +} + +/*! + Removes the item \a d from the list. +*/ + +bool QGList::removeRef( QPtrCollection::Item d ) +{ + if ( findRef(d) == -1 ) + return FALSE; + QLNode *n = unlink(); + if ( !n ) + return FALSE; + deleteItem( n->data ); + delete n; + return TRUE; +} + +/*! + \fn bool QGList::removeFirst() + + Removes the first item in the list. +*/ + +/*! + \fn bool QGList::removeLast() + + Removes the last item in the list. +*/ + +/*! + Removes the item at position \a index from the list. +*/ + +bool QGList::removeAt( uint index ) +{ + if ( !locate(index) ) + return FALSE; + QLNode *n = unlink(); + if ( !n ) + return FALSE; + deleteItem( n->data ); + delete n; + return TRUE; +} + + +/*! + Replaces the item at index \a index with \a d. +*/ +bool QGList::replaceAt( uint index, QPtrCollection::Item d ) +{ + QLNode *n = locate( index ); + if ( !n ) + return FALSE; + if ( n->data != d ) { + deleteItem( n->data ); + n->data = newItem( d ); + } + return TRUE; +} + + + +/*! + Takes the node \a n out of the list. +*/ + +QPtrCollection::Item QGList::takeNode( QLNode *n ) +{ +#if defined(QT_CHECK_NULL) + if ( n == 0 || (n->prev && n->prev->next != n) || + (n->next && n->next->prev != n) ) { + qWarning( "QGList::takeNode: Corrupted node" ); + return 0; + } +#endif + curNode = n; + unlink(); // unlink node + Item d = n->data; + delete n; // delete the node, not data + curNode = firstNode; + curIndex = curNode ? 0 : -1; + return d; +} + +/*! + Takes the current item out of the list. +*/ + +QPtrCollection::Item QGList::take() +{ + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; // delete node, keep contents + return d; +} + +/*! + Takes the item at position \a index out of the list. +*/ + +QPtrCollection::Item QGList::takeAt( uint index ) +{ + if ( !locate(index) ) + return 0; + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; // delete node, keep contents + return d; +} + +/*! + Takes the first item out of the list. +*/ + +QPtrCollection::Item QGList::takeFirst() +{ + first(); + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; + return d; +} + +/*! + Takes the last item out of the list. +*/ + +QPtrCollection::Item QGList::takeLast() +{ + last(); + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; + return d; +} + + +/*! + Removes all items from the list. +*/ + +void QGList::clear() +{ + register QLNode *n = firstNode; + + firstNode = lastNode = curNode = 0; // initialize list + numNodes = 0; + curIndex = -1; + + if ( iterators ) + iterators->notifyClear( FALSE ); + + QLNode *prevNode; + while ( n ) { // for all nodes ... + deleteItem( n->data ); // deallocate data + prevNode = n; + n = n->next; + delete prevNode; // deallocate node + } +} + + +/*! + Finds item \a d in the list. If \a fromStart is TRUE the search + begins at the first node; otherwise it begins at the current node. +*/ + +int QGList::findRef( QPtrCollection::Item d, bool fromStart ) +{ + register QLNode *n; + int index; + if ( fromStart ) { // start from first node + n = firstNode; + index = 0; + } else { // start from current node + n = curNode; + index = curIndex; + } + while ( n && n->data != d ) { // find exact match + n = n->next; + index++; + } + curNode = n; + curIndex = n ? index : -1; + return curIndex; // return position of item +} + +/*! + Finds item \a d in the list using compareItems(). If \a fromStart is + TRUE the search begins at the first node; otherwise it begins at the + current node. +*/ + +int QGList::find( QPtrCollection::Item d, bool fromStart ) +{ + register QLNode *n; + int index; + if ( fromStart ) { // start from first node + n = firstNode; + index = 0; + } else { // start from current node + n = curNode; + index = curIndex; + } + while ( n && compareItems(n->data,d) ){ // find equal match + n = n->next; + index++; + } + curNode = n; + curIndex = n ? index : -1; + return curIndex; // return position of item +} + + +/*! + Counts the number item \a d occurs in the list. +*/ + +uint QGList::containsRef( QPtrCollection::Item d ) const +{ + register QLNode *n = firstNode; + uint count = 0; + while ( n ) { // for all nodes... + if ( n->data == d ) // count # exact matches + count++; + n = n->next; + } + return count; +} + +/*! + Counts the number of times item \a d occurs in the list. Uses + compareItems(). +*/ + +uint QGList::contains( QPtrCollection::Item d ) const +{ + register QLNode *n = firstNode; + uint count = 0; + QGList *that = (QGList*)this; // mutable for compareItems() + while ( n ) { // for all nodes... + if ( !that->compareItems(n->data,d) ) // count # equal matches + count++; + n = n->next; + } + return count; +} + + +/*! + \overload QPtrCollection::Item QGList::at( uint index ) + + Sets the item at position \a index to the current item. +*/ + +/*! + \fn int QGList::at() const + + Returns the current index. +*/ + +/*! + \fn QLNode *QGList::currentNode() const + + Returns the current node. +*/ + +/*! + \fn QPtrCollection::Item QGList::get() const + + Returns the current item. +*/ + +/*! + \fn QPtrCollection::Item QGList::cfirst() const + + Returns the first item in the list. +*/ + +/*! + \fn QPtrCollection::Item QGList::clast() const + + Returns the last item in the list. +*/ + + +/*! + Returns the first list item. Sets this to current. +*/ + +QPtrCollection::Item QGList::first() +{ + if ( firstNode ) { + curIndex = 0; + return (curNode=firstNode)->data; + } + return 0; +} + +/*! + Returns the last list item. Sets this to current. +*/ + +QPtrCollection::Item QGList::last() +{ + if ( lastNode ) { + curIndex = numNodes-1; + return (curNode=lastNode)->data; + } + return 0; +} + +/*! + Returns the next list item (after current). Sets this to current. +*/ + +QPtrCollection::Item QGList::next() +{ + if ( curNode ) { + if ( curNode->next ) { + curIndex++; + curNode = curNode->next; + return curNode->data; + } + curIndex = -1; + curNode = 0; + } + return 0; +} + +/*! + Returns the previous list item (before current). Sets this to current. +*/ + +QPtrCollection::Item QGList::prev() +{ + if ( curNode ) { + if ( curNode->prev ) { + curIndex--; + curNode = curNode->prev; + return curNode->data; + } + curIndex = -1; + curNode = 0; + } + return 0; +} + + +/*! + Converts the list to a vector, \a vector. +*/ + +void QGList::toVector( QGVector *vector ) const +{ + vector->clear(); + if ( !vector->resize( count() ) ) + return; + register QLNode *n = firstNode; + uint i = 0; + while ( n ) { + vector->insert( i, n->data ); + n = n->next; + i++; + } +} + +void QGList::heapSortPushDown( QPtrCollection::Item* heap, int first, int last ) +{ + int r = first; + while( r <= last/2 ) { + // Node r has only one child ? + if ( last == 2*r ) { + // Need for swapping ? + if ( compareItems( heap[r], heap[ 2*r ] ) > 0 ) { + QPtrCollection::Item tmp = heap[r]; + heap[ r ] = heap[ 2*r ]; + heap[ 2*r ] = tmp; + } + // That's it ... + r = last; + } else { + // Node has two children + if ( compareItems( heap[r], heap[ 2*r ] ) > 0 && + compareItems( heap[ 2*r ], heap[ 2*r+1 ] ) <= 0 ) { + // Swap with left child + QPtrCollection::Item tmp = heap[r]; + heap[ r ] = heap[ 2*r ]; + heap[ 2*r ] = tmp; + r *= 2; + } else if ( compareItems( heap[r], heap[ 2*r+1 ] ) > 0 && + compareItems( heap[ 2*r+1 ], heap[ 2*r ] ) < 0 ) { + // Swap with right child + QPtrCollection::Item tmp = heap[r]; + heap[ r ] = heap[ 2*r+1 ]; + heap[ 2*r+1 ] = tmp; + r = 2*r+1; + } else { + // We are done + r = last; + } + } + } +} + + +/*! Sorts the list by the result of the virtual compareItems() function. + + The Heap-Sort algorithm is used for sorting. It sorts n items with + O(n*log n) compares. This is the asymptotic optimal solution of the + sorting problem. +*/ + +void QGList::sort() +{ + uint n = count(); + if ( n < 2 ) + return; + + // Create the heap + QPtrCollection::Item* realheap = new QPtrCollection::Item[ n ]; + // Wow, what a fake. But I want the heap to be indexed as 1...n + QPtrCollection::Item* heap = realheap - 1; + int size = 0; + QLNode* insert = firstNode; + for( ; insert != 0; insert = insert->next ) { + heap[++size] = insert->data; + int i = size; + while( i > 1 && compareItems( heap[i], heap[ i / 2 ] ) < 0 ) { + QPtrCollection::Item tmp = heap[ i ]; + heap[ i ] = heap[ i/2 ]; + heap[ i/2 ] = tmp; + i /= 2; + } + } + + insert = firstNode; + // Now do the sorting + for ( int i = n; i > 0; i-- ) { + insert->data = heap[1]; + insert = insert->next; + if ( i > 1 ) { + heap[1] = heap[i]; + heapSortPushDown( heap, 1, i - 1 ); + } + } + + delete [] realheap; +} + + +/***************************************************************************** + QGList stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +QDataStream &operator>>( QDataStream &s, QGList &list ) +{ // read list + return list.read( s ); +} + +QDataStream &operator<<( QDataStream &s, const QGList &list ) +{ // write list + return list.write( s ); +} + +/*! + Reads a list from the stream \a s. +*/ + +QDataStream &QGList::read( QDataStream &s ) +{ + uint num; + s >> num; // read number of items + clear(); // clear list + while ( num-- ) { // read all items + Item d; + read( s, d ); + Q_CHECK_PTR( d ); + if ( !d ) // no memory + break; + QLNode *n = new QLNode( d ); + Q_CHECK_PTR( n ); + if ( !n ) // no memory + break; + n->next = 0; + if ( (n->prev = lastNode) ) // list is not empty + lastNode->next = n; + else // initialize list + firstNode = n; + lastNode = n; + numNodes++; + } + curNode = firstNode; + curIndex = curNode ? 0 : -1; + return s; +} + +/*! + Writes the list to the stream \a s. +*/ + +QDataStream &QGList::write( QDataStream &s ) const +{ + s << count(); // write number of items + QLNode *n = firstNode; + while ( n ) { // write all items + write( s, n->data ); + n = n->next; + } + return s; +} + +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QGListIterator member functions + *****************************************************************************/ + +/*! + \class QGListIterator qglist.h + \reentrant + \ingroup collection + \brief The QGListIterator class is an internal class for implementing QPtrListIterator. + + \internal + + QGListIterator is a strictly internal class that does the heavy work for + QPtrListIterator. +*/ + +/*! + \internal + Constructs an iterator that operates on the list \a l. +*/ + +QGListIterator::QGListIterator( const QGList &l ) +{ + list = (QGList *)&l; // get reference to list + curNode = list->firstNode; // set to first node + if ( !list->iterators ) { + list->iterators = new QGListIteratorList; // create iterator list + Q_CHECK_PTR( list->iterators ); + } + list->iterators->add( this ); // attach iterator to list +} + +/*! + \internal + Constructs a copy of the iterator \a it. +*/ + +QGListIterator::QGListIterator( const QGListIterator &it ) +{ + list = it.list; + curNode = it.curNode; + if ( list ) + list->iterators->add( this ); // attach iterator to list +} + +/*! + \internal + Assigns a copy of the iterator \a it and returns a reference to this + iterator. +*/ + +QGListIterator &QGListIterator::operator=( const QGListIterator &it ) +{ + if ( list ) // detach from old list + list->iterators->remove( this ); + list = it.list; + curNode = it.curNode; + if ( list ) + list->iterators->add( this ); // attach to new list + return *this; +} + +/*! + \internal + Destroys the iterator. +*/ + +QGListIterator::~QGListIterator() +{ + if ( list ) // detach iterator from list + list->iterators->remove(this); +} + + +/*! + \fn bool QGListIterator::atFirst() const + \internal + Returns TRUE if the iterator points to the first item, otherwise FALSE. +*/ + +/*! + \fn bool QGListIterator::atLast() const + \internal + Returns TRUE if the iterator points to the last item, otherwise FALSE. +*/ + + +/*! + \internal + Sets the list iterator to point to the first item in the list. +*/ + +QPtrCollection::Item QGListIterator::toFirst() +{ + if ( !list ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGListIterator::toFirst: List has been deleted" ); +#endif + return 0; + } + return list->firstNode ? (curNode = list->firstNode)->getData() : 0; +} + +/*! + \internal + Sets the list iterator to point to the last item in the list. +*/ + +QPtrCollection::Item QGListIterator::toLast() +{ + if ( !list ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGListIterator::toLast: List has been deleted" ); +#endif + return 0; + } + return list->lastNode ? (curNode = list->lastNode)->getData() : 0; +} + + +/*! + \fn QPtrCollection::Item QGListIterator::get() const + \internal + Returns the iterator item. +*/ + + +/*! + \internal + Moves to the next item (postfix). +*/ + +QPtrCollection::Item QGListIterator::operator()() +{ + if ( !curNode ) + return 0; + QPtrCollection::Item d = curNode->getData(); + curNode = curNode->next; + return d; +} + +/*! + \internal + Moves to the next item (prefix). +*/ + +QPtrCollection::Item QGListIterator::operator++() +{ + if ( !curNode ) + return 0; + curNode = curNode->next; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves \a jumps positions forward. +*/ + +QPtrCollection::Item QGListIterator::operator+=( uint jumps ) +{ + while ( curNode && jumps-- ) + curNode = curNode->next; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves to the previous item (prefix). +*/ + +QPtrCollection::Item QGListIterator::operator--() +{ + if ( !curNode ) + return 0; + curNode = curNode->prev; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves \a jumps positions backward. +*/ + +QPtrCollection::Item QGListIterator::operator-=( uint jumps ) +{ + while ( curNode && jumps-- ) + curNode = curNode->prev; + return curNode ? curNode->getData() : 0; +} diff --git a/qmake/tools/qglobal.cpp b/qmake/tools/qglobal.cpp new file mode 100644 index 0000000..47cd6bd --- a/dev/null +++ b/qmake/tools/qglobal.cpp @@ -0,0 +1,835 @@ +/**************************************************************************** +** $Id$ +** +** Global functions +** +** Created : 920604 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +#include "qasciidict.h" +#include <limits.h> +#include <stdio.h> +#include <limits.h> +#include <stdarg.h> +#include <stdlib.h> + + +/*! + \relates QApplication + + Returns the Qt version number as a string, for example, "2.3.0" or + "3.0.5". + + The \c QT_VERSION define has the numeric value in the form: + 0xmmiibb (m = major, i = minor, b = bugfix). For example, Qt + 3.0.5's \c QT_VERSION is 0x030005. +*/ + +const char *qVersion() +{ + return QT_VERSION_STR; +} + + +/***************************************************************************** + System detection routines + *****************************************************************************/ + +static bool si_alreadyDone = FALSE; +static int si_wordSize; +static bool si_bigEndian; + +/*! + \relates QApplication + + Obtains information about the system. + + The system's word size in bits (typically 32) is returned in \a + *wordSize. The \a *bigEndian is set to TRUE if this is a big-endian + machine, or to FALSE if this is a little-endian machine. + + In debug mode, this function calls qFatal() with a message if the + computer is truly weird (i.e. different endianness for 16 bit and + 32 bit integers); in release mode it returns FALSE. +*/ + +bool qSysInfo( int *wordSize, bool *bigEndian ) +{ +#if defined(QT_CHECK_NULL) + Q_ASSERT( wordSize != 0 ); + Q_ASSERT( bigEndian != 0 ); +#endif + + if ( si_alreadyDone ) { // run it only once + *wordSize = si_wordSize; + *bigEndian = si_bigEndian; + return TRUE; + } + + si_wordSize = 0; + Q_ULONG n = (Q_ULONG)(~0); + while ( n ) { // detect word size + si_wordSize++; + n /= 2; + } + *wordSize = si_wordSize; + + if ( *wordSize != 64 && + *wordSize != 32 && + *wordSize != 16 ) { // word size: 16, 32 or 64 +#if defined(QT_CHECK_RANGE) + qFatal( "qSysInfo: Unsupported system word size %d", *wordSize ); +#endif + return FALSE; + } + if ( sizeof(Q_INT8) != 1 || sizeof(Q_INT16) != 2 || sizeof(Q_INT32) != 4 || + sizeof(Q_ULONG)*8 != si_wordSize || sizeof(float) != 4 || sizeof(double) != 8 ) { +#if defined(QT_CHECK_RANGE) + qFatal( "qSysInfo: Unsupported system data type size" ); +#endif + return FALSE; + } + + bool be16, be32; // determine byte ordering + short ns = 0x1234; + int nl = 0x12345678; + + unsigned char *p = (unsigned char *)(&ns); // 16-bit integer + be16 = *p == 0x12; + + p = (unsigned char *)(&nl); // 32-bit integer + if ( p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78 ) + be32 = TRUE; + else + if ( p[0] == 0x78 && p[1] == 0x56 && p[2] == 0x34 && p[3] == 0x12 ) + be32 = FALSE; + else + be32 = !be16; + + if ( be16 != be32 ) { // strange machine! +#if defined(QT_CHECK_RANGE) + qFatal( "qSysInfo: Inconsistent system byte order" ); +#endif + return FALSE; + } + + *bigEndian = si_bigEndian = be32; + si_alreadyDone = TRUE; + return TRUE; +} + +#if defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN) +bool qt_winunicode; + +#include "qt_windows.h" + +int qWinVersion() +{ +#ifndef VER_PLATFORM_WIN32s +#define VER_PLATFORM_WIN32s 0 +#endif +#ifndef VER_PLATFORM_WIN32_WINDOWS +#define VER_PLATFORM_WIN32_WINDOWS 1 +#endif +#ifndef VER_PLATFORM_WIN32_NT +#define VER_PLATFORM_WIN32_NT 2 +#endif + + static int winver = Qt::WV_NT; + static int t=0; + if ( !t ) { + t=1; +#ifdef Q_OS_TEMP + OSVERSIONINFOW osver; + osver.dwOSVersionInfoSize = sizeof(osver); + GetVersionEx( &osver ); +#else + OSVERSIONINFOA osver; + osver.dwOSVersionInfoSize = sizeof(osver); + GetVersionExA( &osver ); +#endif + switch ( osver.dwPlatformId ) { + case VER_PLATFORM_WIN32s: + winver = Qt::WV_32s; + break; + case VER_PLATFORM_WIN32_WINDOWS: + // We treat Windows Me (minor 90) the same as Windows 98 + if ( ( osver.dwMinorVersion == 10 ) || ( osver.dwMinorVersion == 90 ) ) + winver = Qt::WV_98; + else + winver = Qt::WV_95; + break; + default: // VER_PLATFORM_WIN32_NT + if ( osver.dwMajorVersion < 5 ) { + winver = Qt::WV_NT; + } else if ( osver.dwMinorVersion == 0 ) { + winver = Qt::WV_2000; + } else { + winver = Qt::WV_XP; + } + } + } + +#if defined(UNICODE) + if ( winver & Qt::WV_NT_based ) + qt_winunicode = TRUE; + else +#endif + qt_winunicode = FALSE; + + return winver; +} + +Qt::WindowsVersion qt_winver = (Qt::WindowsVersion)qWinVersion(); +#endif + + +/***************************************************************************** + Debug output routines + *****************************************************************************/ + +/*! + \fn void qDebug( const char *msg, ... ) + + \relates QApplication + + Prints a debug message \a msg, or calls the message handler (if it + has been installed). + + This function takes a format string and a list of arguments, + similar to the C printf() function. + + Example: + \code + qDebug( "my window handle = %x", myWidget->id() ); + \endcode + + Under X11, the text is printed to stderr. Under Windows, the text + is sent to the debugger. + + \warning The internal buffer is limited to 8196 bytes (including + the '\0'-terminator). + + \warning Passing (const char *)0 as argument to qDebug might lead + to crashes on certain platforms due to the platforms printf implementation. + + \sa qWarning(), qFatal(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + +/*! + \fn void qWarning( const char *msg, ... ) + + \relates QApplication + + Prints a warning message \a msg, or calls the message handler (if + it has been installed). + + This function takes a format string and a list of arguments, + similar to the C printf() function. + + Example: + \code + void f( int c ) + { + if ( c > 200 ) + qWarning( "f: bad argument, c == %d", c ); + } + \endcode + + Under X11, the text is printed to stderr. Under Windows, the text + is sent to the debugger. + + \warning The internal buffer is limited to 8196 bytes (including + the '\0'-terminator). + + \warning Passing (const char *)0 as argument to qWarning might lead + to crashes on certain platforms due to the platforms printf implementation. + + \sa qDebug(), qFatal(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + +/*! + \fn void qFatal( const char *msg, ... ) + + \relates QApplication + + Prints a fatal error message \a msg and exits, or calls the + message handler (if it has been installed). + + This function takes a format string and a list of arguments, + similar to the C printf() function. + + Example: + \code + int divide( int a, int b ) + { + if ( b == 0 ) // program error + qFatal( "divide: cannot divide by zero" ); + return a/b; + } + \endcode + + Under X11, the text is printed to stderr. Under Windows, the text + is sent to the debugger. + + \warning The internal buffer is limited to 8196 bytes (including + the '\0'-terminator). + + \warning Passing (const char *)0 as argument to qFatal might lead + to crashes on certain platforms due to the platforms printf implementation. + + \sa qDebug(), qWarning(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + + +static QtMsgHandler handler = 0; // pointer to debug handler +static const int QT_BUFFER_LENGTH = 8196; // internal buffer length + + +#ifdef Q_OS_MAC +const unsigned char * p_str(const char * c, int len=-1) +{ + const int maxlen = 255; + if(len == -1) + len = qstrlen(c); + if(len > maxlen) { + qWarning( "p_str len must never exceed %d", maxlen ); + len = maxlen; + } + unsigned char *ret = (unsigned char*)malloc(len+2); + *ret=len; + memcpy(((char *)ret)+1,c,len); + *(ret+len+1) = '\0'; + return ret; +} + +const unsigned char * p_str(const QString &s) +{ + return p_str(s, s.length()); +} + +QCString p2qstring(const unsigned char *c) { + char *arr = (char *)malloc(c[0] + 1); + memcpy(arr, c+1, c[0]); + arr[c[0]] = '\0'; + QCString ret = arr; + delete arr; + return ret; +} +#endif + + +#ifdef Q_CC_MWERKS + +#include "qt_mac.h" + +extern bool qt_is_gui_used; +static void mac_default_handler( const char *msg ) +{ + if ( qt_is_gui_used ) { + const char *p = p_str(msg); + DebugStr(p); + free(p); + } else { + fprintf( stderr, msg ); + } +} + +#endif + + +void qDebug( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { +#if defined(Q_CC_MWERKS) + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif + } +} + +// copied... this looks really bad. +void debug( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { +#ifdef Q_CC_MWERKS + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif + } +} + +void qWarning( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtWarningMsg, buf ); + } else { +#ifdef Q_CC_MWERKS + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif + } +} + + +// again, copied +void warning( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtWarningMsg, buf ); + } else { +#ifdef Q_CC_MWERKS + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif + } +} + +void qFatal( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtFatalMsg, buf ); + } else { +#ifdef Q_CC_MWERKS + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit( 1 ); // goodbye cruel world +#endif + } +} + +// yet again, copied +void fatal( const char *msg, ... ) +{ + char buf[QT_BUFFER_LENGTH]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { +#if defined(QT_VSNPRINTF) + QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); +#else + vsprintf( buf, msg, ap ); +#endif + va_end( ap ); + (*handler)( QtFatalMsg, buf ); + } else { +#ifdef Q_CC_MWERKS + vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? + va_end( ap ); + mac_default_handler(buf); +#else + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#endif +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit( 1 ); // goodbye cruel world +#endif + } +} + +/*! + \relates QApplication + + Prints the message \a msg and uses \a code to get a system specific + error message. When \a code is -1 (the default), the system's last + error code will be used if possible. Use this method to handle + failures in platform specific API calls. + + This function does nothing when Qt is built with \c QT_NO_DEBUG + defined. +*/ +void qSystemWarning( const char* msg, int code ) +{ +#ifndef QT_NO_DEBUG +#if defined(Q_OS_WIN32) + if ( code == -1 ) + code = GetLastError(); + + if ( !code ) + return; + +#ifdef Q_OS_TEMP + unsigned short *string; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&string, + 0, + NULL ); + + qWarning( "%s\n\tError code %d - %s (###may need fixing in qglobal.h)", msg, code, (const char *)string ); +#else + char* string; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char*)&string, + 0, + NULL ); + + qWarning( "%s\n\tError code %d - %s", msg, code, (const char*)string ); +#endif + + LocalFree( (HLOCAL)string ); +#else + if ( code != -1 ) + qWarning( "%s\n\tError code %d - %s", msg, code, strerror( code ) ); + else + qWarning( msg ); +#endif +#endif +} + +/*! + \fn void Q_ASSERT( bool test ) + + \relates QApplication + + Prints a warning message containing the source code file name and + line number if \a test is FALSE. + + This is really a macro defined in \c qglobal.h. + + Q_ASSERT is useful for testing pre- and post-conditions. + + Example: + \code + // + // File: div.cpp + // + + #include <qglobal.h> + + int divide( int a, int b ) + { + Q_ASSERT( b != 0 ); // this is line 9 + return a/b; + } + \endcode + + If \c b is zero, the Q_ASSERT statement will output the following + message using the qWarning() function: + \code + ASSERT: "b == 0" in div.cpp (9) + \endcode + + \sa qWarning(), \link debug.html Debugging\endlink +*/ + + +/*! + \fn void Q_CHECK_PTR( void *p ) + + \relates QApplication + + If \a p is null, a fatal messages says that the program ran out of + memory and exits. If \e p is not null, nothing happens. + + This is really a macro defined in \c qglobal.h. + + Example: + \code + int *a; + + Q_CHECK_PTR( a = new int[80] ); // WRONG! + + a = new int[80]; // Right + Q_CHECK_PTR( a ); + \endcode + + \sa qFatal(), \link debug.html Debugging\endlink +*/ + + +// +// The Q_CHECK_PTR macro calls this function to check if an allocation went ok. +// +#if (QT_VERSION-0 >= 0x040000) +#if defined(Q_CC_GNU) +#warning "Change Q_CHECK_PTR to '{if ((p)==0) qt_check_pointer(__FILE__,__LINE__);}'" +#warning "No need for qt_check_pointer() to return a value - make it void!" +#endif +#endif +bool qt_check_pointer( bool c, const char *n, int l ) +{ + if ( c ) + qWarning( "In file %s, line %d: Out of memory", n, l ); + return TRUE; +} + + +static bool firstObsoleteWarning(const char *obj, const char *oldfunc ) +{ + static QAsciiDict<int> *obsoleteDict = 0; + if ( !obsoleteDict ) { // first time func is called + obsoleteDict = new QAsciiDict<int>; +#if defined(QT_DEBUG) + qDebug( + "You are using obsolete functions in the Qt library. Call the function\n" + "qSuppressObsoleteWarnings() to suppress obsolete warnings.\n" + ); +#endif + } + QCString s( obj ); + s += "::"; + s += oldfunc; + if ( obsoleteDict->find(s.data()) == 0 ) { + obsoleteDict->insert( s.data(), (int*)1 ); // anything different from 0 + return TRUE; + } + return FALSE; +} + +static bool suppressObsolete = FALSE; + +void qSuppressObsoleteWarnings( bool suppress ) +{ + suppressObsolete = suppress; +} + +void qObsolete( const char *obj, const char *oldfunc, const char *newfunc ) +{ + if ( suppressObsolete ) + return; + if ( !firstObsoleteWarning(obj, oldfunc) ) + return; + if ( obj ) + qDebug( "%s::%s: This function is obsolete, use %s instead.", + obj, oldfunc, newfunc ); + else + qDebug( "%s: This function is obsolete, use %s instead.", + oldfunc, newfunc ); +} + +void qObsolete( const char *obj, const char *oldfunc ) +{ + if ( suppressObsolete ) + return; + if ( !firstObsoleteWarning(obj, oldfunc) ) + return; + if ( obj ) + qDebug( "%s::%s: This function is obsolete.", obj, oldfunc ); + else + qDebug( "%s: This function is obsolete.", oldfunc ); +} + +void qObsolete( const char *message ) +{ + if ( suppressObsolete ) + return; + if ( !firstObsoleteWarning( "Qt", message) ) + return; + qDebug( "%s", message ); +} + + +/*! + \relates QApplication + + Installs a Qt message handler \a h. Returns a pointer to the + message handler previously defined. + + The message handler is a function that prints out debug messages, + warnings and fatal error messages. The Qt library (debug version) + contains hundreds of warning messages that are printed when + internal errors (usually invalid function arguments) occur. If you + implement your own message handler, you get total control of these + messages. + + The default message handler prints the message to the standard + output under X11 or to the debugger under Windows. If it is a + fatal message, the application aborts immediately. + + Only one message handler can be defined, since this is usually + done on an application-wide basis to control debug output. + + To restore the message handler, call \c qInstallMsgHandler(0). + + Example: + \code + #include <qapplication.h> + #include <stdio.h> + #include <stdlib.h> + + void myMessageOutput( QtMsgType type, const char *msg ) + { + switch ( type ) { + case QtDebugMsg: + fprintf( stderr, "Debug: %s\n", msg ); + break; + case QtWarningMsg: + fprintf( stderr, "Warning: %s\n", msg ); + break; + case QtFatalMsg: + fprintf( stderr, "Fatal: %s\n", msg ); + abort(); // deliberately core dump + } + } + + int main( int argc, char **argv ) + { + qInstallMsgHandler( myMessageOutput ); + QApplication a( argc, argv ); + ... + return a.exec(); + } + \endcode + + \sa qDebug(), qWarning(), qFatal(), \link debug.html Debugging\endlink +*/ + +QtMsgHandler qInstallMsgHandler( QtMsgHandler h ) +{ + QtMsgHandler old = handler; + handler = h; + return old; +} + + +/* + Dijkstra's bisection algorithm to find the square root as an integer. + Deliberately not exported as part of the Qt API, but used in both + qsimplerichtext.cpp and qgfxraster_qws.cpp +*/ +unsigned int qt_int_sqrt( unsigned int n ) +{ + // n must be in the range 0...UINT_MAX/2-1 + if ( n >= ( UINT_MAX>>2 ) ) { + unsigned int r = 2 * qt_int_sqrt( n / 4 ); + unsigned int r2 = r + 1; + return ( n >= r2 * r2 ) ? r2 : r; + } + uint h, p= 0, q= 1, r= n; + while ( q <= n ) + q <<= 2; + while ( q != 1 ) { + q >>= 2; + h= p + q; + p >>= 1; + if ( r >= h ) { + p += q; + r -= h; + } + } + return p; +} + diff --git a/qmake/tools/qgpluginmanager.cpp b/qmake/tools/qgpluginmanager.cpp new file mode 100644 index 0000000..46c85f5 --- a/dev/null +++ b/qmake/tools/qgpluginmanager.cpp @@ -0,0 +1,544 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGPluginManager class +** +** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qgpluginmanager_p.h" +#ifndef QT_NO_COMPONENT +#include "qcomlibrary_p.h" +#include "qmap.h" +#include "qdir.h" + +/* + The following co-occurrence code is borrowed from Qt Linguist. + + How similar are two texts? The approach used here relies on + co-occurrence matrices and is very efficient. + + Let's see with an example: how similar are "here" and "hither"? The + co-occurrence matrix M for "here" is M[h,e] = 1, M[e,r] = 1, + M[r,e] = 1 and 0 elsewhere; the matrix N for "hither" is N[h,i] = 1, + N[i,t] = 1, ..., N[h,e] = 1, N[e,r] = 1 and 0 elsewhere. The union + U of both matrices is the matrix U[i,j] = max { M[i,j], N[i,j] }, + and the intersection V is V[i,j] = min { M[i,j], N[i,j] }. The score + for a pair of texts is + + score = (sum of V[i,j] over all i, j) / (sum of U[i,j] over all i, j), + + a formula suggested by Arnt Gulbrandsen. Here we have + + score = 2 / 6, + + or one third. + + The implementation differs from this in a few details. Most + importantly, repetitions are ignored; for input "xxx", M[x,x] equals + 1, not 2. +*/ + +/* + Every character is assigned to one of 20 buckets so that the + co-occurrence matrix requires only 20 * 20 = 400 bits, not + 256 * 256 = 65536 bits or even more if we want the whole Unicode. + Which character falls in which bucket is arbitrary. + + The second half of the table is a replica of the first half, because of + laziness. +*/ +static const char indexOf[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +// ! " # $ % & ' ( ) * + , - . / + 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, +// @ A B C D E F G H I J K L M N O + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, +// P Q R S T U V W X Y Z [ \ ] ^ _ + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, +// ` a b c d e f g h i j k l m n o + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, +// p q r s t u v w x y z { | } ~ + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, + 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0 +}; + +/* + The entry bitCount[i] (for i between 0 and 255) is the number of + bits used to represent i in binary. +*/ +static const char bitCount[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +class QCoMatrix +{ +public: + /* + The matrix has 20 * 20 = 400 entries. This requires 50 bytes, or + 13 words. Some operations are performed on words for more + efficiency. + */ + union { + Q_UINT8 b[52]; + Q_UINT32 w[13]; + }; + + QCoMatrix() { memset( b, 0, 52 ); } + QCoMatrix( const char *text ) { + char c = '\0', d; + memset( b, 0, 52 ); + while ( (d = *text) != '\0' ) { + setCoocc( c, d ); + if ( (c = *++text) != '\0' ) { + setCoocc( d, c ); + text++; + } + } + } + + void setCoocc( char c, char d ) { + int k = indexOf[(uchar) c] + 20 * indexOf[(uchar) d]; + b[k >> 3] |= k & 0x7; + } + + int worth() const { + int result = 0; + for ( int i = 0; i < 50; i++ ) + result += bitCount[b[i]]; + return result; + } + + static QCoMatrix reunion( const QCoMatrix& m, const QCoMatrix& n ) + { + QCoMatrix p; + for ( int i = 0; i < 13; i++ ) + p.w[i] = m.w[i] | n.w[i]; + return p; + } + static QCoMatrix intersection( const QCoMatrix& m, const QCoMatrix& n ) + { + QCoMatrix p; + for ( int i = 0; i < 13; i++ ) + p.w[i] = m.w[i] & n.w[i]; + return p; + } +}; + +/* + Returns an integer between 0 (dissimilar) and 15 (very similar) + depending on how similar the string is to \a target. + + This function is efficient, but its results might change in future + versions of Qt as the algorithm evolves. + + \code + QString s( "color" ); + a = similarity( s, "color" ); // a == 15 + a = similarity( s, "colour" ); // a == 8 + a = similarity( s, "flavor" ); // a == 4 + a = similarity( s, "dahlia" ); // a == 0 + \endcode +*/ +static int similarity( const QString& s1, const QString& s2 ) +{ + QCoMatrix m1( s1 ); + QCoMatrix m2( s2 ); + return ( 15 * (QCoMatrix::intersection(m1, m2).worth() + 1) ) / + ( QCoMatrix::reunion(m1, m2).worth() + 1 ); +} + +/*! + \class QPluginManager qpluginmanager.h + \reentrant + \brief The QPluginManager class provides basic functions to access a certain kind of functionality in libraries. + \ingroup componentmodel + + \internal + + A common usage of components is to extend the existing functionality in an application using plugins. The application + defines interfaces that abstract a certain group of functionality, and a plugin provides a specialized implementation + of one or more of those interfaces. + + The QPluginManager template has to be instantiated with an interface definition and the IID for this interface. + + \code + QPluginManager<MyPluginInterface> *manager = new QPluginManager<MyPluginInterface>( IID_MyPluginInterface ); + \endcode + + It searches a specified directory for all shared libraries, queries for components that implement the specific interface and + reads information about the features the plugin wants to add to the application. The component can provide the set of features + provided by implementing either the QFeatureListInterface or the QComponentInformationInterface. The strings returned by the implementations + of + + \code + QStringList QFeatureListInterface::featureList() const + \endcode + + or + + \code + QString QComponentInformationInterface::name() const + \endcode + + respectively, can then be used to access the component that provides the requested feature: + + \code + MyPluginInterface *iface; + manager->queryInterface( "feature", &iface ); + if ( iface ) + iface->execute( "feature" ); + \endcode + + The application can use a QPluginManager instance to create parts of the user interface based on the list of features + found in plugins: + + \code + QPluginManager<MyPluginInterface> *manager = new QPluginManager<MyPluginInterface>( IID_ImageFilterInterface ); + manager->addLibraryPath(...); + + QStringList features = manager->featureList(); + for ( QStringList::Iterator it = features.begin(); it != features.end(); ++it ) { + MyPluginInterface *iface; + manager->queryInterface( *it, &iface ); + + // use QAction to provide toolbuttons and menuitems for each feature... + } + \endcode +*/ + +/*! + \fn QPluginManager::QPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ) + + Creates an QPluginManager for interfaces \a id that will load all shared library files in the \a paths + \a suffix. + If \a cs is FALSE the manager will handle feature strings case insensitive. + + \warning + Setting the cs flag to FALSE requires that components also convert to lower case when comparing with passed strings, so this has + to be handled with care and documented very well. + + \sa QApplication::libraryPaths() +*/ + + +/*! + \fn QRESULT QPluginManager::queryInterface(const QString& feature, Type** iface) const + + Sets \a iface to point to the interface providing \a feature. + + \sa featureList(), library() +*/ + + + +#include <qptrlist.h> + +QGPluginManager::QGPluginManager( const QUuid& id, const QStringList& paths, const QString &suffix, bool cs ) + : interfaceId( id ), plugDict( 17, cs ), casesens( cs ), autounload( TRUE ) +{ + // Every QLibrary object is destroyed on destruction of the manager + libDict.setAutoDelete( TRUE ); + for ( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) { + QString path = *it; + addLibraryPath( path + suffix ); + } +} + +QGPluginManager::~QGPluginManager() +{ + if ( !autounload ) { + QDictIterator<QLibrary> it( libDict ); + while ( it.current() ) { + QLibrary *lib = it.current(); + ++it; + lib->setAutoUnload( FALSE ); + } + } +} + +void QGPluginManager::addLibraryPath( const QString& path ) +{ + if ( !enabled() || !QDir( path ).exists( ".", TRUE ) ) + return; + +#if defined(Q_OS_WIN32) + QString filter = "dll"; +#elif defined(Q_OS_MACX) + QString filter = "dylib"; +#elif defined(Q_OS_UNIX) + QString filter = "so"; +#endif + + QStringList plugins = QDir(path).entryList( "*." + filter ); + for ( QStringList::Iterator p = plugins.begin(); p != plugins.end(); ++p ) { + QString lib = QDir::cleanDirPath( path + "/" + *p ); + if ( libList.contains( lib ) ) + continue; + libList.append( lib ); + } +} + +const QLibrary* QGPluginManager::library( const QString& feature ) const +{ + if ( !enabled() || feature.isEmpty() ) + return 0; + + // We already have a QLibrary object for this feature + QLibrary *library = 0; + if ( ( library = plugDict[feature] ) ) + return library; + + // Find the filename that matches the feature request best + QMap<int, QStringList> map; + QStringList::ConstIterator it = libList.begin(); + int best = 0; + int worst = 15; + while ( it != libList.end() ) { + if ( (*it).isEmpty() || libDict[*it] ) { + ++it; + continue; + } + QString basename = QFileInfo(*it).baseName(); + int s = similarity( feature, basename ); + if ( s < worst ) + worst = s; + if ( s > best ) + best = s; + map[s].append( basename + QChar(0xfffd) + *it ); + ++it; + } + + if ( map.isEmpty() ) + return 0; // no libraries to add + + // Start with the best match to get the library object + QGPluginManager *that = (QGPluginManager*)this; + for ( int s = best; s >= worst; --s ) { + QStringList group = map[s]; + group.sort(); // sort according to the base name + QStringList::ConstIterator git = group.begin(); + while ( git != group.end() ) { + QString lib = (*git).mid( (*git).find( QChar(0xfffd) ) + 1 ); + QString basename = (*git).left( (*git).find( QChar(0xfffd) ) ); + ++git; + + QStringList sameBasename; + while( git != group.end() && + basename == (*git).left( (*git).find( QChar(0xfffd) ) ) ) { + sameBasename << (*git).mid( (*git).find( QChar(0xfffd) ) + 1 ); + ++git; + } + + if ( sameBasename.isEmpty() ) { + that->addLibrary( new QComLibrary( lib ) ); + } else { + QPtrList<QComLibrary> same; + same.setAutoDelete( TRUE ); + for ( QStringList::ConstIterator bit = sameBasename.begin(); + bit != sameBasename.end(); ++bit ) + same.append( new QComLibrary( *bit ) ); + QComLibrary* bestMatch = 0; + for ( QComLibrary* candidate = same.first(); candidate; candidate = same.next() ) + if ( candidate->qtVersion() && candidate->qtVersion() <= QT_VERSION + && ( !bestMatch || candidate->qtVersion() > bestMatch->qtVersion() ) ) + bestMatch = candidate; + if ( bestMatch ) { + same.find( bestMatch ); + that->addLibrary( same.take() ); + } + } + + if ( ( library = that->plugDict[feature] ) ) + return library; + } + } + return 0; +} + +QStringList QGPluginManager::featureList() const +{ + QStringList features; + + if ( !enabled() ) + return features; + + QGPluginManager *that = (QGPluginManager*)this; + QStringList theLibs = libList; + QStringList phase2Libs; + QStringList phase2Deny; + + /* In order to get the feature list we need to add all interesting + libraries. If there are libraries with the same base name, we + prioritze the one that fits our Qt version number and ignore the + others */ + QStringList::Iterator it; + for ( it = theLibs.begin(); it != theLibs.end(); ++it ) { + if ( (*it).isEmpty() || libDict[*it] ) + continue; + QComLibrary* library = new QComLibrary( *it ); + if ( library->qtVersion() == QT_VERSION ) { + that->addLibrary( library ); + phase2Deny << QFileInfo( *it ).baseName(); + } else { + delete library; + phase2Libs << *it; + } + } + for ( it = phase2Libs.begin(); it != phase2Libs.end(); ++it ) + if ( !phase2Deny.contains( QFileInfo( *it ).baseName() ) ) + that->addLibrary( new QComLibrary( *it ) ); + + for ( QDictIterator<QLibrary> pit( plugDict ); pit.current(); ++pit ) + features << pit.currentKey(); + + return features; +} + +bool QGPluginManager::addLibrary( QLibrary* lib ) +{ + if ( !enabled() || !lib ) + return FALSE; + + QComLibrary* plugin = (QComLibrary*)lib; + bool useful = FALSE; + + QUnknownInterface* iFace = 0; + plugin->queryInterface( interfaceId, &iFace ); + if ( iFace ) { + QFeatureListInterface *fliFace = 0; + QComponentInformationInterface *cpiFace = 0; + iFace->queryInterface( IID_QFeatureList, (QUnknownInterface**)&fliFace ); + if ( !fliFace ) + plugin->queryInterface( IID_QFeatureList, (QUnknownInterface**)&fliFace ); + if ( !fliFace ) { + iFace->queryInterface( IID_QComponentInformation, (QUnknownInterface**)&cpiFace ); + if ( !cpiFace ) + plugin->queryInterface( IID_QComponentInformation, (QUnknownInterface**)&cpiFace ); + } + QStringList fl; + if ( fliFace ) + // Map all found features to the library + fl = fliFace->featureList(); + else if ( cpiFace ) + fl << cpiFace->name(); + + for ( QStringList::Iterator f = fl.begin(); f != fl.end(); f++ ) { + QLibrary *old = plugDict[*f]; + if ( !old ) { + useful = TRUE; + plugDict.replace( *f, plugin ); + } else { + // we have old *and* plugin, which one to pick? + QComLibrary* first = (QComLibrary*)old; + QComLibrary* second = (QComLibrary*)plugin; + bool takeFirst = TRUE; + if ( first->qtVersion() != QT_VERSION ) { + if ( second->qtVersion() == QT_VERSION ) + takeFirst = FALSE; + else if ( second->qtVersion() < QT_VERSION && + first->qtVersion() > QT_VERSION ) + takeFirst = FALSE; + } + if ( !takeFirst ) { + useful = TRUE; + plugDict.replace( *f, plugin ); + qWarning("%s: Discarding feature %s in %s!", + (const char*) QFile::encodeName( plugin->library()), + (*f).latin1(), + (const char*) QFile::encodeName( old->library() ) ); + } else { + qWarning("%s: Feature %s already defined in %s!", + (const char*) QFile::encodeName( old->library() ), + (*f).latin1(), + (const char*) QFile::encodeName( plugin->library() ) ); + } + } + } + if ( fliFace ) + fliFace->release(); + if ( cpiFace ) + cpiFace->release(); + iFace->release(); + } + + if ( useful ) { + libDict.replace( plugin->library(), plugin ); + if ( !libList.contains( plugin->library() ) ) + libList.append( plugin->library() ); + return TRUE; + } + delete plugin; + return FALSE; +} + + +bool QGPluginManager::enabled() const +{ +#ifdef QT_SHARED + return TRUE; +#else + return FALSE; +#endif +} + +QRESULT QGPluginManager::queryUnknownInterface(const QString& feature, QUnknownInterface** iface) const +{ + QComLibrary* plugin = 0; + plugin = (QComLibrary*)library( feature ); + return plugin ? plugin->queryInterface( interfaceId, (QUnknownInterface**)iface ) : QE_NOINTERFACE; +} + +#endif //QT_NO_COMPONENT diff --git a/qmake/tools/qgvector.cpp b/qmake/tools/qgvector.cpp new file mode 100644 index 0000000..1985f03 --- a/dev/null +++ b/qmake/tools/qgvector.cpp @@ -0,0 +1,584 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QGVector class +** +** Created : 930907 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#define QGVECTOR_CPP +#include "qgvector.h" +#include "qglist.h" +#include "qstring.h" +#include "qdatastream.h" +#include <stdlib.h> + +#ifdef QT_THREAD_SUPPORT +# include <private/qmutexpool_p.h> +#endif // QT_THREAD_SUPPORT + +#define USE_MALLOC // comment to use new/delete + +#undef NEW +#undef DELETE + +#if defined(USE_MALLOC) +#define NEW(type,size) ((type*)malloc(size*sizeof(type))) +#define DELETE(array) (free((char*)array)) +#else +#define NEW(type,size) (new type[size]) +#define DELETE(array) (delete[] array) +#define DONT_USE_REALLOC // comment to use realloc() +#endif + +/*! + \class QGVector + \reentrant + \ingroup collection + + \brief The QGVector class is an internal class for implementing Qt + collection classes. + + \internal + + QGVector is an internal class that acts as a base class for the + QPtrVector collection class. + + QGVector has some virtual functions that may be reimplemented in + subclasses to customize behavior. + + \list + \i compareItems() compares two collection/vector items. + \i read() reads a collection/vector item from a QDataStream. + \i write() writes a collection/vector item to a QDataStream. + \endlist +*/ + +/***************************************************************************** + Default implementation of virtual functions + *****************************************************************************/ + +/*! + This virtual function compares two list items. + + Returns: + <ul> + <li> 0 if \a d1 == \a d2 + <li> non-zero if \a d1 != \a d2 + </ul> + + This function returns \e int rather than \e bool so that + reimplementations can return one of three values and use it to sort + by: + <ul> + <li> 0 if \a d1 == \a d2 + <li> \> 0 (positive integer) if \a d1 \> \a d2 + <li> \< 0 (negative integer) if \a d1 \< \a d2 + </ul> + + The QPtrVector::sort() and QPtrVector::bsearch() functions require that + compareItems() is implemented as described here. + + This function should not modify the vector because some const + functions call compareItems(). +*/ + +int QGVector::compareItems( Item d1, Item d2 ) +{ + return d1 != d2; // compare pointers +} + +#ifndef QT_NO_DATASTREAM +/*! + Reads a collection/vector item from the stream \a s and returns a reference + to the stream. + + The default implementation sets \a d to 0. + + \sa write() +*/ + +QDataStream &QGVector::read( QDataStream &s, Item &d ) +{ // read item from stream + d = 0; + return s; +} + +/*! + Writes a collection/vector item to the stream \a s and returns a reference + to the stream. + + The default implementation does nothing. + + \sa read() +*/ + +QDataStream &QGVector::write( QDataStream &s, Item ) const +{ // write item to stream + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QGVector member functions + *****************************************************************************/ + +QGVector::QGVector() // create empty vector +{ + vec = 0; + len = numItems = 0; +} + +QGVector::QGVector( uint size ) // create vectors with nullptrs +{ + len = size; + numItems = 0; + if ( len == 0 ) { // zero length + vec = 0; + return; + } + vec = NEW(Item,len); + Q_CHECK_PTR( vec ); + memset( (void*)vec, 0, len*sizeof(Item) ); // fill with nulls +} + +QGVector::QGVector( const QGVector &a ) // make copy of other vector + : QPtrCollection( a ) +{ + len = a.len; + numItems = a.numItems; + if ( len == 0 ) { + vec = 0; + return; + } + vec = NEW( Item, len ); + Q_CHECK_PTR( vec ); + for ( uint i = 0; i < len; i++ ) { + if ( a.vec[i] ) { + vec[i] = newItem( a.vec[i] ); + Q_CHECK_PTR( vec[i] ); + } else { + vec[i] = 0; + } + } +} + +QGVector::~QGVector() +{ + clear(); +} + +QGVector& QGVector::operator=( const QGVector &v ) +{ + if ( &v == this ) + return *this; + + clear(); + len = v.len; + numItems = v.numItems; + if ( len == 0 ) { + vec = 0; + return *this; + } + vec = NEW( Item, len ); + Q_CHECK_PTR( vec ); + for ( uint i = 0; i < len; i++ ) { + if ( v.vec[i] ) { + vec[i] = newItem( v.vec[i] ); + Q_CHECK_PTR( vec[i] ); + } else { + vec[i] = 0; + } + } + return *this; +} + + +bool QGVector::insert( uint index, Item d ) // insert item at index +{ +#if defined(QT_CHECK_RANGE) + if ( index >= len ) { // range error + qWarning( "QGVector::insert: Index %d out of range", index ); + return FALSE; + } +#endif + if ( vec[index] ) { // remove old item + deleteItem( vec[index] ); + numItems--; + } + if ( d ) { + vec[index] = newItem( d ); + Q_CHECK_PTR( vec[index] ); + numItems++; + return vec[index] != 0; + } else { + vec[index] = 0; // reset item + } + return TRUE; +} + +bool QGVector::remove( uint index ) // remove item at index +{ +#if defined(QT_CHECK_RANGE) + if ( index >= len ) { // range error + qWarning( "QGVector::remove: Index %d out of range", index ); + return FALSE; + } +#endif + if ( vec[index] ) { // valid item + deleteItem( vec[index] ); // delete it + vec[index] = 0; // reset pointer + numItems--; + } + return TRUE; +} + +QPtrCollection::Item QGVector::take( uint index ) // take out item +{ +#if defined(QT_CHECK_RANGE) + if ( index >= len ) { // range error + qWarning( "QGVector::take: Index %d out of range", index ); + return 0; + } +#endif + Item d = vec[index]; // don't delete item + if ( d ) + numItems--; + vec[index] = 0; + return d; +} + +void QGVector::clear() // clear vector +{ + if ( vec ) { + for ( uint i=0; i<len; i++ ) { // delete each item + if ( vec[i] ) + deleteItem( vec[i] ); + } + DELETE(vec); + vec = 0; + len = numItems = 0; + } +} + +bool QGVector::resize( uint newsize ) // resize array +{ + if ( newsize == len ) // nothing to do + return TRUE; + if ( vec ) { // existing data + if ( newsize < len ) { // shrink vector + uint i = newsize; + while ( i < len ) { // delete lost items + if ( vec[i] ) { + deleteItem( vec[i] ); + numItems--; + } + i++; + } + } + if ( newsize == 0 ) { // vector becomes empty + DELETE(vec); + vec = 0; + len = numItems = 0; + return TRUE; + } +#if defined(DONT_USE_REALLOC) + if ( newsize == 0 ) { + DELETE(vec); + vec = 0; + return FALSE; + } + Item *newvec = NEW(Item,newsize); // manual realloc + memcpy( newvec, vec, (len < newsize ? len : newsize)*sizeof(Item) ); + DELETE(vec); + vec = newvec; +#else + vec = (Item*)realloc( (char *)vec, newsize*sizeof(Item) ); +#endif + } else { // create new vector + vec = NEW(Item,newsize); + len = numItems = 0; + } + Q_CHECK_PTR( vec ); + if ( !vec ) // no memory + return FALSE; + if ( newsize > len ) // init extra space added + memset( (void*)&vec[len], 0, (newsize-len)*sizeof(Item) ); + len = newsize; + return TRUE; +} + + +bool QGVector::fill( Item d, int flen ) // resize and fill vector +{ + if ( flen < 0 ) + flen = len; // default: use vector length + else if ( !resize( flen ) ) + return FALSE; + for ( uint i=0; i<(uint)flen; i++ ) // insert d at every index + insert( i, d ); + return TRUE; +} + + +static QGVector *sort_vec=0; // current sort vector + + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +#ifdef Q_OS_TEMP +static int _cdecl cmp_vec( const void *n1, const void *n2 ) +#else +static int cmp_vec( const void *n1, const void *n2 ) +#endif +{ + return sort_vec->compareItems( *((QPtrCollection::Item*)n1), *((QPtrCollection::Item*)n2) ); +} + +#if defined(Q_C_CALLBACKS) +} +#endif + + +void QGVector::sort() // sort vector +{ + if ( count() == 0 ) // no elements + return; + register Item *start = &vec[0]; + register Item *end = &vec[len-1]; + Item tmp; + for (;;) { // put all zero elements behind + while ( start < end && *start != 0 ) + start++; + while ( end > start && *end == 0 ) + end--; + if ( start < end ) { + tmp = *start; + *start = *end; + *end = tmp; + } else { + break; + } + } + +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &sort_vec ) ); +#endif // QT_THREAD_SUPPORT + + sort_vec = (QGVector*)this; + qsort( vec, count(), sizeof(Item), cmp_vec ); + sort_vec = 0; +} + +int QGVector::bsearch( Item d ) const // binary search; when sorted +{ + if ( !len ) + return -1; + if ( !d ) { +#if defined(QT_CHECK_NULL) + qWarning( "QGVector::bsearch: Cannot search for null object" ); +#endif + return -1; + } + int n1 = 0; + int n2 = len - 1; + int mid = 0; + bool found = FALSE; + while ( n1 <= n2 ) { + int res; + mid = (n1 + n2)/2; + if ( vec[mid] == 0 ) // null item greater + res = -1; + else + res = ((QGVector*)this)->compareItems( d, vec[mid] ); + if ( res < 0 ) + n2 = mid - 1; + else if ( res > 0 ) + n1 = mid + 1; + else { // found it + found = TRUE; + break; + } + } + if ( !found ) + return -1; + // search to first of equal items + while ( (mid - 1 >= 0) && !((QGVector*)this)->compareItems(d, vec[mid-1]) ) + mid--; + return mid; +} + +int QGVector::findRef( Item d, uint index) const // find exact item in vector +{ +#if defined(QT_CHECK_RANGE) + if ( index > len ) { // range error + qWarning( "QGVector::findRef: Index %d out of range", index ); + return -1; + } +#endif + for ( uint i=index; i<len; i++ ) { + if ( vec[i] == d ) + return i; + } + return -1; +} + +int QGVector::find( Item d, uint index ) const // find equal item in vector +{ +#if defined(QT_CHECK_RANGE) + if ( index >= len ) { // range error + qWarning( "QGVector::find: Index %d out of range", index ); + return -1; + } +#endif + for ( uint i=index; i<len; i++ ) { + if ( vec[i] == 0 && d == 0 ) // found null item + return i; + if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) + return i; + } + return -1; +} + +uint QGVector::containsRef( Item d ) const // get number of exact matches +{ + uint count = 0; + for ( uint i=0; i<len; i++ ) { + if ( vec[i] == d ) + count++; + } + return count; +} + +uint QGVector::contains( Item d ) const // get number of equal matches +{ + uint count = 0; + for ( uint i=0; i<len; i++ ) { + if ( vec[i] == 0 && d == 0 ) // count null items + count++; + if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) + count++; + } + return count; +} + +bool QGVector::insertExpand( uint index, Item d )// insert and grow if necessary +{ + if ( index >= len ) { + if ( !resize( index+1 ) ) // no memory + return FALSE; + } + insert( index, d ); + return TRUE; +} + +void QGVector::toList( QGList *list ) const // store items in list +{ + list->clear(); + for ( uint i=0; i<len; i++ ) { + if ( vec[i] ) + list->append( vec[i] ); + } +} + + +void QGVector::warningIndexRange( uint i ) +{ +#if defined(QT_CHECK_RANGE) + qWarning( "QGVector::operator[]: Index %d out of range", i ); +#else + Q_UNUSED( i ) +#endif +} + + +/***************************************************************************** + QGVector stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +QDataStream &operator>>( QDataStream &s, QGVector &vec ) +{ // read vector + return vec.read( s ); +} + +QDataStream &operator<<( QDataStream &s, const QGVector &vec ) +{ // write vector + return vec.write( s ); +} + +QDataStream &QGVector::read( QDataStream &s ) // read vector from stream +{ + uint num; + s >> num; // read number of items + clear(); // clear vector + resize( num ); + for (uint i=0; i<num; i++) { // read all items + Item d; + read( s, d ); + Q_CHECK_PTR( d ); + if ( !d ) // no memory + break; + vec[i] = d; + } + return s; +} + +QDataStream &QGVector::write( QDataStream &s ) const +{ // write vector to stream + uint num = count(); + s << num; // number of items to write + num = size(); + for (uint i=0; i<num; i++) { // write non-null items + if ( vec[i] ) + write( s, vec[i] ); + } + return s; +} + +/* Returns whether v equals this vector or not */ + +bool QGVector::operator==( const QGVector &v ) const +{ + if ( size() != v.size() ) + return FALSE; + if ( count() != v.count() ) + return FALSE; + for ( int i = 0; i < (int)size(); ++i ) { + if ( ( (QGVector*)this )->compareItems( at( i ), v.at( i ) ) != 0 ) + return FALSE; + } + return TRUE; +} + +#endif // QT_NO_DATASTREAM diff --git a/qmake/tools/qiodevice.cpp b/qmake/tools/qiodevice.cpp new file mode 100644 index 0000000..93969e4 --- a/dev/null +++ b/qmake/tools/qiodevice.cpp @@ -0,0 +1,755 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QIODevice class +** +** Created : 940913 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qiodevice.h" + +/*! + \class QIODevice qiodevice.h + \reentrant + + \brief The QIODevice class is the base class of I/O devices. + + \ingroup io + + An I/O device represents a medium that one can read bytes from + and/or write bytes to. The QIODevice class is the abstract + superclass of all such devices; classes such as QFile, QBuffer and + QSocket inherit QIODevice and implement virtual functions such as + write() appropriately. + + Although applications sometimes use QIODevice directly, it is + usually better to use QTextStream and QDataStream, which provide + stream operations on any QIODevice subclass. QTextStream provides + text-oriented stream functionality (for human-readable ASCII + files, for example), whereas QDataStream deals with binary data in + a totally platform-independent manner. + + The public member functions in QIODevice roughly fall into two + groups: the action functions and the state access functions. The + most important action functions are: + + \list + + \i open() opens a device for reading and/or writing, depending on + the mode argument. + + \i close() closes the device and tidies up (e.g. flushes buffered + data) + + \i readBlock() reads a block of data from the device. + + \i writeBlock() writes a block of data to the device. + + \i readLine() reads a line (of text, usually) from the device. + + \i flush() ensures that all buffered data are written to the real device. + + \endlist + + There are also some other, less used, action functions: + + \list + + \i getch() reads a single character. + + \i ungetch() forgets the last call to getch(), if possible. + + \i putch() writes a single character. + + \i size() returns the size of the device, if there is one. + + \i at() returns the current read/write pointer's position, if there + is one for this device, or it moves the pointer if given an offset. + + \i atEnd() indicates whether there is more to read, if this is + meaningful for this device. + + \i reset() moves the read/write pointer to the start of the + device, if that is possible for this device. + + \endlist + + The state access are all "get" functions. The QIODevice subclass + calls setState() to update the state, and simple access functions + tell the user of the device what the device's state is. Here are + the settings, and their associated access functions: + + \list + + \i Access type. Some devices are direct access (it is possible + to read/write anywhere), whereas others are sequential. QIODevice + provides the access functions (isDirectAccess(), + isSequentialAccess(), and isCombinedAccess()) to tell users what a + given I/O device supports. + + \i Buffering. Some devices are accessed in raw mode, whereas + others are buffered. Buffering usually provides greater + efficiency, particularly for small read/write operations. + isBuffered() tells the user whether a given device is buffered. + (This can often be set by the application in the call to open().) + + \i Synchronicity. Synchronous devices work immediately (for + example, files). When you read from a file, the file delivers its + data straight away. Other kinds of device, such as a socket + connected to a HTTP server, may not deliver the data until seconds + after you ask to read it. isSynchronous() and isAsynchronous() + tell the user how this device operates. + + \i CR/LF translation. For simplicity, applications often like to + see just a single CR/LF style, and QIODevice subclasses can + provide this. isTranslated() returns TRUE if this object + translates CR/LF to just LF. (This can often be set by the + application in the call to open().) + + \i Permissions. Some files cannot be written. For example, + isReadable(), isWritable() and isReadWrite() tell the application + whether it can read from and write to a given device. (This can + often be set by the application in the call to open().) + + \i Finally, isOpen() returns TRUE if the device is open, i.e. + after an open() call. + + \endlist + + QIODevice provides numerous pure virtual functions that you need + to implement when subclassing it. Here is a skeleton subclass with + all the members you are sure to need and some that you will + probably need: + + \code + class MyDevice : public QIODevice + { + public: + MyDevice(); + ~MyDevice(); + + bool open( int mode ); + void close(); + void flush(); + + uint size() const; + int at() const; // non-pure virtual + bool at( int ); // non-pure virtual + bool atEnd() const; // non-pure virtual + + int readBlock( char *data, uint maxlen ); + int writeBlock( const char *data, uint len ); + int readLine( char *data, uint maxlen ); + + int getch(); + int putch( int ); + int ungetch( int ); + }; + \endcode + + The three non-pure virtual functions need not be reimplemented for + sequential devices. + + \sa QDataStream, QTextStream +*/ + +/*! + \enum QIODevice::Offset + + The offset within the device. +*/ + + +/*! + Constructs an I/O device. +*/ + +QIODevice::QIODevice() +{ + ioMode = 0; // initial mode + ioSt = IO_Ok; + ioIndex = 0; +} + +/*! + Destroys the I/O device. +*/ + +QIODevice::~QIODevice() +{ +} + + +/*! + \fn int QIODevice::flags() const + + Returns the current I/O device flags setting. + + Flags consists of mode flags and state flags. + + \sa mode(), state() +*/ + +/*! + \fn int QIODevice::mode() const + + Returns bits OR'ed together that specify the current operation + mode. + + These are the flags that were given to the open() function. + + The flags are \c IO_ReadOnly, \c IO_WriteOnly, \c IO_ReadWrite, + \c IO_Append, \c IO_Truncate and \c IO_Translate. +*/ + +/*! + \fn int QIODevice::state() const + + Returns bits OR'ed together that specify the current state. + + The flags are: \c IO_Open. + + Subclasses may define additional flags. +*/ + +/*! + \fn bool QIODevice::isDirectAccess() const + + Returns TRUE if the I/O device is a direct access device; + otherwise returns FALSE, i.e. if the device is a sequential access + device. + + \sa isSequentialAccess() +*/ + +/*! + \fn bool QIODevice::isSequentialAccess() const + + Returns TRUE if the device is a sequential access device; + otherwise returns FALSE, i.e. if the device is a direct access + device. + + Operations involving size() and at(int) are not valid on + sequential devices. + + \sa isDirectAccess() +*/ + +/*! + \fn bool QIODevice::isCombinedAccess() const + + Returns TRUE if the I/O device is a combined access (both direct + and sequential) device; otherwise returns FALSE. + + This access method is currently not in use. +*/ + +/*! + \fn bool QIODevice::isBuffered() const + + Returns TRUE if the I/O device is a buffered device; otherwise + returns FALSE, i.e. the device is a raw device. + + \sa isRaw() +*/ + +/*! + \fn bool QIODevice::isRaw() const + + Returns TRUE if the device is a raw device; otherwise returns + FALSE, i.e. if the device is a buffered device. + + \sa isBuffered() +*/ + +/*! + \fn bool QIODevice::isSynchronous() const + + Returns TRUE if the I/O device is a synchronous device; otherwise + returns FALSE, i.e. the device is an asynchronous device. + + \sa isAsynchronous() +*/ + +/*! + \fn bool QIODevice::isAsynchronous() const + + Returns TRUE if the device is an asynchronous device; otherwise + returns FALSE, i.e. if the device is a synchronous device. + + This mode is currently not in use. + + \sa isSynchronous() +*/ + +/*! + \fn bool QIODevice::isTranslated() const + + Returns TRUE if the I/O device translates carriage-return and + linefeed characters; otherwise returns FALSE. + + A QFile is translated if it is opened with the \c IO_Translate + mode flag. +*/ + +/*! + \fn bool QIODevice::isReadable() const + + Returns TRUE if the I/O device was opened using \c IO_ReadOnly or + \c IO_ReadWrite mode; otherwise returns FALSE. + + \sa isWritable(), isReadWrite() +*/ + +/*! + \fn bool QIODevice::isWritable() const + + Returns TRUE if the I/O device was opened using \c IO_WriteOnly or + \c IO_ReadWrite mode; otherwise returns FALSE. + + \sa isReadable(), isReadWrite() +*/ + +/*! + \fn bool QIODevice::isReadWrite() const + + Returns TRUE if the I/O device was opened using \c IO_ReadWrite + mode; otherwise returns FALSE. + + \sa isReadable(), isWritable() +*/ + +/*! + \fn bool QIODevice::isInactive() const + + Returns TRUE if the I/O device state is 0, i.e. the device is not + open; otherwise returns FALSE. + + \sa isOpen() +*/ + +/*! + \fn bool QIODevice::isOpen() const + + Returns TRUE if the I/O device has been opened; otherwise returns + FALSE. + + \sa isInactive() +*/ + + +/*! + \fn int QIODevice::status() const + + Returns the I/O device status. + + The I/O device status returns an error code. If open() returns + FALSE or readBlock() or writeBlock() return -1, this function can + be called to find out the reason why the operation failed. + + \keyword IO_Ok + \keyword IO_ReadError + \keyword IO_WriteError + \keyword IO_FatalError + \keyword IO_OpenError + \keyword IO_ConnectError + \keyword IO_AbortError + \keyword IO_TimeOutError + \keyword IO_UnspecifiedError + + The status codes are: + \table + \header \i Status code \i Meaning + \row \i \c IO_Ok \i The operation was successful. + \row \i \c IO_ReadError \i Could not read from the device. + \row \i \c IO_WriteError \i Could not write to the device. + \row \i \c IO_FatalError \i A fatal unrecoverable error occurred. + \row \i \c IO_OpenError \i Could not open the device. + \row \i \c IO_ConnectError \i Could not connect to the device. + \row \i \c IO_AbortError \i The operation was unexpectedly aborted. + \row \i \c IO_TimeOutError \i The operation timed out. + \row \i \c IO_UnspecifiedError \i An unspecified error happened on close. + \endtable + + \sa resetStatus() +*/ + +/*! + \fn void QIODevice::resetStatus() + + Sets the I/O device status to \c IO_Ok. + + \sa status() +*/ + + +/*! + \fn void QIODevice::setFlags( int f ) + \internal + Used by subclasses to set the device flags. +*/ + +/*! + \internal + Used by subclasses to set the device type. +*/ + +void QIODevice::setType( int t ) +{ +#if defined(QT_CHECK_RANGE) + if ( (t & IO_TypeMask) != t ) + qWarning( "QIODevice::setType: Specified type out of range" ); +#endif + ioMode &= ~IO_TypeMask; // reset type bits + ioMode |= t; +} + +/*! + \internal + Used by subclasses to set the device mode. +*/ + +void QIODevice::setMode( int m ) +{ +#if defined(QT_CHECK_RANGE) + if ( (m & IO_ModeMask) != m ) + qWarning( "QIODevice::setMode: Specified mode out of range" ); +#endif + ioMode &= ~IO_ModeMask; // reset mode bits + ioMode |= m; +} + +/*! + \internal + Used by subclasses to set the device state. +*/ + +void QIODevice::setState( int s ) +{ +#if defined(QT_CHECK_RANGE) + if ( ((uint)s & IO_StateMask) != (uint)s ) + qWarning( "QIODevice::setState: Specified state out of range" ); +#endif + ioMode &= ~IO_StateMask; // reset state bits + ioMode |= (uint)s; +} + +/*! + \internal + Used by subclasses to set the device status (not state) to \a s. +*/ + +void QIODevice::setStatus( int s ) +{ + ioSt = s; +} + + +/*! + \fn bool QIODevice::open( int mode ) + + Opens the I/O device using the specified \a mode. Returns TRUE if + the device was successfully opened; otherwise returns FALSE. + + The mode parameter \a mode must be an OR'ed combination of the + following flags. + \table + \header \i Mode flags \i Meaning + \row \i \c IO_Raw \i specifies raw (unbuffered) file access. + \row \i \c IO_ReadOnly \i opens a file in read-only mode. + \row \i \c IO_WriteOnly \i opens a file in write-only mode. + \row \i \c IO_ReadWrite \i opens a file in read/write mode. + \row \i \c IO_Append \i sets the file index to the end of the file. + \row \i \c IO_Truncate \i truncates the file. + \row \i \c IO_Translate \i enables carriage returns and linefeed + translation for text files under MS-DOS, Windows and Macintosh. On + Unix systems this flag has no effect. Use with caution as it will + also transform every linefeed written to the file into a CRLF + pair. This is likely to corrupt your file if you write write + binary data. Cannot be combined with \c IO_Raw. + \endtable + + This virtual function must be reimplemented by all subclasses. + + \sa close() +*/ + +/*! + \fn void QIODevice::close() + + Closes the I/O device. + + This virtual function must be reimplemented by all subclasses. + + \sa open() +*/ + +/*! + \fn void QIODevice::flush() + + Flushes an open I/O device. + + This virtual function must be reimplemented by all subclasses. +*/ + + +/*! + \fn QIODevice::Offset QIODevice::size() const + + Virtual function that returns the size of the I/O device. + + \sa at() +*/ + +/*! + Virtual function that returns the current I/O device position. + + This is the position of the data read/write head of the I/O + device. + + \sa size() +*/ + +QIODevice::Offset QIODevice::at() const +{ + return ioIndex; +} + + +/* + The following is a "bad" overload, since it does "not behave essentially + the same" like the above. So don't use \overload in the documentation of + this function and we have to live with the qdoc warning which is generated + for this. +*/ +/*! + Virtual function that sets the I/O device position to \a pos. + Returns TRUE if the position was successfully set, i.e. \a pos is + within range; otherwise returns FALSE. + + \sa size() +*/ + +bool QIODevice::at( Offset pos ) +{ +#if defined(QT_CHECK_RANGE) + if ( pos > size() ) { +#if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) + qWarning( "QIODevice::at: Index %llu out of range", pos ); +#else + qWarning( "QIODevice::at: Index %lu out of range", pos ); +#endif + return FALSE; + } +#endif + ioIndex = pos; + return TRUE; +} + +/*! + Virtual function that returns TRUE if the I/O device position is + at the end of the input; otherwise returns FALSE. +*/ + +bool QIODevice::atEnd() const +{ + if ( isSequentialAccess() || isTranslated() ) { + QIODevice* that = (QIODevice*)this; + int c = that->getch(); + bool result = c < 0; + that->ungetch(c); + return result; + } else { + return at() == size(); + } +} + +/*! + \fn bool QIODevice::reset() + + Sets the device index position to 0. + + \sa at() +*/ + + +/*! + \fn int QIODevice::readBlock( char *data, Q_ULONG maxlen ) + + Reads at most \a maxlen bytes from the I/O device into \a data and + returns the number of bytes actually read. + + This function should return -1 if a fatal error occurs and should + return 0 if there are no bytes to read. + + The device must be opened for reading, and \a data must not be 0. + + This virtual function must be reimplemented by all subclasses. + + \sa writeBlock() isOpen() isReadable() +*/ + +/*! + This convenience function returns all of the remaining data in the + device. +*/ +QByteArray QIODevice::readAll() +{ + if ( isDirectAccess() ) { + // we know the size + int n = size()-at(); // ### fix for 64-bit or large files? + int totalRead = 0; + QByteArray ba( n ); + char* c = ba.data(); + while ( n ) { + int r = readBlock( c, n ); + if ( r < 0 ) + return QByteArray(); + n -= r; + c += r; + totalRead += r; + // If we have a translated file, then it is possible that + // we read less bytes than size() reports + if ( atEnd() ) { + ba.resize( totalRead ); + break; + } + } + return ba; + } else { + // read until we reach the end + const int blocksize = 512; + int nread = 0; + QByteArray ba; + while ( !atEnd() ) { + ba.resize( nread + blocksize ); + int r = readBlock( ba.data()+nread, blocksize ); + if ( r < 0 ) + return QByteArray(); + nread += r; + } + ba.resize( nread ); + return ba; + } +} + +/*! + \fn int QIODevice::writeBlock( const char *data, Q_ULONG len ) + + Writes \a len bytes from \a data to the I/O device and returns the + number of bytes actually written. + + This function should return -1 if a fatal error occurs. + + This virtual function must be reimplemented by all subclasses. + + \sa readBlock() +*/ + +/*! + \overload + + This convenience function is the same as calling writeBlock( + data.data(), data.size() ). +*/ +Q_LONG QIODevice::writeBlock( const QByteArray& data ) +{ + return writeBlock( data.data(), data.size() ); +} + +/*! + Reads a line of text, (or up to \a maxlen bytes if a newline isn't + encountered) plus a terminating '\0' into \a data. If there is a + newline at the end if the line, it is not stripped. + + Returns the number of bytes read including the terminating '\0', + or -1 if an error occurred. + + This virtual function can be reimplemented much more efficiently + by the most subclasses. + + \sa readBlock(), QTextStream::readLine() +*/ + +Q_LONG QIODevice::readLine( char *data, Q_ULONG maxlen ) +{ + if ( maxlen == 0 ) // application bug? + return 0; + char *p = data; + while ( --maxlen && (readBlock(p,1)>0) ) { // read one byte at a time + if ( *p++ == '\n' ) // end of line + break; + } + *p++ = '\0'; + return p - data; +} + + +/*! + \fn int QIODevice::getch() + + Reads a single byte/character from the I/O device. + + Returns the byte/character read, or -1 if the end of the I/O + device has been reached. + + This virtual function must be reimplemented by all subclasses. + + \sa putch(), ungetch() +*/ + +/*! + \fn int QIODevice::putch( int ch ) + + Writes the character \a ch to the I/O device. + + Returns \a ch, or -1 if an error occurred. + + This virtual function must be reimplemented by all subclasses. + + \sa getch(), ungetch() +*/ + +/*! + \fn int QIODevice::ungetch( int ch ) + + Puts the character \a ch back into the I/O device and decrements + the index position if it is not zero. + + This function is normally called to "undo" a getch() operation. + + Returns \a ch, or -1 if an error occurred. + + This virtual function must be reimplemented by all subclasses. + + \sa getch(), putch() +*/ diff --git a/qmake/tools/qlibrary.cpp b/qmake/tools/qlibrary.cpp new file mode 100644 index 0000000..564db30 --- a/dev/null +++ b/qmake/tools/qlibrary.cpp @@ -0,0 +1,343 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QLibrary class +** +** Created : 2000-01-01 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" +#include <private/qlibrary_p.h> + +#ifndef QT_NO_LIBRARY + +// uncomment this to get error messages +//#define QT_DEBUG_COMPONENT 1 +// uncomment this to get error and success messages +//#define QT_DEBUG_COMPONENT 2 + +#ifndef QT_DEBUG_COMPONENT +# if defined(QT_DEBUG) +# define QT_DEBUG_COMPONENT 1 +# endif +#endif + +#if defined(QT_DEBUG_COMPONENT) +#include <qfile.h> +#endif + +#if defined(Q_WS_WIN) && !defined(QT_MAKEDLL) +#define QT_NO_LIBRARY_UNLOAD +#endif + +QLibraryPrivate::QLibraryPrivate( QLibrary *lib ) + : pHnd( 0 ), library( lib ) +{ +} + + +/*! + \class QLibrary qlibrary.h + \reentrant + \brief The QLibrary class provides a wrapper for handling shared libraries. + + \mainclass + \group plugins + + An instance of a QLibrary object can handle a single shared + library and provide access to the functionality in the library in + a platform independent way. If the library is a component server, + QLibrary provides access to the exported component and can + directly query this component for interfaces. + + QLibrary ensures that the shared library is loaded and stays in + memory whilst it is in use. QLibrary can also unload the library + on destruction and release unused resources. + + A typical use of QLibrary is to resolve an exported symbol in a + shared object, and to call the function that this symbol + represents. This is called "explicit linking" in contrast to + "implicit linking", which is done by the link step in the build + process when linking an executable against a library. + + The following code snippet loads a library, resolves the symbol + "mysymbol", and calls the function if everything succeeded. If + something went wrong, e.g. the library file does not exist or the + symbol is not defined, the function pointer will be 0 and won't be + called. When the QLibrary object is destroyed the library will be + unloaded, making all references to memory allocated in the library + invalid. + + \code + typedef void (*MyPrototype)(); + MyPrototype myFunction; + + QLibrary myLib( "mylib" ); + myFunction = (MyProtoype) myLib.resolve( "mysymbol" ); + if ( myFunction ) { + myFunction(); + } + \endcode +*/ + +/*! + Creates a QLibrary object for the shared library \a filename. The + library will be unloaded in the destructor. + + Note that \a filename does not need to include the (platform specific) + file extension, so calling + \code + QLibrary lib( "mylib" ); + \endcode + is equivalent to calling + \code + QLibrary lib( "mylib.dll" ); + \endcode + on Windows, and + \code + QLibrary lib( "libmylib.so" ); + \endcode + on Unix. Specifying the extension is not recommended, since + doing so introduces a platform dependency. + + If \a filename does not include a path, the library loader will + look for the file in the platform specific search paths. + + \sa load() unload(), setAutoUnload() +*/ +QLibrary::QLibrary( const QString& filename ) + : libfile( filename ), aunload( TRUE ) +{ + libfile.replace( '\\', '/' ); + d = new QLibraryPrivate( this ); +} + +/*! + Deletes the QLibrary object. + + The library will be unloaded if autoUnload() is TRUE (the + default), otherwise it stays in memory until the application + exits. + + \sa unload(), setAutoUnload() +*/ +QLibrary::~QLibrary() +{ + if ( autoUnload() ) + unload(); + + delete d; +} + +/*! + Returns the address of the exported symbol \a symb. The library is + loaded if necessary. The function returns 0 if the symbol could + not be resolved or the library could not be loaded. + + \code + typedef int (*avgProc)( int, int ); + + avgProc avg = (avgProc) library->resolve( "avg" ); + if ( avg ) + return avg( 5, 8 ); + else + return -1; + \endcode + +*/ +void *QLibrary::resolve( const char* symb ) +{ + if ( !d->pHnd ) + load(); + if ( !d->pHnd ) + return 0; + + void *address = d->resolveSymbol( symb ); + + return address; +} + +/*! + \overload + + Loads the library \a filename and returns the address of the + exported symbol \a symb. Note that like the constructor, \a + filename does not need to include the (platform specific) file + extension. The library remains loaded until the process exits. + + The function returns 0 if the symbol could not be resolved or the + library could not be loaded. + + This function is useful only if you want to resolve a single + symbol, e.g. a function pointer from a specific library once: + + \code + typedef void (*FunctionType)(); + static FunctionType *ptrFunction = 0; + static bool triedResolve = FALSE; + if ( !ptrFunction && !triedResolve ) + ptrFunction = QLibrary::resolve( "mylib", "mysymb" ); + + if ( ptrFunction ) + ptrFunction(); + else + ... + \endcode + + If you want to resolve multiple symbols, use a QLibrary object and + call the non-static version of resolve(). + + \sa resolve() +*/ +void *QLibrary::resolve( const QString &filename, const char *symb ) +{ + QLibrary lib( filename ); + lib.setAutoUnload( FALSE ); + return lib.resolve( symb ); +} + +/*! + Returns TRUE if the library is loaded; otherwise returns FALSE. + + \sa unload() +*/ +bool QLibrary::isLoaded() const +{ + return d->pHnd != 0; +} + +/*! + Loads the library. Since resolve() always calls this function + before resolving any symbols it is not necessary to call it + explicitly. In some situations you might want the library loaded + in advance, in which case you would use this function. +*/ +bool QLibrary::load() +{ + return d->loadLibrary(); +} + +/*! + Unloads the library and returns TRUE if the library could be + unloaded; otherwise returns FALSE. + + This function is called by the destructor if autoUnload() is + enabled. + + \sa resolve() +*/ +bool QLibrary::unload() +{ + if ( !d->pHnd ) + return TRUE; + +#if !defined(QT_NO_LIBRARY_UNLOAD) + if ( !d->freeLibrary() ) { +# if defined(QT_DEBUG_COMPONENT) + qWarning( "%s could not be unloaded", (const char*) QFile::encodeName(library()) ); +# endif + return FALSE; + } + +# if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2 + qWarning( "%s has been unloaded", (const char*) QFile::encodeName(library()) ); +# endif + d->pHnd = 0; +#endif + return TRUE; +} + +/*! + Returns TRUE if the library will be automatically unloaded when + this wrapper object is destructed; otherwise returns FALSE. The + default is TRUE. + + \sa setAutoUnload() +*/ +bool QLibrary::autoUnload() const +{ + return (bool)aunload; +} + +/*! + If \a enabled is TRUE (the default), the wrapper object is set to + automatically unload the library upon destruction. If \a enabled + is FALSE, the wrapper object is not unloaded unless you explicitly + call unload(). + + \sa autoUnload() +*/ +void QLibrary::setAutoUnload( bool enabled ) +{ + aunload = enabled; +} + +/*! + Returns the filename of the shared library this QLibrary object + handles, including the platform specific file extension. + + For example: + \code + QLibrary lib( "mylib" ); + QString str = lib.library(); + \endcode + will set \e str to "mylib.dll" on Windows, and "libmylib.so" on Linux. +*/ +QString QLibrary::library() const +{ + if ( libfile.isEmpty() ) + return libfile; + + QString filename = libfile; + +#if defined(Q_WS_WIN) + if ( filename.findRev( '.' ) <= filename.findRev( '/' ) ) + filename += ".dll"; +#elif defined(Q_OS_MACX) + if ( filename.find( ".dylib" ) == -1 ) + filename += ".dylib"; +#else + if ( filename.find( ".so" ) == -1 ) { + const int x = filename.findRev( "/" ); + if ( x != -1 ) { + QString path = filename.left( x + 1 ); + QString file = filename.right( filename.length() - x - 1 ); + filename = QString( "%1lib%2.so" ).arg( path ).arg( file ); + } else { + filename = QString( "lib%1.so" ).arg( filename ); + } + } +#endif + + return filename; +} +#endif //QT_NO_LIBRARY diff --git a/qmake/tools/qlibrary_unix.cpp b/qmake/tools/qlibrary_unix.cpp new file mode 100644 index 0000000..f0fbdf6 --- a/dev/null +++ b/qmake/tools/qlibrary_unix.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QLibraryPrivate class +** +** Created : 2000-01-01 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" +#include "private/qlibrary_p.h" + +#ifndef QT_NO_LIBRARY + +#if defined(QT_AOUT_UNDERSCORE) +#include <string.h> +#endif + +/* + The platform dependent implementations of + - loadLibrary + - freeLibrary + - resolveSymbol + + It's not too hard to guess what the functions do. +*/ + +#if defined(QT_HPUX_LD) // for HP-UX < 11.x and 32 bit + +bool QLibraryPrivate::loadLibrary() +{ + if ( pHnd ) + return TRUE; + + QString filename = library->library(); + + pHnd = (void*)shl_load( filename.latin1(), BIND_DEFERRED | BIND_NONFATAL | DYNAMIC_PATH, 0 ); +#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) + if ( !pHnd ) + qWarning( "%s: failed to load library!", filename.latin1() ); +#endif + return pHnd != 0; +} + +bool QLibraryPrivate::freeLibrary() +{ + if ( !pHnd ) + return TRUE; + + if ( shl_unload( (shl_t)pHnd ) ) { +#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) + QString filename = library->library(); + qWarning( "%s: Failed to unload library!", filename.latin1() ); +#endif + return FALSE; + } + pHnd = 0; + return TRUE; +} + +void* QLibraryPrivate::resolveSymbol( const char* symbol ) +{ + if ( !pHnd ) + return 0; + + void* address = 0; + if ( shl_findsym( (shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address ) < 0 ) { +#if defined(QT_DEBUG_COMPONENT) + QString filename = library->library(); + qWarning( "%s: couldn't resolve symbol \"%s\"", filename.latin1(), symbol ); +#endif + } + return address; +} + +#else // POSIX +#include <dlfcn.h> + +bool QLibraryPrivate::loadLibrary() +{ + if ( pHnd ) + return TRUE; + + QString filename = library->library(); + + pHnd = dlopen( filename.latin1(), RTLD_LAZY ); +#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) + if ( !pHnd ) + qWarning( "%s", dlerror() ); +#endif + return pHnd != 0; +} + +bool QLibraryPrivate::freeLibrary() +{ + if ( !pHnd ) + return TRUE; + + if ( dlclose( pHnd ) ) { +#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) + qWarning( "%s", dlerror() ); +#endif + return FALSE; + } + + pHnd = 0; + return TRUE; +} + +void* QLibraryPrivate::resolveSymbol( const char* symbol ) +{ + if ( !pHnd ) + return 0; + +#if defined(QT_AOUT_UNDERSCORE) + // older a.out systems add an underscore in front of symbols + char* undrscr_symbol = new char[strlen(symbol)+2]; + undrscr_symbol[0] = '_'; + strcpy(undrscr_symbol+1, symbol); + void* address = dlsym( pHnd, undrscr_symbol ); + delete [] undrscr_symbol; +#else + void* address = dlsym( pHnd, symbol ); +#endif +#if defined(QT_DEBUG_COMPONENT) + const char* error = dlerror(); + if ( error ) + qWarning( "%s", error ); +#endif + return address; +} + +#endif // POSIX + +#endif diff --git a/qmake/tools/qmap.cpp b/qmake/tools/qmap.cpp new file mode 100644 index 0000000..3f73f81 --- a/dev/null +++ b/qmake/tools/qmap.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QMap +** +** Created : 990406 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qmap.h" + +typedef QMapNodeBase* NodePtr; +typedef QMapNodeBase Node; + + +void QMapPrivateBase::rotateLeft( NodePtr x, NodePtr& root) +{ + NodePtr y = x->right; + x->right = y->left; + if (y->left !=0) + y->left->parent = x; + y->parent = x->parent; + if (x == root) + root = y; + else if (x == x->parent->left) + x->parent->left = y; + else + x->parent->right = y; + y->left = x; + x->parent = y; +} + + +void QMapPrivateBase::rotateRight( NodePtr x, NodePtr& root ) +{ + NodePtr y = x->left; + x->left = y->right; + if (y->right != 0) + y->right->parent = x; + y->parent = x->parent; + if (x == root) + root = y; + else if (x == x->parent->right) + x->parent->right = y; + else + x->parent->left = y; + y->right = x; + x->parent = y; +} + + +void QMapPrivateBase::rebalance( NodePtr x, NodePtr& root) +{ + x->color = Node::Red; + while ( x != root && x->parent->color == Node::Red ) { + if ( x->parent == x->parent->parent->left ) { + NodePtr y = x->parent->parent->right; + if (y && y->color == Node::Red) { + x->parent->color = Node::Black; + y->color = Node::Black; + x->parent->parent->color = Node::Red; + x = x->parent->parent; + } else { + if (x == x->parent->right) { + x = x->parent; + rotateLeft( x, root ); + } + x->parent->color = Node::Black; + x->parent->parent->color = Node::Red; + rotateRight (x->parent->parent, root ); + } + } else { + NodePtr y = x->parent->parent->left; + if ( y && y->color == Node::Red ) { + x->parent->color = Node::Black; + y->color = Node::Black; + x->parent->parent->color = Node::Red; + x = x->parent->parent; + } else { + if (x == x->parent->left) { + x = x->parent; + rotateRight( x, root ); + } + x->parent->color = Node::Black; + x->parent->parent->color = Node::Red; + rotateLeft( x->parent->parent, root ); + } + } + } + root->color = Node::Black; +} + + +NodePtr QMapPrivateBase::removeAndRebalance( NodePtr z, NodePtr& root, + NodePtr& leftmost, + NodePtr& rightmost ) +{ + NodePtr y = z; + NodePtr x; + NodePtr x_parent; + if (y->left == 0) { + x = y->right; + } else { + if (y->right == 0) + x = y->left; + else + { + y = y->right; + while (y->left != 0) + y = y->left; + x = y->right; + } + } + if (y != z) { + z->left->parent = y; + y->left = z->left; + if (y != z->right) { + x_parent = y->parent; + if (x) + x->parent = y->parent; + y->parent->left = x; + y->right = z->right; + z->right->parent = y; + } else { + x_parent = y; + } + if (root == z) + root = y; + else if (z->parent->left == z) + z->parent->left = y; + else + z->parent->right = y; + y->parent = z->parent; + // Swap the colors + Node::Color c = y->color; + y->color = z->color; + z->color = c; + y = z; + } else { + x_parent = y->parent; + if (x) + x->parent = y->parent; + if (root == z) + root = x; + else if (z->parent->left == z) + z->parent->left = x; + else + z->parent->right = x; + if ( leftmost == z ) { + if (z->right == 0) + leftmost = z->parent; + else + leftmost = x->minimum(); + } + if (rightmost == z) { + if (z->left == 0) + rightmost = z->parent; + else + rightmost = x->maximum(); + } + } + if (y->color != Node::Red) { + while (x != root && (x == 0 || x->color == Node::Black)) { + if (x == x_parent->left) { + NodePtr w = x_parent->right; + if (w->color == Node::Red) { + w->color = Node::Black; + x_parent->color = Node::Red; + rotateLeft(x_parent, root); + w = x_parent->right; + } + if ((w->left == 0 || w->left->color == Node::Black) && + (w->right == 0 || w->right->color == Node::Black)) { + w->color = Node::Red; + x = x_parent; + x_parent = x_parent->parent; + } else { + if (w->right == 0 || w->right->color == Node::Black) { + if (w->left) + w->left->color = Node::Black; + w->color = Node::Red; + rotateRight(w, root); + w = x_parent->right; + } + w->color = x_parent->color; + x_parent->color = Node::Black; + if (w->right) + w->right->color = Node::Black; + rotateLeft(x_parent, root); + break; + } + } else { + NodePtr w = x_parent->left; + if (w->color == Node::Red) { + w->color = Node::Black; + x_parent->color = Node::Red; + rotateRight(x_parent, root); + w = x_parent->left; + } + if ((w->right == 0 || w->right->color == Node::Black) && + (w->left == 0 || w->left->color == Node::Black)) { + w->color = Node::Red; + x = x_parent; + x_parent = x_parent->parent; + } else { + if (w->left == 0 || w->left->color == Node::Black) { + if (w->right) + w->right->color = Node::Black; + w->color = Node::Red; + rotateLeft(w, root); + w = x_parent->left; + } + w->color = x_parent->color; + x_parent->color = Node::Black; + if (w->left) + w->left->color = Node::Black; + rotateRight(x_parent, root); + break; + } + } + } + if (x) + x->color = Node::Black; + } + return y; +} diff --git a/qmake/tools/qmutex_unix.cpp b/qmake/tools/qmutex_unix.cpp new file mode 100644 index 0000000..c861b2d --- a/dev/null +++ b/qmake/tools/qmutex_unix.cpp @@ -0,0 +1,687 @@ +/**************************************************************************** +** $Id$ +** +** QMutex class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#if defined(QT_THREAD_SUPPORT) + +#include "qplatformdefs.h" + +typedef pthread_mutex_t Q_MUTEX_T; + +// POSIX threads mutex types +#if ((defined(PTHREAD_MUTEX_RECURSIVE) && defined(PTHREAD_MUTEX_DEFAULT)) || \ + defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) + // POSIX 1003.1c-1995 - We love this OS +# define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_settype((a), (b)) +# if defined(QT_CHECK_RANGE) +# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK +# else +# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT +# endif +# define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE +#elif defined(MUTEX_NONRECURSIVE_NP) && defined(MUTEX_RECURSIVE_NP) +// POSIX 1003.4a pthreads draft extensions +# define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_setkind_np((a), (b)); +# define Q_NORMAL_MUTEX_TYPE MUTEX_NONRECURSIVE_NP +# define Q_RECURSIVE_MUTEX_TYPE MUTEX_RECURSIVE_NP +#else +// Unknown mutex types - skip them +# define Q_MUTEX_SET_TYPE(a, b) +# undef Q_NORMAL_MUTEX_TYPE +# undef Q_RECURSIVE_MUTEX_TYPE +#endif + +#include "qmutex.h" +#include "qmutex_p.h" + +#include <errno.h> +#include <string.h> + + +// Private class declarations + +class QRealMutexPrivate : public QMutexPrivate { +public: + QRealMutexPrivate(bool = FALSE); + + void lock(); + void unlock(); + bool locked(); + bool trylock(); + int type() const; + + bool recursive; +}; + +#ifndef Q_RECURSIVE_MUTEX_TYPE +class QRecursiveMutexPrivate : public QMutexPrivate +{ +public: + QRecursiveMutexPrivate(); + ~QRecursiveMutexPrivate(); + + void lock(); + void unlock(); + bool locked(); + bool trylock(); + int type() const; + + int count; + unsigned long owner; + pthread_mutex_t handle2; +}; +#endif // !Q_RECURSIVE_MUTEX_TYPE + + +// Private class implementation + +// base destructor +QMutexPrivate::~QMutexPrivate() +{ + int ret = pthread_mutex_destroy(&handle); + +#ifdef QT_CHECK_RANGE + if ( ret ) + qWarning( "Mutex destroy failure: %s", strerror( ret ) ); +#endif +} + +// real mutex class +QRealMutexPrivate::QRealMutexPrivate(bool recurs) + : recursive(recurs) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + Q_MUTEX_SET_TYPE(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); + Q_UNUSED(recursive); + int ret = pthread_mutex_init(&handle, &attr); + pthread_mutexattr_destroy(&attr); + +#ifdef QT_CHECK_RANGE + if( ret ) + qWarning( "Mutex init failure: %s", strerror( ret ) ); +#endif // QT_CHECK_RANGE +} + +void QRealMutexPrivate::lock() +{ + int ret = pthread_mutex_lock(&handle); + +#ifdef QT_CHECK_RANGE + if (ret) + qWarning("Mutex lock failure: %s", strerror(ret)); +#endif +} + +void QRealMutexPrivate::unlock() +{ + int ret = pthread_mutex_unlock(&handle); + +#ifdef QT_CHECK_RANGE + if (ret) + qWarning("Mutex unlock failure: %s", strerror(ret)); +#endif +} + +bool QRealMutexPrivate::locked() +{ + int ret = pthread_mutex_trylock(&handle); + + if (ret == EBUSY) { + return TRUE; + } else if (ret) { +#ifdef QT_CHECK_RANGE + qWarning("Mutex locktest failure: %s", strerror(ret)); +#endif + } else + pthread_mutex_unlock(&handle); + + return FALSE; +} + +bool QRealMutexPrivate::trylock() +{ + int ret = pthread_mutex_trylock(&handle); + + if (ret == EBUSY) { + return FALSE; + } else if (ret) { +#ifdef QT_CHECK_RANGE + qWarning("Mutex trylock failure: %s", strerror(ret)); +#endif + return FALSE; + } + + return TRUE; +} + +int QRealMutexPrivate::type() const +{ + return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; +} + + +#ifndef Q_RECURSIVE_MUTEX_TYPE +QRecursiveMutexPrivate::QRecursiveMutexPrivate() + : count(0), owner(0) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + Q_MUTEX_SET_TYPE(&attr, Q_NORMAL_MUTEX_TYPE); + int ret = pthread_mutex_init(&handle, &attr); + pthread_mutexattr_destroy(&attr); + +# ifdef QT_CHECK_RANGE + if (ret) + qWarning( "Mutex init failure: %s", strerror(ret) ); +# endif + + pthread_mutexattr_init(&attr); + ret = pthread_mutex_init( &handle2, &attr ); + pthread_mutexattr_destroy(&attr); + +# ifdef QT_CHECK_RANGE + if (ret) + qWarning( "Mutex init failure: %s", strerror(ret) ); +# endif +} + +QRecursiveMutexPrivate::~QRecursiveMutexPrivate() +{ + int ret = pthread_mutex_destroy(&handle2); + +# ifdef QT_CHECK_RANGE + if (ret) + qWarning( "Mutex destroy failure: %s", strerror(ret) ); +# endif +} + +void QRecursiveMutexPrivate::lock() +{ + pthread_mutex_lock(&handle2); + + if (count > 0 && owner == (unsigned long) pthread_self()) { + count++; + } else { + pthread_mutex_unlock(&handle2); + pthread_mutex_lock(&handle); + pthread_mutex_lock(&handle2); + count = 1; + owner = (unsigned long) pthread_self(); + } + + pthread_mutex_unlock(&handle2); +} + +void QRecursiveMutexPrivate::unlock() +{ + pthread_mutex_lock(&handle2); + + if (owner == (unsigned long) pthread_self()) { + // do nothing if the count is already 0... to reflect the behaviour described + // in the docs + if (count && (--count) < 1) { + count = 0; + pthread_mutex_unlock(&handle); + } + } else { +#ifdef QT_CHECK_RANGE + qWarning("QMutex::unlock: unlock from different thread than locker"); + qWarning(" was locked by %d, unlock attempt from %d", + (int)owner, (int)pthread_self()); +#endif + } + + pthread_mutex_unlock(&handle2); +} + +bool QRecursiveMutexPrivate::locked() +{ + pthread_mutex_lock(&handle2); + + bool ret; + int code = pthread_mutex_trylock(&handle); + + if (code == EBUSY) { + ret = TRUE; + } else { +#ifdef QT_CHECK_RANGE + if (code) + qWarning("Mutex trylock failure: %s", strerror(code)); +#endif + + pthread_mutex_unlock(&handle); + ret = FALSE; + } + + pthread_mutex_unlock(&handle2); + + return ret; +} + +bool QRecursiveMutexPrivate::trylock() +{ + bool ret = TRUE; + + pthread_mutex_lock(&handle2); + + if ( count > 0 && owner == (unsigned long) pthread_self() ) { + count++; + } else { + int code = pthread_mutex_trylock(&handle); + + if (code == EBUSY) { + ret = FALSE; + } else if (code) { +#ifdef QT_CHECK_RANGE + qWarning("Mutex trylock failure: %s", strerror(code)); +#endif + ret = FALSE; + } else { + count = 1; + owner = (unsigned long) pthread_self(); + } + } + + pthread_mutex_unlock(&handle2); + + return ret; +} + +int QRecursiveMutexPrivate::type() const +{ + return Q_MUTEX_RECURSIVE; +} + +#endif // !Q_RECURSIVE_MUTEX_TYPE + + +/*! + \class QMutex qmutex.h + \threadsafe + \brief The QMutex class provides access serialization between threads. + + \ingroup thread + \ingroup environment + + The purpose of a QMutex is to protect an object, data structure or + section of code so that only one thread can access it at a time + (This is similar to the Java \c synchronized keyword). For + example, say there is a method which prints a message to the user + on two lines: + + \code + int number = 6; + + void method1() + { + number *= 5; + number /= 4; + } + + void method1() + { + number *= 3; + number /= 2; + } + \endcode + + If these two methods are called in succession, the following happens: + + \code + // method1() + number *= 5; // number is now 30 + number /= 4; // number is now 7 + + // method2() + number *= 3; // nubmer is now 21 + number /= 2; // number is now 10 + \endcode + + If these two methods are called simultaneously from two threads then the + following sequence could result: + + \code + // Thread 1 calls method1() + number *= 5; // number is now 30 + + // Thread 2 calls method2(). + // + // Most likely Thread 1 has been put to sleep by the operating + // system to allow Thread 2 to run. + number *= 3; // number is now 90 + number /= 2; // number is now 45 + + // Thread 1 finishes executing. + number /= 4; // number is now 11, instead of 10 + \endcode + + If we add a mutex, we should get the result we want: + + \code + QMutex mutex; + int number = 6; + + void method1() + { + mutex.lock(); + number *= 5; + number /= 4; + mutex.unlock(); + } + + void method2() + { + mutex.lock(); + number *= 3; + number /= 2; + mutex.unlock(); + } + \endcode + + Then only one thread can modify \c number at any given time and + the result is correct. This is a trivial example, of course, but + applies to any other case where things need to happen in a + particular sequence. + + When you call lock() in a thread, other threads that try to call + lock() in the same place will block until the thread that got the + lock calls unlock(). A non-blocking alternative to lock() is + tryLock(). +*/ + +/*! + Constructs a new mutex. The mutex is created in an unlocked state. + A recursive mutex is created if \a recursive is TRUE; a normal + mutex is created if \a recursive is FALSE (the default). With a + recursive mutex, a thread can lock the same mutex multiple times + and it will not be unlocked until a corresponding number of + unlock() calls have been made. +*/ +QMutex::QMutex(bool recursive) +{ +#ifndef Q_RECURSIVE_MUTEX_TYPE + if ( recursive ) + d = new QRecursiveMutexPrivate(); + else +#endif // !Q_RECURSIVE_MUTEX_TYPE + d = new QRealMutexPrivate(recursive); +} + +/*! + Destroys the mutex. + + \warning If you destroy a mutex that still holds a lock the + resultant behavior is undefined. +*/ +QMutex::~QMutex() +{ + delete d; +} + +/*! + Attempt to lock the mutex. If another thread has locked the mutex + then this call will \e block until that thread has unlocked it. + + \sa unlock(), locked() +*/ +void QMutex::lock() +{ + d->lock(); +} + +/*! + Unlocks the mutex. Attempting to unlock a mutex in a different + thread to the one that locked it results in an error. Unlocking a + mutex that is not locked results in undefined behaviour (varies + between different Operating Systems' thread implementations). + + \sa lock(), locked() +*/ +void QMutex::unlock() +{ + d->unlock(); +} + +/*! + Returns TRUE if the mutex is locked by another thread; otherwise + returns FALSE. + + \warning Due to differing implementations of recursive mutexes on + various platforms, calling this function from the same thread that + previously locked the mutex will return undefined results. + + \sa lock(), unlock() +*/ +bool QMutex::locked() +{ + return d->locked(); +} + +/*! + Attempt to lock the mutex. If the lock was obtained, this function + returns TRUE. If another thread has locked the mutex, this + function returns FALSE, instead of waiting for the mutex to become + available, i.e. it does not block. + + If the lock was obtained, the mutex must be unlocked with unlock() + before another thread can successfully lock it. + + \sa lock(), unlock(), locked() +*/ +bool QMutex::tryLock() +{ + return d->trylock(); +} + +/*! + \class QMutexLocker qmutex.h + \brief The QMutexLocker class simplifies locking and unlocking QMutexes. + + \threadsafe + + \ingroup thread + \ingroup environment + + The purpose of QMutexLocker is to simplify QMutex locking and + unlocking. Locking and unlocking a QMutex in complex functions and + statements or in exception handling code is error prone and + difficult to debug. QMutexLocker should be used in such situations + to ensure that the state of the mutex is well defined and always + locked and unlocked properly. + + QMutexLocker should be created within a function where a QMutex + needs to be locked. The mutex is locked when QMutexLocker is + created, and unlocked when QMutexLocker is destroyed. + + For example, this complex function locks a QMutex upon entering + the function and unlocks the mutex at all the exit points: + + \code + int complexFunction( int flag ) + { + mutex.lock(); + + int return_value = 0; + + switch ( flag ) { + case 0: + case 1: + { + mutex.unlock(); + return moreComplexFunction( flag ); + } + + case 2: + { + int status = anotherFunction(); + if ( status < 0 ) { + mutex.unlock(); + return -2; + } + return_value = status + flag; + break; + } + + default: + { + if ( flag > 10 ) { + mutex.unlock(); + return -1; + } + break; + } + } + + mutex.unlock(); + return return_value; + } + \endcode + + This example function will get more complicated as it is + developed, which increases the likelihood that errors will occur. + + Using QMutexLocker greatly simplifies the code, and makes it more + readable: + + \code + int complexFunction( int flag ) + { + QMutexLocker locker( &mutex ); + + int return_value = 0; + + switch ( flag ) { + case 0: + case 1: + { + return moreComplexFunction( flag ); + } + + case 2: + { + int status = anotherFunction(); + if ( status < 0 ) + return -2; + return_value = status + flag; + break; + } + + default: + { + if ( flag > 10 ) + return -1; + break; + } + } + + return return_value; + } + \endcode + + Now, the mutex will always be unlocked when the QMutexLocker + object is destroyed (when the function returns since \c locker is + an auto variable). + + The same principle applies to code that throws and catches + exceptions. An exception that is not caught in the function that + has locked the mutex has no way of unlocking the mutex before the + exception is passed up the stack to the calling function. + + QMutexLocker also provides a mutex() member function that returns + the mutex on which the QMutexLocker is operating. This is useful + for code that needs access to the mutex, such as + QWaitCondition::wait(). For example: + + \code + class SignalWaiter + { + private: + QMutexLocker locker; + + public: + SignalWaiter( QMutex *mutex ) + : locker( mutex ) + { + } + + void waitForSignal() + { + ... + ... + ... + + while ( ! signalled ) + waitcondition.wait( locker.mutex() ); + + ... + ... + ... + } + }; + \endcode + + \sa QMutex, QWaitCondition +*/ + +/*! + \fn QMutexLocker::QMutexLocker( QMutex *mutex ) + + Constructs a QMutexLocker and locks \a mutex. The mutex will be + unlocked when the QMutexLocker is destroyed. + + \sa QMutex::lock() +*/ + +/*! + \fn QMutexLocker::~QMutexLocker() + + Destroys the QMutexLocker and unlocks the mutex which was locked + in the constructor. + + \sa QMutexLocker::QMutexLocker(), QMutex::unlock() +*/ + +/*! + \fn QMutex *QMutexLocker::mutex() const + + Returns a pointer to the mutex which was locked in the + constructor. + + \sa QMutexLocker::QMutexLocker() +*/ + +#endif // QT_THREAD_SUPPORT diff --git a/qmake/tools/qmutexpool.cpp b/qmake/tools/qmutexpool.cpp new file mode 100644 index 0000000..9ed2829 --- a/dev/null +++ b/qmake/tools/qmutexpool.cpp @@ -0,0 +1,130 @@ +#include "qmutexpool_p.h" + +#ifdef QT_THREAD_SUPPORT + +#include <qthread.h> +#include <stdio.h> + +QMutexPool *qt_global_mutexpool = 0; + +// this is an internal class used only for inititalizing the global mutexpool +class QGlobalMutexPoolInitializer +{ +public: + inline QGlobalMutexPoolInitializer() + { + /* + Purify will report a leak here. However, this mutex pool must be alive + until *everything* in Qt has been destructed. Unfortunately there is + no way to guarantee this, so we never destroy this mutex pool. + */ + qt_global_mutexpool = new QMutexPool( TRUE ); + } +}; +QGlobalMutexPoolInitializer qt_global_mutexpool_initializer; + +/*! + \class QMutexPool qmutexpool_p.h + \brief The QMutexPool class provides a pool of QMutex objects. + + \internal + + \ingroup thread + + QMutexPool is a convenience class that provides access to a fixed + number of QMutex objects. + + Typical use of a QMutexPool is in situations where it is not + possible or feasible to use one QMutex for every protected object. + The mutex pool will return a mutex based on the address of the + object that needs protection. + + For example, consider this simple class: + + \code + class Number { + public: + Number( double n ) : num ( n ) { } + + void setNumber( double n ) { num = n; } + double number() const { return num; } + + private: + double num; + }; + \endcode + + Adding a QMutex member to the Number class does not make sense, + because it is so small. However, in order to ensure that access to + each Number is protected, you need to use a mutex. In this case, a + QMutexPool would be ideal. + + Code to calculate the square of a number would then look something + like this: + + \code + void calcSquare( Number *num ) + { + QMutexLocker locker( mutexpool.get( num ) ); + num.setNumber( num.number() * num.number() ); + } + \endcode + + This function will safely calculate the square of a number, since + it uses a mutex from a QMutexPool. The mutex is locked and + unlocked automatically by the QMutexLocker class. See the + QMutexLocker documentation for more details. +*/ + +/*! + Constructs a QMutexPool, reserving space for \a size QMutexes. If + \a recursive is TRUE, all QMutexes in the pool will be recursive + mutexes; otherwise they will all be non-recursive (the default). + + The QMutexes are created when needed, and deleted when the + QMutexPool is destructed. +*/ +QMutexPool::QMutexPool( bool recursive, int size ) + : mutex( FALSE ), mutexes( size ), recurs( recursive ) +{ + mutexes.fill( 0 ); +} + +/*! + Destructs a QMutexPool. All QMutexes that were created by the pool + are deleted. +*/ +QMutexPool::~QMutexPool() +{ + QMutexLocker locker( &mutex ); + QMutex **d = mutexes.data(); + for ( int index = 0; (uint) index < mutexes.size(); index++ ) { + delete d[index]; + d[index] = 0; + } +} + +/*! + Returns a QMutex from the pool. QMutexPool uses the value \a + address to determine which mutex is retured from the pool. +*/ +QMutex *QMutexPool::get( void *address ) +{ + QMutex **d = mutexes.data(); + int index = (int)( (ulong) address % mutexes.size() ); + + if ( ! d[index] ) { + // mutex not created, create one + + QMutexLocker locker( &mutex ); + // we need to check once again that the mutex hasn't been created, since + // 2 threads could be trying to create a mutex as the same index... + if ( ! d[index] ) { + d[index] = new QMutex( recurs ); + } + } + + return d[index]; +} + +#endif diff --git a/qmake/tools/qptrcollection.cpp b/qmake/tools/qptrcollection.cpp new file mode 100644 index 0000000..304ec1b --- a/dev/null +++ b/qmake/tools/qptrcollection.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of base class for all pointer based collection classes +** +** Created : 920820 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qptrcollection.h" + +/*! + \class QPtrCollection qptrcollection.h + \reentrant + \brief The QPtrCollection class is the base class of most pointer-based Qt collections. + + \ingroup collection + \ingroup tools + + The QPtrCollection class is an abstract base class for the Qt + \link collection.html collection classes\endlink QDict, QPtrList, + etc. Qt also includes value based collections, e.g. QValueList, + QMap, etc. + + A QPtrCollection only knows about the number of objects in the + collection and the deletion strategy (see setAutoDelete()). + + A collection is implemented using the \c Item (generic collection + item) type, which is a \c void*. The template classes that create + the real collections cast the \c Item to the required type. +*/ + + +/*! + \enum QPtrCollection::Item + + This type is the generic "item" in a QPtrCollection. +*/ + + +/*! + \fn QPtrCollection::QPtrCollection() + + Constructs a collection. The constructor is protected because + QPtrCollection is an abstract class. +*/ + +/*! + \fn QPtrCollection::QPtrCollection( const QPtrCollection & source ) + + Constructs a copy of \a source with autoDelete() set to FALSE. The + constructor is protected because QPtrCollection is an abstract + class. + + Note that if \a source has autoDelete turned on, copying it will + risk memory leaks, reading freed memory, or both. +*/ + +/*! + \fn QPtrCollection::~QPtrCollection() + + Destroys the collection. The destructor is protected because + QPtrCollection is an abstract class. +*/ + + +/*! + \fn bool QPtrCollection::autoDelete() const + + Returns the setting of the auto-delete option. The default is FALSE. + + \sa setAutoDelete() +*/ + +/*! + \fn void QPtrCollection::setAutoDelete( bool enable ) + + Sets the collection to auto-delete its contents if \a enable is + TRUE and to never delete them if \a enable is FALSE. + + If auto-deleting is turned on, all the items in a collection are + deleted when the collection itself is deleted. This is convenient + if the collection has the only pointer to the items. + + The default setting is FALSE, for safety. If you turn it on, be + careful about copying the collection - you might find yourself + with two collections deleting the same items. + + Note that the auto-delete setting may also affect other functions + in subclasses. For example, a subclass that has a remove() + function will remove the item from its data structure, and if + auto-delete is enabled, will also delete the item. + + \sa autoDelete() +*/ + + +/*! + \fn virtual uint QPtrCollection::count() const + + Returns the number of objects in the collection. +*/ + +/*! + \fn virtual void QPtrCollection::clear() + + Removes all objects from the collection. The objects will be + deleted if auto-delete has been enabled. + + \sa setAutoDelete() +*/ + +/*! + \fn void QPtrCollection::deleteItem( Item d ) + + Reimplement this function if you want to be able to delete items. + + Deletes an item that is about to be removed from the collection. + + This function has to reimplemented in the collection template + classes, and should \e only delete item \a d if auto-delete has + been enabled. + + \warning If you reimplement this function you must also + reimplement the destructor and call the virtual function clear() + from your destructor. This is due to the way virtual functions and + destructors work in C++: Virtual functions in derived classes + cannot be called from a destructor. If you do not do this, your + deleteItem() function will not be called when the container is + destroyed. + + \sa newItem(), setAutoDelete() +*/ + +/*! + Virtual function that creates a copy of an object that is about to + be inserted into the collection. + + The default implementation returns the \a d pointer, i.e. no copy + is made. + + This function is seldom reimplemented in the collection template + classes. It is not common practice to make a copy of something + that is being inserted. + + \sa deleteItem() +*/ + +QPtrCollection::Item QPtrCollection::newItem( Item d ) +{ + return d; // just return reference +} diff --git a/qmake/tools/qregexp.cpp b/qmake/tools/qregexp.cpp new file mode 100644 index 0000000..500efed --- a/dev/null +++ b/qmake/tools/qregexp.cpp @@ -0,0 +1,3935 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QRegExp class +** +** Created : 950126 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qregexp.h" + +#ifndef QT_NO_REGEXP + +#include "qmemarray.h" +#include "qbitarray.h" +#include "qcache.h" +#include "qcleanuphandler.h" +#include "qintdict.h" +#include "qmap.h" +#include "qptrvector.h" +#include "qstring.h" +#include "qtl.h" + +#ifdef QT_THREAD_SUPPORT +#include "qmutexpool_p.h" +#endif // QT_THREAD_SUPPORT + +#undef QT_TRANSLATE_NOOP +#define QT_TRANSLATE_NOOP( context, sourceText ) sourceText + +#include <limits.h> + +// error strings for the regexp parser +#define RXERR_OK QT_TRANSLATE_NOOP( "QRegExp", "no error occurred" ) +#define RXERR_DISABLED QT_TRANSLATE_NOOP( "QRegExp", "disabled feature used" ) +#define RXERR_CHARCLASS QT_TRANSLATE_NOOP( "QRegExp", "bad char class syntax" ) +#define RXERR_LOOKAHEAD QT_TRANSLATE_NOOP( "QRegExp", "bad lookahead syntax" ) +#define RXERR_REPETITION QT_TRANSLATE_NOOP( "QRegExp", "bad repetition syntax" ) +#define RXERR_OCTAL QT_TRANSLATE_NOOP( "QRegExp", "invalid octal value" ) +#define RXERR_LEFTDELIM QT_TRANSLATE_NOOP( "QRegExp", "missing left delim" ) +#define RXERR_END QT_TRANSLATE_NOOP( "QRegExp", "unexpected end" ) +#define RXERR_LIMIT QT_TRANSLATE_NOOP( "QRegExp", "met internal limit" ) + +/* + WARNING! Be sure to read qregexp.tex before modifying this file. +*/ + +/*! + \class QRegExp qregexp.h + \reentrant + \brief The QRegExp class provides pattern matching using regular expressions. + + \ingroup tools + \ingroup misc + \ingroup shared + \mainclass + \keyword regular expression + + Regular expressions, or "regexps", provide a way to find patterns + within text. This is useful in many contexts, for example: + + \table + \row \i Validation + \i A regexp can be used to check whether a piece of text + meets some criteria, e.g. is an integer or contains no + whitespace. + \row \i Searching + \i Regexps provide a much more powerful means of searching + text than simple string matching does. For example we can + create a regexp which says "find one of the words 'mail', + 'letter' or 'correspondence' but not any of the words + 'email', 'mailman' 'mailer', 'letterbox' etc." + \row \i Search and Replace + \i A regexp can be used to replace a pattern with a piece of + text, for example replace all occurrences of '&' with + '\&' except where the '&' is already followed by 'amp;'. + \row \i String Splitting + \i A regexp can be used to identify where a string should be + split into its component fields, e.g. splitting tab-delimited + strings. + \endtable + + We present a very brief introduction to regexps, a description of + Qt's regexp language, some code examples, and finally the function + documentation itself. QRegExp is modeled on Perl's regexp + language, and also fully supports Unicode. QRegExp can also be + used in the weaker 'wildcard' (globbing) mode which works in a + similar way to command shells. A good text on regexps is \e + {Mastering Regular Expressions: Powerful Techniques for Perl and + Other Tools} by Jeffrey E. Friedl, ISBN 1565922573. + + Experienced regexp users may prefer to skip the introduction and + go directly to the relevant information. + + \tableofcontents + + \section1 Introduction + + Regexps are built up from expressions, quantifiers, and assertions. + The simplest form of expression is simply a character, e.g. + <b>x</b> or <b>5</b>. An expression can also be a set of + characters. For example, <b>[ABCD]</b>, will match an <b>A</b> or + a <b>B</b> or a <b>C</b> or a <b>D</b>. As a shorthand we could + write this as <b>[A-D]</b>. If we want to match any of the + captital letters in the English alphabet we can write + <b>[A-Z]</b>. A quantifier tells the regexp engine how many + occurrences of the expression we want, e.g. <b>x{1,1}</b> means + match an <b>x</b> which occurs at least once and at most once. + We'll look at assertions and more complex expressions later. + + Note that in general regexps cannot be used to check for balanced + brackets or tags. For example if you want to match an opening html + \c <b> and its closing \c </b> you can only use a regexp if you + know that these tags are not nested; the html fragment, \c{<b>bold + <b>bolder</b></b>} will not match as expected. If you know the + maximum level of nesting it is possible to create a regexp that + will match correctly, but for an unknown level of nesting, regexps + will fail. + + We'll start by writing a regexp to match integers in the range 0 + to 99. We will require at least one digit so we will start with + <b>[0-9]{1,1}</b> which means match a digit exactly once. This + regexp alone will match integers in the range 0 to 9. To match one + or two digits we can increase the maximum number of occurrences so + the regexp becomes <b>[0-9]{1,2}</b> meaning match a digit at + least once and at most twice. However, this regexp as it stands + will not match correctly. This regexp will match one or two digits + \e within a string. To ensure that we match against the whole + string we must use the anchor assertions. We need <b>^</b> (caret) + which when it is the first character in the regexp means that the + regexp must match from the beginning of the string. And we also + need <b>$</b> (dollar) which when it is the last character in the + regexp means that the regexp must match until the end of the + string. So now our regexp is <b>^[0-9]{1,2}$</b>. Note that + assertions, such as <b>^</b> and <b>$</b>, do not match any + characters. + + If you've seen regexps elsewhere they may have looked different from + the ones above. This is because some sets of characters and some + quantifiers are so common that they have special symbols to + represent them. <b>[0-9]</b> can be replaced with the symbol + <b>\d</b>. The quantifier to match exactly one occurrence, + <b>{1,1}</b>, can be replaced with the expression itself. This means + that <b>x{1,1}</b> is exactly the same as <b>x</b> alone. So our 0 + to 99 matcher could be written <b>^\d{1,2}$</b>. Another way of + writing it would be <b>^\d\d{0,1}$</b>, i.e. from the start of the + string match a digit followed by zero or one digits. In practice + most people would write it <b>^\d\d?$</b>. The <b>?</b> is a + shorthand for the quantifier <b>{0,1}</b>, i.e. a minimum of no + occurrences a maximum of one occurrence. This is used to make an + expression optional. The regexp <b>^\d\d?$</b> means "from the + beginning of the string match one digit followed by zero or one + digits and then the end of the string". + + Our second example is matching the words 'mail', 'letter' or + 'correspondence' but without matching 'email', 'mailman', + 'mailer', 'letterbox' etc. We'll start by just matching 'mail'. In + full the regexp is, <b>m{1,1}a{1,1}i{1,1}l{1,1}</b>, but since + each expression itself is automatically quantified by <b>{1,1}</b> + we can simply write this as <b>mail</b>; an 'm' followed by an 'a' + followed by an 'i' followed by an 'l'. The symbol '|' (bar) is + used for \e alternation, so our regexp now becomes + <b>mail|letter|correspondence</b> which means match 'mail' \e or + 'letter' \e or 'correspondence'. Whilst this regexp will find the + words we want it will also find words we don't want such as + 'email'. We will start by putting our regexp in parentheses, + <b>(mail|letter|correspondence)</b>. Parentheses have two effects, + firstly they group expressions together and secondly they identify + parts of the regexp that we wish to \link #capturing-text capture + \endlink. Our regexp still matches any of the three words but now + they are grouped together as a unit. This is useful for building + up more complex regexps. It is also useful because it allows us to + examine which of the words actually matched. We need to use + another assertion, this time <b>\b</b> "word boundary": + <b>\b(mail|letter|correspondence)\b</b>. This regexp means "match + a word boundary followed by the expression in parentheses followed + by another word boundary". The <b>\b</b> assertion matches at a \e + position in the regexp not a \e character in the regexp. A word + boundary is any non-word character such as a space a newline or + the beginning or end of the string. + + For our third example we want to replace ampersands with the HTML + entity '\&'. The regexp to match is simple: <b>\&</b>, i.e. + match one ampersand. Unfortunately this will mess up our text if + some of the ampersands have already been turned into HTML + entities. So what we really want to say is replace an ampersand + providing it is not followed by 'amp;'. For this we need the + negative lookahead assertion and our regexp becomes: + <b>\&(?!amp;)</b>. The negative lookahead assertion is introduced + with '(?!' and finishes at the ')'. It means that the text it + contains, 'amp;' in our example, must \e not follow the expression + that preceeds it. + + Regexps provide a rich language that can be used in a variety of + ways. For example suppose we want to count all the occurrences of + 'Eric' and 'Eirik' in a string. Two valid regexps to match these + are <b>\\b(Eric|Eirik)\\b</b> and <b>\\bEi?ri[ck]\\b</b>. We need + the word boundary '\b' so we don't get 'Ericsson' etc. The second + regexp actually matches more than we want, 'Eric', 'Erik', 'Eiric' + and 'Eirik'. + + We will implement some the examples above in the + \link #code-examples code examples \endlink section. + + \target characters-and-abbreviations-for-sets-of-characters + \section1 Characters and Abbreviations for Sets of Characters + + \table + \header \i Element \i Meaning + \row \i <b>c</b> + \i Any character represents itself unless it has a special + regexp meaning. Thus <b>c</b> matches the character \e c. + \row \i <b>\\c</b> + \i A character that follows a backslash matches the character + itself except where mentioned below. For example if you + wished to match a literal caret at the beginning of a string + you would write <b>\^</b>. + \row \i <b>\\a</b> + \i This matches the ASCII bell character (BEL, 0x07). + \row \i <b>\\f</b> + \i This matches the ASCII form feed character (FF, 0x0C). + \row \i <b>\\n</b> + \i This matches the ASCII line feed character (LF, 0x0A, Unix newline). + \row \i <b>\\r</b> + \i This matches the ASCII carriage return character (CR, 0x0D). + \row \i <b>\\t</b> + \i This matches the ASCII horizontal tab character (HT, 0x09). + \row \i <b>\\v</b> + \i This matches the ASCII vertical tab character (VT, 0x0B). + \row \i <b>\\xhhhh</b> + \i This matches the Unicode character corresponding to the + hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo + (i.e., \zero ooo) matches the ASCII/Latin-1 character + corresponding to the octal number ooo (between 0 and 0377). + \row \i <b>. (dot)</b> + \i This matches any character (including newline). + \row \i <b>\\d</b> + \i This matches a digit (see QChar::isDigit()). + \row \i <b>\\D</b> + \i This matches a non-digit. + \row \i <b>\\s</b> + \i This matches a whitespace (see QChar::isSpace()). + \row \i <b>\\S</b> + \i This matches a non-whitespace. + \row \i <b>\\w</b> + \i This matches a word character (see QChar::isLetterOrNumber()). + \row \i <b>\\W</b> + \i This matches a non-word character. + \row \i <b>\\n</b> + \i The n-th \link #capturing-text backreference \endlink, + e.g. \1, \2, etc. + \endtable + + \e {Note that the C++ compiler transforms backslashes in strings + so to include a <b>\\</b> in a regexp you will need to enter it + twice, i.e. <b>\\\\</b>.} + + \target sets-of-characters + \section1 Sets of Characters + + Square brackets are used to match any character in the set of + characters contained within the square brackets. All the character + set abbreviations described above can be used within square + brackets. Apart from the character set abbreviations and the + following two exceptions no characters have special meanings in + square brackets. + + \table + \row \i <b>^</b> + \i The caret negates the character set if it occurs as the + first character, i.e. immediately after the opening square + bracket. For example, <b>[abc]</b> matches 'a' or 'b' or 'c', + but <b>[^abc]</b> matches anything \e except 'a' or 'b' or + 'c'. + \row \i <b>-</b> + \i The dash is used to indicate a range of characters, for + example <b>[W-Z]</b> matches 'W' or 'X' or 'Y' or 'Z'. + \endtable + + Using the predefined character set abbreviations is more portable + than using character ranges across platforms and languages. For + example, <b>[0-9]</b> matches a digit in Western alphabets but + <b>\d</b> matches a digit in \e any alphabet. + + Note that in most regexp literature sets of characters are called + "character classes". + + \target quantifiers + \section1 Quantifiers + + By default an expression is automatically quantified by + <b>{1,1}</b>, i.e. it should occur exactly once. In the following + list <b>\e {E}</b> stands for any expression. An expression is a + character or an abbreviation for a set of characters or a set of + characters in square brackets or any parenthesised expression. + + \table + \row \i <b>\e {E}?</b> + \i Matches zero or one occurrence of \e E. This quantifier + means "the previous expression is optional" since it will + match whether or not the expression occurs in the string. It + is the same as <b>\e {E}{0,1}</b>. For example <b>dents?</b> + will match 'dent' and 'dents'. + + \row \i <b>\e {E}+</b> + \i Matches one or more occurrences of \e E. This is the same + as <b>\e {E}{1,MAXINT}</b>. For example, <b>0+</b> will match + '0', '00', '000', etc. + + \row \i <b>\e {E}*</b> + \i Matches zero or more occurrences of \e E. This is the same + as <b>\e {E}{0,MAXINT}</b>. The <b>*</b> quantifier is often + used by a mistake. Since it matches \e zero or more + occurrences it will match no occurrences at all. For example + if we want to match strings that end in whitespace and use + the regexp <b>\s*$</b> we would get a match on every string. + This is because we have said find zero or more whitespace + followed by the end of string, so even strings that don't end + in whitespace will match. The regexp we want in this case is + <b>\s+$</b> to match strings that have at least one + whitespace at the end. + + \row \i <b>\e {E}{n}</b> + \i Matches exactly \e n occurrences of the expression. This + is the same as repeating the expression \e n times. For + example, <b>x{5}</b> is the same as <b>xxxxx</b>. It is also + the same as <b>\e {E}{n,n}</b>, e.g. <b>x{5,5}</b>. + + \row \i <b>\e {E}{n,}</b> + \i Matches at least \e n occurrences of the expression. This + is the same as <b>\e {E}{n,MAXINT}</b>. + + \row \i <b>\e {E}{,m}</b> + \i Matches at most \e m occurrences of the expression. This + is the same as <b>\e {E}{0,m}</b>. + + \row \i <b>\e {E}{n,m}</b> + \i Matches at least \e n occurrences of the expression and at + most \e m occurrences of the expression. + \endtable + + (MAXINT is implementation dependent but will not be smaller than + 1024.) + + If we wish to apply a quantifier to more than just the preceding + character we can use parentheses to group characters together in + an expression. For example, <b>tag+</b> matches a 't' followed by + an 'a' followed by at least one 'g', whereas <b>(tag)+</b> matches + at least one occurrence of 'tag'. + + Note that quantifiers are "greedy". They will match as much text + as they can. For example, <b>0+</b> will match as many zeros as it + can from the first zero it finds, e.g. '2.<u>000</u>5'. + Quantifiers can be made non-greedy, see setMinimal(). + + \target capturing-text + \section1 Capturing Text + + Parentheses allow us to group elements together so that we can + quantify and capture them. For example if we have the expression + <b>mail|letter|correspondence</b> that matches a string we know + that \e one of the words matched but not which one. Using + parentheses allows us to "capture" whatever is matched within + their bounds, so if we used <b>(mail|letter|correspondence)</b> + and matched this regexp against the string "I sent you some email" + we can use the cap() or capturedTexts() functions to extract the + matched characters, in this case 'mail'. + + We can use captured text within the regexp itself. To refer to the + captured text we use \e backreferences which are indexed from 1, + the same as for cap(). For example we could search for duplicate + words in a string using <b>\b(\w+)\W+\1\b</b> which means match a + word boundary followed by one or more word characters followed by + one or more non-word characters followed by the same text as the + first parenthesised expression followed by a word boundary. + + If we want to use parentheses purely for grouping and not for + capturing we can use the non-capturing syntax, e.g. + <b>(?:green|blue)</b>. Non-capturing parentheses begin '(?:' and + end ')'. In this example we match either 'green' or 'blue' but we + do not capture the match so we only know whether or not we matched + but not which color we actually found. Using non-capturing + parentheses is more efficient than using capturing parentheses + since the regexp engine has to do less book-keeping. + + Both capturing and non-capturing parentheses may be nested. + + \target assertions + \section1 Assertions + + Assertions make some statement about the text at the point where + they occur in the regexp but they do not match any characters. In + the following list <b>\e {E}</b> stands for any expression. + + \table + \row \i <b>^</b> + \i The caret signifies the beginning of the string. If you + wish to match a literal \c{^} you must escape it by + writing \c{\\^}. For example, <b>^#include</b> will only + match strings which \e begin with the characters '#include'. + (When the caret is the first character of a character set it + has a special meaning, see \link #sets-of-characters Sets of + Characters \endlink.) + + \row \i <b>$</b> + \i The dollar signifies the end of the string. For example + <b>\d\s*$</b> will match strings which end with a digit + optionally followed by whitespace. If you wish to match a + literal \c{$} you must escape it by writing + \c{\\$}. + + \row \i <b>\\b</b> + \i A word boundary. For example the regexp + <b>\\bOK\\b</b> means match immediately after a word + boundary (e.g. start of string or whitespace) the letter 'O' + then the letter 'K' immediately before another word boundary + (e.g. end of string or whitespace). But note that the + assertion does not actually match any whitespace so if we + write <b>(\\bOK\\b)</b> and we have a match it will only + contain 'OK' even if the string is "Its <u>OK</u> now". + + \row \i <b>\\B</b> + \i A non-word boundary. This assertion is true wherever + <b>\\b</b> is false. For example if we searched for + <b>\\Bon\\B</b> in "Left on" the match would fail (space + and end of string aren't non-word boundaries), but it would + match in "t<u>on</u>ne". + + \row \i <b>(?=\e E)</b> + \i Positive lookahead. This assertion is true if the + expression matches at this point in the regexp. For example, + <b>const(?=\\s+char)</b> matches 'const' whenever it is + followed by 'char', as in 'static <u>const</u> char *'. + (Compare with <b>const\\s+char</b>, which matches 'static + <u>const char</u> *'.) + + \row \i <b>(?!\e E)</b> + \i Negative lookahead. This assertion is true if the + expression does not match at this point in the regexp. For + example, <b>const(?!\\s+char)</b> matches 'const' \e except + when it is followed by 'char'. + \endtable + + \target wildcard-matching + \section1 Wildcard Matching (globbing) + + Most command shells such as \e bash or \e cmd.exe support "file + globbing", the ability to identify a group of files by using + wildcards. The setWildcard() function is used to switch between + regexp and wildcard mode. Wildcard matching is much simpler than + full regexps and has only four features: + + \table + \row \i <b>c</b> + \i Any character represents itself apart from those mentioned + below. Thus <b>c</b> matches the character \e c. + \row \i <b>?</b> + \i This matches any single character. It is the same as + <b>.</b> in full regexps. + \row \i <b>*</b> + \i This matches zero or more of any characters. It is the + same as <b>.*</b> in full regexps. + \row \i <b>[...]</b> + \i Sets of characters can be represented in square brackets, + similar to full regexps. Within the character class, like + outside, backslash has no special meaning. + \endtable + + For example if we are in wildcard mode and have strings which + contain filenames we could identify HTML files with <b>*.html</b>. + This will match zero or more characters followed by a dot followed + by 'h', 't', 'm' and 'l'. + + \target perl-users + \section1 Notes for Perl Users + + Most of the character class abbreviations supported by Perl are + supported by QRegExp, see \link + #characters-and-abbreviations-for-sets-of-characters characters + and abbreviations for sets of characters \endlink. + + In QRegExp, apart from within character classes, \c{^} always + signifies the start of the string, so carets must always be + escaped unless used for that purpose. In Perl the meaning of caret + varies automagically depending on where it occurs so escaping it + is rarely necessary. The same applies to \c{$} which in + QRegExp always signifies the end of the string. + + QRegExp's quantifiers are the same as Perl's greedy quantifiers. + Non-greedy matching cannot be applied to individual quantifiers, + but can be applied to all the quantifiers in the pattern. For + example, to match the Perl regexp <b>ro+?m</b> requires: + \code + QRegExp rx( "ro+m" ); + rx.setMinimal( TRUE ); + \endcode + + The equivalent of Perl's \c{/i} option is + setCaseSensitive(FALSE). + + Perl's \c{/g} option can be emulated using a \link + #cap_in_a_loop loop \endlink. + + In QRegExp <b>.</b> matches any character, therefore all QRegExp + regexps have the equivalent of Perl's \c{/s} option. QRegExp + does not have an equivalent to Perl's \c{/m} option, but this + can be emulated in various ways for example by splitting the input + into lines or by looping with a regexp that searches for newlines. + + Because QRegExp is string oriented there are no \A, \Z or \z + assertions. The \G assertion is not supported but can be emulated + in a loop. + + Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp + equivalents for $`, $' or $+. Perl's capturing variables, $1, $2, + ... correspond to cap(1) or capturedTexts()[1], cap(2) or + capturedTexts()[2], etc. + + To substitute a pattern use QString::replace(). + + Perl's extended \c{/x} syntax is not supported, nor are + regexp comments (?#comment) or directives, e.g. (?i). + + Both zero-width positive and zero-width negative lookahead + assertions (?=pattern) and (?!pattern) are supported with the same + syntax as Perl. Perl's lookbehind assertions, "independent" + subexpressions and conditional expressions are not supported. + + Non-capturing parentheses are also supported, with the same + (?:pattern) syntax. + + See QStringList::split() and QStringList::join() for equivalents + to Perl's split and join functions. + + Note: because C++ transforms \\'s they must be written \e twice in + code, e.g. <b>\\b</b> must be written <b>\\\\b</b>. + + \target code-examples + \section1 Code Examples + + \code + QRegExp rx( "^\\d\\d?$" ); // match integers 0 to 99 + rx.search( "123" ); // returns -1 (no match) + rx.search( "-6" ); // returns -1 (no match) + rx.search( "6" ); // returns 0 (matched as position 0) + \endcode + + The third string matches '<u>6</u>'. This is a simple validation + regexp for integers in the range 0 to 99. + + \code + QRegExp rx( "^\\S+$" ); // match strings without whitespace + rx.search( "Hello world" ); // returns -1 (no match) + rx.search( "This_is-OK" ); // returns 0 (matched at position 0) + \endcode + + The second string matches '<u>This_is-OK</u>'. We've used the + character set abbreviation '\S' (non-whitespace) and the anchors + to match strings which contain no whitespace. + + In the following example we match strings containing 'mail' or + 'letter' or 'correspondence' but only match whole words i.e. not + 'email' + + \code + QRegExp rx( "\\b(mail|letter|correspondence)\\b" ); + rx.search( "I sent you an email" ); // returns -1 (no match) + rx.search( "Please write the letter" ); // returns 17 + \endcode + + The second string matches "Please write the <u>letter</u>". The + word 'letter' is also captured (because of the parentheses). We + can see what text we've captured like this: + + \code + QString captured = rx.cap( 1 ); // captured == "letter" + \endcode + + This will capture the text from the first set of capturing + parentheses (counting capturing left parentheses from left to + right). The parentheses are counted from 1 since cap( 0 ) is the + whole matched regexp (equivalent to '&' in most regexp engines). + + \code + QRegExp rx( "&(?!amp;)" ); // match ampersands but not & + QString line1 = "This & that"; + line1.replace( rx, "&" ); + // line1 == "This & that" + QString line2 = "His & hers & theirs"; + line2.replace( rx, "&" ); + // line2 == "His & hers & theirs" + \endcode + + Here we've passed the QRegExp to QString's replace() function to + replace the matched text with new text. + + \code + QString str = "One Eric another Eirik, and an Ericsson." + " How many Eiriks, Eric?"; + QRegExp rx( "\\b(Eric|Eirik)\\b" ); // match Eric or Eirik + int pos = 0; // where we are in the string + int count = 0; // how many Eric and Eirik's we've counted + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos >= 0 ) { + pos++; // move along in str + count++; // count our Eric or Eirik + } + } + \endcode + + We've used the search() function to repeatedly match the regexp in + the string. Note that instead of moving forward by one character + at a time \c pos++ we could have written \c {pos += + rx.matchedLength()} to skip over the already matched string. The + count will equal 3, matching 'One <u>Eric</u> another + <u>Eirik</u>, and an Ericsson. How many Eiriks, <u>Eric</u>?'; it + doesn't match 'Ericsson' or 'Eiriks' because they are not bounded + by non-word boundaries. + + One common use of regexps is to split lines of delimited data into + their component fields. + + \code + str = "Trolltech AS\twww.trolltech.com\tNorway"; + QString company, web, country; + rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" ); + if ( rx.search( str ) != -1 ) { + company = rx.cap( 1 ); + web = rx.cap( 2 ); + country = rx.cap( 3 ); + } + \endcode + + In this example our input lines have the format company name, web + address and country. Unfortunately the regexp is rather long and + not very versatile -- the code will break if we add any more + fields. A simpler and better solution is to look for the + separator, '\t' in this case, and take the surrounding text. The + QStringList split() function can take a separator string or regexp + as an argument and split a string accordingly. + + \code + QStringList field = QStringList::split( "\t", str ); + \endcode + + Here field[0] is the company, field[1] the web address and so on. + + To imitate the matching of a shell we can use wildcard mode. + + \code + QRegExp rx( "*.html" ); // invalid regexp: * doesn't quantify anything + rx.setWildcard( TRUE ); // now it's a valid wildcard regexp + rx.search( "index.html" ); // returns 0 (matched at position 0) + rx.search( "default.htm" ); // returns -1 (no match) + rx.search( "readme.txt" ); // returns -1 (no match) + \endcode + + Wildcard matching can be convenient because of its simplicity, but + any wildcard regexp can be defined using full regexps, e.g. + <b>.*\.html$</b>. Notice that we can't match both \c .html and \c + .htm files with a wildcard unless we use <b>*.htm*</b> which will + also match 'test.html.bak'. A full regexp gives us the precision + we need, <b>.*\\.html?$</b>. + + QRegExp can match case insensitively using setCaseSensitive(), and + can use non-greedy matching, see setMinimal(). By default QRegExp + uses full regexps but this can be changed with setWildcard(). + Searching can be forward with search() or backward with + searchRev(). Captured text can be accessed using capturedTexts() + which returns a string list of all captured strings, or using + cap() which returns the captured string for the given index. The + pos() function takes a match index and returns the position in the + string where the match was made (or -1 if there was no match). + + \sa QRegExpValidator QString QStringList + + \target member-function-documentation +*/ + +const int NumBadChars = 64; +#define BadChar( ch ) ( (ch).unicode() % NumBadChars ) + +const int NoOccurrence = INT_MAX; +const int EmptyCapture = INT_MAX; +const int InftyLen = INT_MAX; +const int InftyRep = 1025; +const int EOS = -1; + +/* + Merges two QMemArrays of ints and puts the result into the first one. +*/ +static void mergeInto( QMemArray<int> *a, const QMemArray<int>& b ) +{ + int asize = a->size(); + int bsize = b.size(); + if ( asize == 0 ) { + *a = b.copy(); +#ifndef QT_NO_REGEXP_OPTIM + } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) { + a->resize( asize + 1 ); + (*a)[asize] = b[0]; +#endif + } else if ( bsize >= 1 ) { + int csize = asize + bsize; + QMemArray<int> c( csize ); + int i = 0, j = 0, k = 0; + while ( i < asize ) { + if ( j < bsize ) { + if ( (*a)[i] == b[j] ) { + i++; + csize--; + } else if ( (*a)[i] < b[j] ) { + c[k++] = (*a)[i++]; + } else { + c[k++] = b[j++]; + } + } else { + memcpy( c.data() + k, (*a).data() + i, + (asize - i) * sizeof(int) ); + break; + } + } + c.resize( csize ); + if ( j < bsize ) + memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) ); + *a = c; + } +} + +/* + Merges two disjoint QMaps of (int, int) pairs and puts the result into the + first one. +*/ +static void mergeInto( QMap<int, int> *a, const QMap<int, int>& b ) +{ + QMap<int, int>::ConstIterator it; + for ( it = b.begin(); it != b.end(); ++it ) + a->insert( it.key(), *it ); +} + +/* + Returns the value associated to key k in QMap m of (int, int) pairs, or 0 if + no such value is explicitly present. +*/ +static int at( const QMap<int, int>& m, int k ) +{ + QMap<int, int>::ConstIterator it = m.find( k ); + if ( it == m.end() ) + return 0; + else + return *it; +} + +#ifndef QT_NO_REGEXP_WILDCARD +/* + Translates a wildcard pattern to an equivalent regular expression pattern + (e.g., *.cpp to .*\.cpp). +*/ +static QString wc2rx( const QString& wc_str ) +{ + int wclen = wc_str.length(); + QString rx = QString::fromLatin1( "" ); + int i = 0; + const QChar *wc = wc_str.unicode(); + while ( i < wclen ) { + QChar c = wc[i++]; + switch ( c.unicode() ) { + case '*': + rx += QString::fromLatin1( ".*" ); + break; + case '?': + rx += QChar( '.' ); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '\\': + case '^': + case '{': + case '|': + case '}': + rx += QChar( '\\' ); + rx += c; + break; + case '[': + rx += c; + if ( wc[i] == QChar('^') ) + rx += wc[i++]; + if ( i < wclen ) { + if ( rx[i] == ']' ) + rx += wc[i++]; + while ( i < wclen && wc[i] != QChar(']') ) { + if ( wc[i] == '\\' ) + rx += QChar( '\\' ); + rx += wc[i++]; + } + } + break; + default: + rx += c; + } + } + return rx; +} +#endif + +/* + The class QRegExpEngine encapsulates a modified nondeterministic + finite automaton (NFA). +*/ +class QRegExpEngine : public QShared +{ +public: +#ifndef QT_NO_REGEXP_CCLASS + /* + The class CharClass represents a set of characters, such as can + be found in regular expressions (e.g., [a-z] denotes the set + {a, b, ..., z}). + */ + class CharClass + { + public: + CharClass(); + CharClass( const CharClass& cc ) { operator=( cc ); } + + CharClass& operator=( const CharClass& cc ); + + void clear(); + bool negative() const { return n; } + void setNegative( bool negative ); + void addCategories( int cats ); + void addRange( ushort from, ushort to ); + void addSingleton( ushort ch ) { addRange( ch, ch ); } + + bool in( QChar ch ) const; +#ifndef QT_NO_REGEXP_OPTIM + const QMemArray<int>& firstOccurrence() const { return occ1; } +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + /* + The struct Range represents a range of characters (e.g., + [0-9] denotes range 48 to 57). + */ + struct Range + { + ushort from; // 48 + ushort to; // 57 + }; + + int c; // character classes + QMemArray<Range> r; // character ranges + bool n; // negative? +#ifndef QT_NO_REGEXP_OPTIM + QMemArray<int> occ1; // first-occurrence array +#endif + }; +#else + struct CharClass + { + int dummy; + +#ifndef QT_NO_REGEXP_OPTIM + CharClass() { occ1.fill( 0, NumBadChars ); } + + const QMemArray<int>& firstOccurrence() const { return occ1; } + QMemArray<int> occ1; +#endif + }; +#endif + + QRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); } + QRegExpEngine( const QString& rx, bool caseSensitive ); +#ifndef QT_NO_REGEXP_OPTIM + ~QRegExpEngine(); +#endif + + bool isValid() const { return valid; } + const QString& errorString() const { return yyError; } + bool caseSensitive() const { return cs; } + int numCaptures() const { return officialncap; } + QMemArray<int> match( const QString& str, int pos, bool minimal, + bool oneTest, int caretIndex ); + int matchedLength() const { return mmMatchedLen; } + + int createState( QChar ch ); + int createState( const CharClass& cc ); +#ifndef QT_NO_REGEXP_BACKREF + int createState( int bref ); +#endif + + void addCatTransitions( const QMemArray<int>& from, + const QMemArray<int>& to ); +#ifndef QT_NO_REGEXP_CAPTURE + void addPlusTransitions( const QMemArray<int>& from, + const QMemArray<int>& to, int atom ); +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + int anchorAlternation( int a, int b ); + int anchorConcatenation( int a, int b ); +#else + int anchorAlternation( int a, int b ) { return a & b; } + int anchorConcatenation( int a, int b ) { return a | b; } +#endif + void addAnchors( int from, int to, int a ); + +#ifndef QT_NO_REGEXP_OPTIM + void setupGoodStringHeuristic( int earlyStart, int lateStart, + const QString& str ); + void setupBadCharHeuristic( int minLen, const QMemArray<int>& firstOcc ); + void heuristicallyChooseHeuristic(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + +private: + enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; + + /* + The struct State represents one state in a modified NFA. The + input characters matched are stored in the state instead of on + the transitions, something possible for an automaton + constructed from a regular expression. + */ + struct State + { +#ifndef QT_NO_REGEXP_CAPTURE + int atom; // which atom does this state belong to? +#endif + int match; // what does it match? (see CharClassBit and BackRefBit) + QMemArray<int> outs; // out-transitions + QMap<int, int> *reenter; // atoms reentered when transiting out + QMap<int, int> *anchors; // anchors met when transiting out + +#ifndef QT_NO_REGEXP_CAPTURE + State( int a, int m ) + : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { } +#else + State( int m ) + : match( m ), reenter( 0 ), anchors( 0 ) { } +#endif + ~State() { delete reenter; delete anchors; } + }; + +#ifndef QT_NO_REGEXP_LOOKAHEAD + /* + The struct Lookahead represents a lookahead a la Perl (e.g., (?=foo) and + (?!bar)). + */ + struct Lookahead + { + QRegExpEngine *eng; // NFA representing the embedded regular expression + bool neg; // negative lookahead? + + Lookahead( QRegExpEngine *eng0, bool neg0 ) + : eng( eng0 ), neg( neg0 ) { } + ~Lookahead() { delete eng; } + }; +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + /* + The struct Atom represents one node in the hierarchy of regular + expression atoms. + */ + struct Atom + { + int parent; // index of parent in array of atoms + int capture; // index of capture, from 1 to ncap + }; +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + /* + The struct AnchorAlternation represents a pair of anchors with + OR semantics. + */ + struct AnchorAlternation + { + int a; // this anchor... + int b; // ...or this one + }; +#endif + + enum { InitialState = 0, FinalState = 1 }; + void setup( bool caseSensitive ); + int setupState( int match ); + + /* + Let's hope that 13 lookaheads and 14 back-references are + enough. + */ + enum { MaxLookaheads = 13, MaxBackRefs = 14 }; + enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, + Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008, + Anchor_FirstLookahead = 0x00000010, + Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, + Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, + Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs, + + Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^ + ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) }; +#ifndef QT_NO_REGEXP_CAPTURE + int startAtom( bool capture ); + void finishAtom( int atom ) { cf = f[atom].parent; } +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD + int addLookahead( QRegExpEngine *eng, bool negative ); +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + bool isBetterCapture( const int *begin1, const int *end1, const int *begin2, + const int *end2 ); +#endif + bool testAnchor( int i, int a, const int *capBegin ); + +#ifndef QT_NO_REGEXP_OPTIM + bool goodStringMatch(); + bool badCharMatch(); +#else + bool bruteMatch(); +#endif + bool matchHere(); + + QPtrVector<State> s; // array of states + int ns; // number of states +#ifndef QT_NO_REGEXP_CAPTURE + QMemArray<Atom> f; // atom hierarchy + int nf; // number of atoms + int cf; // current atom +#endif + int officialncap; // number of captures, seen from the outside + int ncap; // number of captures, seen from the inside +#ifndef QT_NO_REGEXP_CCLASS + QPtrVector<CharClass> cl; // array of character classes +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + QPtrVector<Lookahead> ahead; // array of lookaheads +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + QMemArray<AnchorAlternation> aa; // array of (a, b) pairs of anchors +#endif +#ifndef QT_NO_REGEXP_OPTIM + bool caretAnchored; // does the regexp start with ^? +#endif + bool valid; // is the regular expression valid? + bool cs; // case sensitive? +#ifndef QT_NO_REGEXP_BACKREF + int nbrefs; // number of back-references +#endif + +#ifndef QT_NO_REGEXP_OPTIM + bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch + + int goodEarlyStart; // the index where goodStr can first occur in a match + int goodLateStart; // the index where goodStr can last occur in a match + QString goodStr; // the string that any match has to contain + + int minl; // the minimum length of a match + QMemArray<int> occ1; // first-occurrence array +#endif + + /* + The class Box is an abstraction for a regular expression + fragment. It can also be seen as one node in the syntax tree of + a regular expression with synthetized attributes. + + It's interface is ugly for performance reasons. + */ + class Box + { + public: + Box( QRegExpEngine *engine ); + Box( const Box& b ) { operator=( b ); } + + Box& operator=( const Box& b ); + + void clear() { operator=(Box(eng)); } + void set( QChar ch ); + void set( const CharClass& cc ); +#ifndef QT_NO_REGEXP_BACKREF + void set( int bref ); +#endif + + void cat( const Box& b ); + void orx( const Box& b ); + void plus( int atom ); + void opt(); + void catAnchor( int a ); +#ifndef QT_NO_REGEXP_OPTIM + void setupHeuristics(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + void addAnchorsToEngine( const Box& to ) const; + + QRegExpEngine *eng; // the automaton under construction + QMemArray<int> ls; // the left states (firstpos) + QMemArray<int> rs; // the right states (lastpos) + QMap<int, int> lanchors; // the left anchors + QMap<int, int> ranchors; // the right anchors + int skipanchors; // the anchors to match if the box is skipped + +#ifndef QT_NO_REGEXP_OPTIM + int earlyStart; // the index where str can first occur + int lateStart; // the index where str can last occur + QString str; // a string that has to occur in any match + QString leftStr; // a string occurring at the left of this box + QString rightStr; // a string occurring at the right of this box + int maxl; // the maximum length of this box (possibly InftyLen) +#endif + + int minl; // the minimum length of this box +#ifndef QT_NO_REGEXP_OPTIM + QMemArray<int> occ1; // first-occurrence array +#endif + }; + friend class Box; + + /* + This is the lexical analyzer for regular expressions. + */ + enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, + Tok_PosLookahead, Tok_NegLookahead, Tok_RightParen, Tok_CharClass, + Tok_Caret, Tok_Quantifier, Tok_Bar, Tok_Word, Tok_NonWord, + Tok_Char = 0x10000, Tok_BackRef = 0x20000 }; + int getChar(); + int getEscape(); +#ifndef QT_NO_REGEXP_INTERVAL + int getRep( int def ); +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + void skipChars( int n ); +#endif + void error( const char *msg ); + void startTokenizer( const QChar *rx, int len ); + int getToken(); + + const QChar *yyIn; // a pointer to the input regular expression pattern + int yyPos0; // the position of yyTok in the input pattern + int yyPos; // the position of the next character to read + int yyLen; // the length of yyIn + int yyCh; // the last character read + CharClass *yyCharClass; // attribute for Tok_CharClass tokens + int yyMinRep; // attribute for Tok_Quantifier + int yyMaxRep; // ditto + QString yyError; // syntax error or overflow during parsing? + + /* + This is the syntactic analyzer for regular expressions. + */ + int parse( const QChar *rx, int len ); + void parseAtom( Box *box ); + void parseFactor( Box *box ); + void parseTerm( Box *box ); + void parseExpression( Box *box ); + + int yyTok; // the last token read + bool yyMayCapture; // set this to FALSE to disable capturing + + /* + This is the engine state during matching. + */ + const QString *mmStr; // a pointer to the input QString + const QChar *mmIn; // a pointer to the input string data + int mmPos; // the current position in the string + int mmCaretPos; + int mmLen; // the length of the input string + bool mmMinimal; // minimal matching? + QMemArray<int> mmCaptured; // an array of pairs (start, len) + QMemArray<int> mmCapturedNoMatch; // an array of pairs (-1, -1) + QMemArray<int> mmBigArray; // big QMemArray<int> array + int *mmInNextStack; // is state is mmNextStack? + int *mmCurStack; // stack of current states + int *mmNextStack; // stack of next states + int *mmCurCapBegin; // start of current states' captures + int *mmNextCapBegin; // start of next states' captures + int *mmCurCapEnd; // end of current states' captures + int *mmNextCapEnd; // end of next states' captures + int *mmTempCapBegin; // start of temporary captures + int *mmTempCapEnd; // end of temporary captures + int *mmCapBegin; // start of captures for a next state + int *mmCapEnd; // end of captures for a next state + int *mmSlideTab; // bump-along slide table for bad-character heuristic + int mmSlideTabSize; // size of slide table +#ifndef QT_NO_REGEXP_BACKREF + QIntDict<int> mmSleeping; // dictionary of back-reference sleepers +#endif + int mmMatchLen; // length of match + int mmMatchedLen; // length of partial match +}; + +QRegExpEngine::QRegExpEngine( const QString& rx, bool caseSensitive ) +#ifndef QT_NO_REGEXP_BACKREF + : mmSleeping( 101 ) +#endif +{ + setup( caseSensitive ); + valid = ( parse(rx.unicode(), rx.length()) == (int) rx.length() ); + if ( !valid ) + error( RXERR_LEFTDELIM ); +} + +#ifndef QT_NO_REGEXP_OPTIM +QRegExpEngine::~QRegExpEngine() +{ +} +#endif + +/* + Tries to match in str and returns an array of (begin, length) pairs + for captured text. If there is no match, all pairs are (-1, -1). +*/ +QMemArray<int> QRegExpEngine::match( const QString& str, int pos, bool minimal, + bool oneTest, int caretIndex ) +{ + mmStr = &str; + mmIn = str.unicode(); + if ( mmIn == 0 ) + mmIn = &QChar::null; + mmPos = pos; + mmCaretPos = caretIndex; + mmLen = str.length(); + mmMinimal = minimal; + mmMatchLen = 0; + mmMatchedLen = 0; + + bool matched = FALSE; + if ( valid && mmPos >= 0 && mmPos <= mmLen ) { +#ifndef QT_NO_REGEXP_OPTIM + if ( oneTest ) { + matched = matchHere(); + } else { + if ( mmPos <= mmLen - minl ) { + if ( caretAnchored ) { + matched = matchHere(); + } else if ( useGoodStringHeuristic ) { + matched = goodStringMatch(); + } else { + matched = badCharMatch(); + } + } + } +#else + matched = oneTest ? matchHere() : bruteMatch(); +#endif + } + + if ( matched ) { + mmCaptured.detach(); + mmCaptured[0] = mmPos; + mmCaptured[1] = mmMatchLen; + for ( int j = 0; j < officialncap; j++ ) { + int len = mmCapEnd[j] - mmCapBegin[j]; + mmCaptured[2 + 2 * j] = len > 0 ? mmPos + mmCapBegin[j] : 0; + mmCaptured[2 + 2 * j + 1] = len; + } + return mmCaptured; + } else { + return mmCapturedNoMatch; + } +} + +/* + The three following functions add one state to the automaton and + return the number of the state. +*/ + +int QRegExpEngine::createState( QChar ch ) +{ + return setupState( ch.unicode() ); +} + +int QRegExpEngine::createState( const CharClass& cc ) +{ +#ifndef QT_NO_REGEXP_CCLASS + int n = cl.size(); + cl.resize( n + 1 ); + cl.insert( n, new CharClass(cc) ); + return setupState( CharClassBit | n ); +#else + Q_UNUSED( cc ); + return setupState( CharClassBit ); +#endif +} + +#ifndef QT_NO_REGEXP_BACKREF +int QRegExpEngine::createState( int bref ) +{ + if ( bref > nbrefs ) { + nbrefs = bref; + if ( nbrefs > MaxBackRefs ) { + error( RXERR_LIMIT ); + return 0; + } + } + return setupState( BackRefBit | bref ); +} +#endif + +/* + The two following functions add a transition between all pairs of + states (i, j) where i is fond in from, and j is found in to. + + Cat-transitions are distinguished from plus-transitions for + capturing. +*/ + +void QRegExpEngine::addCatTransitions( const QMemArray<int>& from, + const QMemArray<int>& to ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + mergeInto( &st->outs, to ); + } +} + +#ifndef QT_NO_REGEXP_CAPTURE +void QRegExpEngine::addPlusTransitions( const QMemArray<int>& from, + const QMemArray<int>& to, int atom ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + QMemArray<int> oldOuts = st->outs.copy(); + mergeInto( &st->outs, to ); + if ( f[atom].capture >= 0 ) { + if ( st->reenter == 0 ) + st->reenter = new QMap<int, int>; + for ( int j = 0; j < (int) to.size(); j++ ) { + if ( !st->reenter->contains(to[j]) && + oldOuts.bsearch(to[j]) < 0 ) + st->reenter->insert( to[j], atom ); + } + } + } +} +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT +/* + Returns an anchor that means a OR b. +*/ +int QRegExpEngine::anchorAlternation( int a, int b ) +{ + if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 ) + return a & b; + + int n = aa.size(); +#ifndef QT_NO_REGEXP_OPTIM + if ( n > 0 && aa[n - 1].a == a && aa[n - 1].b == b ) + return Anchor_Alternation | ( n - 1 ); +#endif + + aa.resize( n + 1 ); + aa[n].a = a; + aa[n].b = b; + return Anchor_Alternation | n; +} + +/* + Returns an anchor that means a AND b. +*/ +int QRegExpEngine::anchorConcatenation( int a, int b ) +{ + if ( ((a | b) & Anchor_Alternation) == 0 ) + return a | b; + if ( (b & Anchor_Alternation) != 0 ) + qSwap( a, b ); + + int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b ); + int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b ); + return anchorAlternation( aprime, bprime ); +} +#endif + +/* + Adds anchor a on a transition caracterised by its from state and + its to state. +*/ +void QRegExpEngine::addAnchors( int from, int to, int a ) +{ + State *st = s[from]; + if ( st->anchors == 0 ) + st->anchors = new QMap<int, int>; + if ( st->anchors->contains(to) ) + a = anchorAlternation( (*st->anchors)[to], a ); + st->anchors->insert( to, a ); +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + The two following functions provide the engine with the information + needed by its matching heuristics. +*/ + +void QRegExpEngine::setupGoodStringHeuristic( int earlyStart, int lateStart, + const QString& str ) +{ + goodEarlyStart = earlyStart; + goodLateStart = lateStart; + goodStr = cs ? str : str.lower(); +} + +void QRegExpEngine::setupBadCharHeuristic( int minLen, + const QMemArray<int>& firstOcc ) +{ + minl = minLen; + if ( cs ) { + occ1 = firstOcc; + } else { + occ1.fill( 0, NumBadChars ); + } +} + +/* + This function chooses between the good-string and the bad-character + heuristics. It computes two scores and chooses the heuristic with + the highest score. + + Here are some common-sense constraints on the scores that should be + respected if the formulas are ever modified: (1) If goodStr is + empty, the good-string heuristic scores 0. (2) If the search is + case insensitive, the good-string heuristic should be used, unless + it scores 0. (Case insensitivity turns all entries of occ1 to 0.) + (3) If (goodLateStart - goodEarlyStart) is big, the good-string + heuristic should score less. +*/ +void QRegExpEngine::heuristicallyChooseHeuristic() +{ + int i; + + if ( minl == 0 ) + return; + + /* + Magic formula: The good string has to constitute a good + proportion of the minimum-length string, and appear at a + more-or-less known index. + */ + int goodStringScore = ( 64 * goodStr.length() / minl ) - + ( goodLateStart - goodEarlyStart ); + + /* + Less magic formula: We pick a couple of characters at random, + and check whether they are good or bad. + */ + int badCharScore = 0; + int step = QMAX( 1, NumBadChars / 32 ); + for ( i = 1; i < NumBadChars; i += step ) { + if ( occ1[i] == NoOccurrence ) + badCharScore += minl; + else + badCharScore += occ1[i]; + } + badCharScore /= minl; + + useGoodStringHeuristic = ( goodStringScore > badCharScore ); +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::dump() const +{ + int i, j; + qDebug( "Case %ssensitive engine", cs ? "" : "in" ); + qDebug( " States" ); + for ( i = 0; i < ns; i++ ) { + qDebug( " %d%s", i, + i == InitialState ? " (initial)" : + i == FinalState ? " (final)" : "" ); +#ifndef QT_NO_REGEXP_CAPTURE + qDebug( " in atom %d", s[i]->atom ); +#endif + int m = s[i]->match; + if ( (m & CharClassBit) != 0 ) { + qDebug( " match character class %d", m ^ CharClassBit ); +#ifndef QT_NO_REGEXP_CCLASS + cl[m ^ CharClassBit]->dump(); +#else + qDebug( " negative character class" ); +#endif + } else if ( (m & BackRefBit) != 0 ) { + qDebug( " match back-reference %d", m ^ BackRefBit ); + } else if ( m >= 0x20 && m <= 0x7e ) { + qDebug( " match 0x%.4x (%c)", m, m ); + } else { + qDebug( " match 0x%.4x", m ); + } + for ( j = 0; j < (int) s[i]->outs.size(); j++ ) { + int next = s[i]->outs[j]; + qDebug( " -> %d", next ); + if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) ) + qDebug( " [reenter %d]", (*s[i]->reenter)[next] ); + if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 ) + qDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] ); + } + } +#ifndef QT_NO_REGEXP_CAPTURE + if ( nf > 0 ) { + qDebug( " Atom Parent Capture" ); + for ( i = 0; i < nf; i++ ) + qDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture ); + } +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + for ( i = 0; i < (int) aa.size(); i++ ) + qDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, + aa[i].b ); +#endif +} +#endif + +void QRegExpEngine::setup( bool caseSensitive ) +{ + s.setAutoDelete( TRUE ); + s.resize( 32 ); + ns = 0; +#ifndef QT_NO_REGEXP_CAPTURE + f.resize( 32 ); + nf = 0; + cf = -1; +#endif + officialncap = 0; + ncap = 0; +#ifndef QT_NO_REGEXP_CCLASS + cl.setAutoDelete( TRUE ); +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + ahead.setAutoDelete( TRUE ); +#endif +#ifndef QT_NO_REGEXP_OPTIM + caretAnchored = TRUE; +#endif + valid = FALSE; + cs = caseSensitive; +#ifndef QT_NO_REGEXP_BACKREF + nbrefs = 0; +#endif +#ifndef QT_NO_REGEXP_OPTIM + useGoodStringHeuristic = FALSE; + minl = 0; + occ1.fill( 0, NumBadChars ); +#endif + mmCapturedNoMatch.fill( -1, 2 ); +} + +int QRegExpEngine::setupState( int match ) +{ + if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() ) + s.resize( (ns + 1) << 1 ); +#ifndef QT_NO_REGEXP_CAPTURE + s.insert( ns, new State(cf, match) ); +#else + s.insert( ns, new State(match) ); +#endif + return ns++; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/* + Functions startAtom() and finishAtom() should be called to delimit + atoms. When a state is created, it is assigned to the current atom. + The information is later used for capturing. +*/ +int QRegExpEngine::startAtom( bool capture ) +{ + if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() ) + f.resize( (nf + 1) << 1 ); + f[nf].parent = cf; + cf = nf++; + f[cf].capture = capture ? ncap++ : -1; + return cf; +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +/* + Creates a lookahead anchor. +*/ +int QRegExpEngine::addLookahead( QRegExpEngine *eng, bool negative ) +{ + int n = ahead.size(); + if ( n == MaxLookaheads ) { + error( RXERR_LIMIT ); + return 0; + } + ahead.resize( n + 1 ); + ahead.insert( n, new Lookahead(eng, negative) ); + return Anchor_FirstLookahead << n; +} +#endif + +#ifndef QT_NO_REGEXP_CAPTURE +/* + We want the longest leftmost captures. +*/ +bool QRegExpEngine::isBetterCapture( const int *begin1, const int *end1, + const int *begin2, const int *end2 ) +{ + for ( int i = 0; i < ncap; i++ ) { + int delta = begin2[i] - begin1[i]; // it has to start early... + if ( delta == 0 ) + delta = end1[i] - end2[i]; // ...and end late (like a party) + + if ( delta != 0 ) + return delta > 0; + } + return FALSE; +} +#endif + +/* + Returns TRUE if anchor a matches at position mmPos + i in the input + string, otherwise FALSE. +*/ +bool QRegExpEngine::testAnchor( int i, int a, const int *capBegin ) +{ + int j; + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + if ( (a & Anchor_Alternation) != 0 ) { + return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) || + testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin ); + } +#endif + + if ( (a & Anchor_Caret) != 0 ) { + if ( mmPos + i != mmCaretPos ) + return FALSE; + } + if ( (a & Anchor_Dollar) != 0 ) { + if ( mmPos + i != mmLen ) + return FALSE; + } +#ifndef QT_NO_REGEXP_ESCAPE + if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) { + bool before = FALSE; + bool after = FALSE; + if ( mmPos + i != 0 ) + before = mmIn[mmPos + i - 1].isLetterOrNumber(); + if ( mmPos + i != mmLen ) + after = mmIn[mmPos + i].isLetterOrNumber(); + if ( (a & Anchor_Word) != 0 && (before == after) ) + return FALSE; + if ( (a & Anchor_NonWord) != 0 && (before != after) ) + return FALSE; + } +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + bool catchx = TRUE; + + if ( (a & Anchor_LookaheadMask) != 0 ) { + QConstString cstr = QConstString( (QChar *) mmIn + mmPos + i, + mmLen - mmPos - i ); + for ( j = 0; j < (int) ahead.size(); j++ ) { + if ( (a & (Anchor_FirstLookahead << j)) != 0 ) { + catchx = ahead[j]->eng->match( cstr.string(), 0, TRUE, TRUE, + mmCaretPos - mmPos - i )[0] == 0; + if ( catchx == ahead[j]->neg ) + return FALSE; + } + } + } +#endif +#ifndef QT_NO_REGEXP_CAPTURE +#ifndef QT_NO_REGEXP_BACKREF + for ( j = 0; j < nbrefs; j++ ) { + if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) { + if ( capBegin[j] != EmptyCapture ) + return FALSE; + } + } +#endif +#endif + return TRUE; +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + The three following functions are what Jeffrey Friedl would call + transmissions (or bump-alongs). Using one or the other should make + no difference except in performance. +*/ + +bool QRegExpEngine::goodStringMatch() +{ + int k = mmPos + goodEarlyStart; + + while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) { + int from = k - goodLateStart; + int to = k - goodEarlyStart; + if ( from > mmPos ) + mmPos = from; + + while ( mmPos <= to ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + k++; + } + return FALSE; +} + +bool QRegExpEngine::badCharMatch() +{ + int slideHead = 0; + int slideNext = 0; + int i; + int lastPos = mmLen - minl; + memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) ); + + /* + Set up the slide table, used for the bad-character heuristic, + using the table of first occurrence of each character. + */ + for ( i = 0; i < minl; i++ ) { + int sk = occ1[BadChar(mmIn[mmPos + i])]; + if ( sk == NoOccurrence ) + sk = i + 1; + if ( sk > 0 ) { + int k = i + 1 - sk; + if ( k < 0 ) { + sk = i + 1; + k = 0; + } + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + } + + if ( mmPos > lastPos ) + return FALSE; + + for ( ;; ) { + if ( ++slideNext >= mmSlideTabSize ) + slideNext = 0; + if ( mmSlideTab[slideHead] > 0 ) { + if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] ) + mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1; + mmSlideTab[slideHead] = 0; + } else { + if ( matchHere() ) + return TRUE; + } + + if ( mmPos == lastPos ) + break; + + /* + Update the slide table. This code has much in common with + the initialization code. + */ + int sk = occ1[BadChar(mmIn[mmPos + minl])]; + if ( sk == NoOccurrence ) { + mmSlideTab[slideNext] = minl; + } else if ( sk > 0 ) { + int k = slideNext + minl - sk; + if ( k >= mmSlideTabSize ) + k -= mmSlideTabSize; + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + slideHead = slideNext; + mmPos++; + } + return FALSE; +} +#else +bool QRegExpEngine::bruteMatch() +{ + while ( mmPos <= mmLen ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + return FALSE; +} +#endif + +/* + Here's the core of the engine. It tries to do a match here and now. +*/ +bool QRegExpEngine::matchHere() +{ + int ncur = 1, nnext = 0; + int i = 0, j, k, m; + bool stop = FALSE; + + mmMatchLen = -1; + mmMatchedLen = -1; + mmCurStack[0] = InitialState; + +#ifndef QT_NO_REGEXP_CAPTURE + if ( ncap > 0 ) { + for ( j = 0; j < ncap; j++ ) { + mmCurCapBegin[j] = EmptyCapture; + mmCurCapEnd[j] = EmptyCapture; + } + } +#endif + +#ifndef QT_NO_REGEXP_BACKREF + int *zzZ = 0; + + while ( (ncur > 0 || !mmSleeping.isEmpty()) && i <= mmLen - mmPos && + !stop ) +#else + while ( ncur > 0 && i <= mmLen - mmPos && !stop ) +#endif + { + int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0; + for ( j = 0; j < ncur; j++ ) { + int cur = mmCurStack[j]; + State *scur = s[cur]; + QMemArray<int>& outs = scur->outs; + for ( k = 0; k < (int) outs.size(); k++ ) { + int next = outs[k]; + State *snext = s[next]; + bool in = TRUE; +#ifndef QT_NO_REGEXP_BACKREF + int needSomeSleep = 0; +#endif + + /* + First, check if the anchors are anchored properly. + */ + if ( scur->anchors != 0 ) { + int a = at( *scur->anchors, next ); + if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) ) + in = FALSE; + } + /* + If indeed they are, check if the input character is + correct for this transition. + */ + if ( in ) { + m = snext->match; + if ( (m & (CharClassBit | BackRefBit)) == 0 ) { + if ( cs ) + in = ( m == ch ); + else + in = ( QChar(m).lower() == QChar(ch).lower() ); + } else if ( next == FinalState ) { + mmMatchLen = i; + stop = mmMinimal; + in = TRUE; + } else if ( (m & CharClassBit) != 0 ) { +#ifndef QT_NO_REGEXP_CCLASS + const CharClass *cc = cl[m ^ CharClassBit]; + if ( cs ) + in = cc->in( ch ); + else if ( cc->negative() ) + in = cc->in( QChar(ch).lower() ) && + cc->in( QChar(ch).upper() ); + else + in = cc->in( QChar(ch).lower() ) || + cc->in( QChar(ch).upper() ); +#endif +#ifndef QT_NO_REGEXP_BACKREF + } else { /* ( (m & BackRefBit) != 0 ) */ + int bref = m ^ BackRefBit; + int ell = j * ncap + ( bref - 1 ); + + in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture; + if ( in ) { + if ( cs ) + in = ( mmIn[mmPos + mmCurCapBegin[ell]] + == QChar(ch) ); + else + in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower() + == QChar(ch).lower() ); + } + + if ( in ) { + int delta; + if ( mmCurCapEnd[ell] == EmptyCapture ) + delta = i - mmCurCapBegin[ell]; + else + delta = mmCurCapEnd[ell] - mmCurCapBegin[ell]; + + in = ( delta <= mmLen - (mmPos + i) ); + if ( in && delta > 1 ) { + int n = 1; + if ( cs ) { + while ( n < delta ) { + if ( mmIn[mmPos + + mmCurCapBegin[ell] + n] != + mmIn[mmPos + i + n] ) + break; + n++; + } + } else { + while ( n < delta ) { + QChar a = mmIn[mmPos + + mmCurCapBegin[ell] + n]; + QChar b = mmIn[mmPos + i + n]; + if ( a.lower() != b.lower() ) + break; + n++; + } + } + in = ( n == delta ); + if ( in ) + needSomeSleep = delta - 1; + } + } +#endif + } + } + + /* + We must now update our data structures. + */ + if ( in ) { +#ifndef QT_NO_REGEXP_CAPTURE + int *capBegin, *capEnd; +#endif + /* + If the next state was not encountered yet, all + is fine. + */ + if ( (m = mmInNextStack[next]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; +#ifndef QT_NO_REGEXP_CAPTURE + capBegin = mmNextCapBegin + m * ncap; + capEnd = mmNextCapEnd + m * ncap; + + /* + Otherwise, we'll first maintain captures in + temporary arrays, and decide at the end whether + it's best to keep the previous capture zones or + the new ones. + */ + } else { + capBegin = mmTempCapBegin; + capEnd = mmTempCapEnd; +#endif + } + +#ifndef QT_NO_REGEXP_CAPTURE + /* + Updating the capture zones is much of a task. + */ + if ( ncap > 0 ) { + memcpy( capBegin, mmCurCapBegin + j * ncap, + ncap * sizeof(int) ); + memcpy( capEnd, mmCurCapEnd + j * ncap, + ncap * sizeof(int) ); + int c = scur->atom, n = snext->atom; + int p = -1, q = -1; + int cap; + + /* + Lemma 1. For any x in the range [0..nf), we + have f[x].parent < x. + + Proof. By looking at startAtom(), it is + clear that cf < nf holds all the time, and + thus that f[nf].parent < nf. + */ + + /* + If we are reentering an atom, we empty all + capture zones inside it. + */ + if ( scur->reenter != 0 && + (q = at(*scur->reenter, next)) != 0 ) { + QBitArray b; + b.fill( FALSE, nf ); + b.setBit( q, TRUE ); + for ( int ell = q + 1; ell < nf; ell++ ) { + if ( b.testBit(f[ell].parent) ) { + b.setBit( ell, TRUE ); + cap = f[ell].capture; + if ( cap >= 0 ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } + } + } + p = f[q].parent; + + /* + Otherwise, close the capture zones we are + leaving. We are leaving f[c].capture, + f[f[c].parent].capture, + f[f[f[c].parent].parent].capture, ..., + until f[x].capture, with x such that + f[x].parent is the youngest common ancestor + for c and n. + + We go up along c's and n's ancestry until + we find x. + */ + } else { + p = c; + q = n; + while ( p != q ) { + if ( p > q ) { + cap = f[p].capture; + if ( cap >= 0 ) { + if ( capBegin[cap] == i ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } else { + capEnd[cap] = i; + } + } + p = f[p].parent; + } else { + q = f[q].parent; + } + } + } + + /* + In any case, we now open the capture zones + we are entering. We work upwards from n + until we reach p (the parent of the atom we + reenter or the youngest common ancestor). + */ + while ( n > p ) { + cap = f[n].capture; + if ( cap >= 0 ) { + capBegin[cap] = i; + capEnd[cap] = EmptyCapture; + } + n = f[n].parent; + } + /* + If the next state was already in + mmNextStack, we must choose carefully which + capture zones we want to keep. + */ + if ( capBegin == mmTempCapBegin && + isBetterCapture(capBegin, capEnd, + mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap) ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + } +#ifndef QT_NO_REGEXP_BACKREF + /* + We are done with updating the capture zones. + It's now time to put the next state to sleep, + if it needs to, and to remove it from + mmNextStack. + */ + if ( needSomeSleep > 0 ) { + zzZ = new int[1 + 2 * ncap]; + zzZ[0] = next; + if ( ncap > 0 ) { + memcpy( zzZ + 1, capBegin, ncap * sizeof(int) ); + memcpy( zzZ + 1 + ncap, capEnd, + ncap * sizeof(int) ); + } + mmInNextStack[mmNextStack[--nnext]] = -1; + mmSleeping.insert( i + needSomeSleep, zzZ ); + } +#endif +#endif + } + } + } +#ifndef QT_NO_REGEXP_CAPTURE + /* + If we reached the final state, hurray! Copy the captured + zone. + */ + if ( ncap > 0 && (m = mmInNextStack[FinalState]) != -1 ) { + memcpy( mmCapBegin, mmNextCapBegin + m * ncap, ncap * sizeof(int) ); + memcpy( mmCapEnd, mmNextCapEnd + m * ncap, ncap * sizeof(int) ); + } +#ifndef QT_NO_REGEXP_BACKREF + /* + It's time to wake up the sleepers. + */ + if ( !mmSleeping.isEmpty() ) { + while ( (zzZ = mmSleeping.take(i)) != 0 ) { + int next = zzZ[0]; + int *capBegin = zzZ + 1; + int *capEnd = zzZ + 1 + ncap; + bool copyOver = TRUE; + + if ( (m = mmInNextStack[zzZ[0]]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; + } else { + copyOver = isBetterCapture( mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap, + capBegin, capEnd ); + } + if ( copyOver ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + delete[] zzZ; + } + } +#endif +#endif + for ( j = 0; j < nnext; j++ ) + mmInNextStack[mmNextStack[j]] = -1; + + // avoid needless iteration that confuses mmMatchedLen + if ( nnext == 1 && mmNextStack[0] == FinalState +#ifndef QT_NO_REGEXP_BACKREF + && mmSleeping.isEmpty() +#endif + ) + stop = TRUE; + + qSwap( mmCurStack, mmNextStack ); +#ifndef QT_NO_REGEXP_CAPTURE + qSwap( mmCurCapBegin, mmNextCapBegin ); + qSwap( mmCurCapEnd, mmNextCapEnd ); +#endif + ncur = nnext; + nnext = 0; + i++; + } + +#ifndef QT_NO_REGEXP_BACKREF + /* + If minimal matching is enabled, we might have some sleepers + left. + */ + while ( !mmSleeping.isEmpty() ) { + zzZ = mmSleeping.take( *QIntDictIterator<int>(mmSleeping) ); + delete[] zzZ; + } +#endif + + mmMatchedLen = i - 1; + return ( mmMatchLen >= 0 ); +} + +#ifndef QT_NO_REGEXP_CCLASS + +QRegExpEngine::CharClass::CharClass() + : c( 0 ), n( FALSE ) +{ +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill( NoOccurrence, NumBadChars ); +#endif +} + +QRegExpEngine::CharClass& QRegExpEngine::CharClass::operator=( + const CharClass& cc ) +{ + c = cc.c; + r = cc.r.copy(); + n = cc.n; +#ifndef QT_NO_REGEXP_OPTIM + occ1 = cc.occ1; +#endif + return *this; +} + +void QRegExpEngine::CharClass::clear() +{ + c = 0; + r.resize( 0 ); + n = FALSE; +} + +void QRegExpEngine::CharClass::setNegative( bool negative ) +{ + n = negative; +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill( 0, NumBadChars ); +#endif +} + +void QRegExpEngine::CharClass::addCategories( int cats ) +{ + c |= cats; +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill( 0, NumBadChars ); +#endif +} + +void QRegExpEngine::CharClass::addRange( ushort from, ushort to ) +{ + if ( from > to ) + qSwap( from, to ); + int m = r.size(); + r.resize( m + 1 ); + r[m].from = from; + r[m].to = to; + +#ifndef QT_NO_REGEXP_OPTIM + int i; + + if ( to - from < NumBadChars ) { + occ1.detach(); + if ( from % NumBadChars <= to % NumBadChars ) { + for ( i = from % NumBadChars; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + } else { + for ( i = 0; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + for ( i = from % NumBadChars; i < NumBadChars; i++ ) + occ1[i] = 0; + } + } else { + occ1.fill( 0, NumBadChars ); + } +#endif +} + +bool QRegExpEngine::CharClass::in( QChar ch ) const +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( occ1[BadChar(ch)] == NoOccurrence ) + return n; +#endif + + if ( c != 0 && (c & (1 << (int) ch.category())) != 0 ) + return !n; + for ( int i = 0; i < (int) r.size(); i++ ) { + if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to ) + return !n; + } + return n; +} + +#if defined(QT_DEBUG) +void QRegExpEngine::CharClass::dump() const +{ + int i; + qDebug( " %stive character class", n ? "nega" : "posi" ); +#ifndef QT_NO_REGEXP_CCLASS + if ( c != 0 ) + qDebug( " categories 0x%.8x", c ); +#endif + for ( i = 0; i < (int) r.size(); i++ ) + qDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to ); +} +#endif +#endif + +QRegExpEngine::Box::Box( QRegExpEngine *engine ) + : eng( engine ), skipanchors( 0 ) +#ifndef QT_NO_REGEXP_OPTIM + , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ) +#endif +{ +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill( NoOccurrence, NumBadChars ); +#endif + minl = 0; +} + +QRegExpEngine::Box& QRegExpEngine::Box::operator=( const Box& b ) +{ + eng = b.eng; + ls = b.ls; + rs = b.rs; + lanchors = b.lanchors; + ranchors = b.ranchors; + skipanchors = b.skipanchors; +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = b.earlyStart; + lateStart = b.lateStart; + str = b.str; + leftStr = b.leftStr; + rightStr = b.rightStr; + maxl = b.maxl; + occ1 = b.occ1; +#endif + minl = b.minl; + return *this; +} + +void QRegExpEngine::Box::set( QChar ch ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( ch ); + rs = ls; + rs.detach(); +#ifndef QT_NO_REGEXP_OPTIM + str = ch; + leftStr = ch; + rightStr = ch; + maxl = 1; + occ1.detach(); + occ1[BadChar(ch)] = 0; +#endif + minl = 1; +} + +void QRegExpEngine::Box::set( const CharClass& cc ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( cc ); + rs = ls; + rs.detach(); +#ifndef QT_NO_REGEXP_OPTIM + maxl = 1; + occ1 = cc.firstOccurrence(); +#endif + minl = 1; +} + +#ifndef QT_NO_REGEXP_BACKREF +void QRegExpEngine::Box::set( int bref ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( bref ); + rs = ls; + rs.detach(); + if ( bref >= 1 && bref <= MaxBackRefs ) + skipanchors = Anchor_BackRef0Empty << bref; +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif + minl = 0; +} +#endif + +void QRegExpEngine::Box::cat( const Box& b ) +{ + eng->addCatTransitions( rs, b.ls ); + addAnchorsToEngine( b ); + if ( minl == 0 ) { + mergeInto( &lanchors, b.lanchors ); + if ( skipanchors != 0 ) { + for ( int i = 0; i < (int) b.ls.size(); i++ ) { + int a = eng->anchorConcatenation( at(lanchors, b.ls[i]), + skipanchors ); + lanchors.insert( b.ls[i], a ); + } + } + mergeInto( &ls, b.ls ); + } + if ( b.minl == 0 ) { + mergeInto( &ranchors, b.ranchors ); + if ( b.skipanchors != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[i]), + b.skipanchors ); + ranchors.insert( rs[i], a ); + } + } + mergeInto( &rs, b.rs ); + } else { + ranchors = b.ranchors; + rs = b.rs; + } + +#ifndef QT_NO_REGEXP_OPTIM + if ( maxl != InftyLen ) { + if ( rightStr.length() + b.leftStr.length() > + QMAX(str.length(), b.str.length()) ) { + earlyStart = minl - rightStr.length(); + lateStart = maxl - rightStr.length(); + str = rightStr + b.leftStr; + } else if ( b.str.length() > str.length() ) { + earlyStart = minl + b.earlyStart; + lateStart = maxl + b.lateStart; + str = b.str; + } + } + + if ( (int) leftStr.length() == maxl ) + leftStr += b.leftStr; + if ( (int) b.rightStr.length() == b.maxl ) + rightStr += b.rightStr; + else + rightStr = b.rightStr; + + if ( maxl == InftyLen || b.maxl == InftyLen ) + maxl = InftyLen; + else + maxl += b.maxl; + + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] ) + occ1[i] = minl + b.occ1[i]; + } +#endif + + minl += b.minl; + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors ); + else + skipanchors = 0; +} + +void QRegExpEngine::Box::orx( const Box& b ) +{ + mergeInto( &ls, b.ls ); + mergeInto( &lanchors, b.lanchors ); + mergeInto( &rs, b.rs ); + mergeInto( &ranchors, b.ranchors ); + + if ( b.minl == 0 ) { + if ( minl == 0 ) + skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors ); + else + skipanchors = b.skipanchors; + } + +#ifndef QT_NO_REGEXP_OPTIM + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] > b.occ1[i] ) + occ1[i] = b.occ1[i]; + } + earlyStart = 0; + lateStart = 0; + str = QString(); + leftStr = QString(); + rightStr = QString(); + if ( b.maxl > maxl ) + maxl = b.maxl; +#endif + if ( b.minl < minl ) + minl = b.minl; +} + +void QRegExpEngine::Box::plus( int atom ) +{ +#ifndef QT_NO_REGEXP_CAPTURE + eng->addPlusTransitions( rs, ls, atom ); +#else + Q_UNUSED( atom ); + eng->addCatTransitions( rs, ls ); +#endif + addAnchorsToEngine( *this ); +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif +} + +void QRegExpEngine::Box::opt() +{ +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = 0; + lateStart = 0; + str = QString(); + leftStr = QString(); + rightStr = QString(); +#endif + skipanchors = 0; + minl = 0; +} + +void QRegExpEngine::Box::catAnchor( int a ) +{ + if ( a != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + a = eng->anchorConcatenation( at(ranchors, rs[i]), a ); + ranchors.insert( rs[i], a ); + } + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, a ); + } +} + +#ifndef QT_NO_REGEXP_OPTIM +void QRegExpEngine::Box::setupHeuristics() +{ + eng->setupGoodStringHeuristic( earlyStart, lateStart, str ); + + /* + A regular expression such as 112|1 has occ1['2'] = 2 and minl = + 1 at this point. An entry of occ1 has to be at most minl or + infinity for the rest of the algorithm to go well. + + We waited until here before normalizing these cases (instead of + doing it in Box::orx()) because sometimes things improve by + themselves. Consider for example (112|1)34. + */ + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] != NoOccurrence && occ1[i] >= minl ) + occ1[i] = minl; + } + eng->setupBadCharHeuristic( minl, occ1 ); + + eng->heuristicallyChooseHeuristic(); +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::Box::dump() const +{ + int i; + qDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" ); + qDebug( " Left states:" ); + for ( i = 0; i < (int) ls.size(); i++ ) { + if ( at(lanchors, ls[i]) == 0 ) + qDebug( " %d", ls[i] ); + else + qDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] ); + } + qDebug( " Right states:" ); + for ( i = 0; i < (int) rs.size(); i++ ) { + if ( at(ranchors, rs[i]) == 0 ) + qDebug( " %d", rs[i] ); + else + qDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] ); + } + qDebug( " Skip anchors: 0x%.8x", skipanchors ); +} +#endif + +void QRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const +{ + for ( int i = 0; i < (int) to.ls.size(); i++ ) { + for ( int j = 0; j < (int) rs.size(); j++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[j]), + at(to.lanchors, to.ls[i]) ); + eng->addAnchors( rs[j], to.ls[i], a ); + } + } +} + +int QRegExpEngine::getChar() +{ + return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode(); +} + +int QRegExpEngine::getEscape() +{ +#ifndef QT_NO_REGEXP_ESCAPE + const char tab[] = "afnrtv"; // no b, as \b means word boundary + const char backTab[] = "\a\f\n\r\t\v"; + ushort low; + int i; +#endif + ushort val; + int prevCh = yyCh; + + if ( prevCh == EOS ) { + error( RXERR_END ); + return Tok_Char | '\\'; + } + yyCh = getChar(); +#ifndef QT_NO_REGEXP_ESCAPE + if ( (prevCh & ~0xff) == 0 ) { + const char *p = strchr( tab, prevCh ); + if ( p != 0 ) + return Tok_Char | backTab[p - tab]; + } +#endif + + switch ( prevCh ) { +#ifndef QT_NO_REGEXP_ESCAPE + case '0': + val = 0; + for ( i = 0; i < 3; i++ ) { + if ( yyCh >= '0' && yyCh <= '7' ) + val = ( val << 3 ) | ( yyCh - '0' ); + else + break; + yyCh = getChar(); + } + if ( (val & ~0377) != 0 ) + error( RXERR_OCTAL ); + return Tok_Char | val; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'B': + return Tok_NonWord; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'D': + // see QChar::isDigit() + yyCharClass->addCategories( 0x7fffffef ); + return Tok_CharClass; + case 'S': + // see QChar::isSpace() + yyCharClass->addCategories( 0x7ffff87f ); + yyCharClass->addRange( 0x0000, 0x0008 ); + yyCharClass->addRange( 0x000e, 0x001f ); + yyCharClass->addRange( 0x007f, 0x009f ); + return Tok_CharClass; + case 'W': + // see QChar::isLetterOrNumber() + yyCharClass->addCategories( 0x7ff07f8f ); + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'b': + return Tok_Word; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'd': + // see QChar::isDigit() + yyCharClass->addCategories( 0x00000010 ); + return Tok_CharClass; + case 's': + // see QChar::isSpace() + yyCharClass->addCategories( 0x00000380 ); + yyCharClass->addRange( 0x0009, 0x000d ); + return Tok_CharClass; + case 'w': + // see QChar::isLetterOrNumber() + yyCharClass->addCategories( 0x000f8070 ); + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'x': + val = 0; + for ( i = 0; i < 4; i++ ) { + low = QChar( yyCh ).lower(); + if ( low >= '0' && low <= '9' ) + val = ( val << 4 ) | ( low - '0' ); + else if ( low >= 'a' && low <= 'f' ) + val = ( val << 4 ) | ( low - 'a' + 10 ); + else + break; + yyCh = getChar(); + } + return Tok_Char | val; +#endif + default: + if ( prevCh >= '1' && prevCh <= '9' ) { +#ifndef QT_NO_REGEXP_BACKREF + val = prevCh - '0'; + while ( yyCh >= '0' && yyCh <= '9' ) { + val = ( val *= 10 ) | ( yyCh - '0' ); + yyCh = getChar(); + } + return Tok_BackRef | val; +#else + error( RXERR_DISABLED ); +#endif + } + return Tok_Char | prevCh; + } +} + +#ifndef QT_NO_REGEXP_INTERVAL +int QRegExpEngine::getRep( int def ) +{ + if ( yyCh >= '0' && yyCh <= '9' ) { + int rep = 0; + do { + rep = 10 * rep + yyCh - '0'; + if ( rep >= InftyRep ) { + error( RXERR_REPETITION ); + rep = def; + } + yyCh = getChar(); + } while ( yyCh >= '0' && yyCh <= '9' ); + return rep; + } else { + return def; + } +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +void QRegExpEngine::skipChars( int n ) +{ + if ( n > 0 ) { + yyPos += n - 1; + yyCh = getChar(); + } +} +#endif + +void QRegExpEngine::error( const char *msg ) +{ + if ( yyError.isEmpty() ) + yyError = QString::fromLatin1( msg ); +} + +void QRegExpEngine::startTokenizer( const QChar *rx, int len ) +{ + yyIn = rx; + yyPos0 = 0; + yyPos = 0; + yyLen = len; + yyCh = getChar(); + yyCharClass = new CharClass; + yyMinRep = 0; + yyMaxRep = 0; + yyError = QString(); +} + +int QRegExpEngine::getToken() +{ +#ifndef QT_NO_REGEXP_CCLASS + ushort pendingCh = 0; + bool charPending; + bool rangePending; + int tok; +#endif + int prevCh = yyCh; + + yyPos0 = yyPos - 1; +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->clear(); +#endif + yyMinRep = 0; + yyMaxRep = 0; + yyCh = getChar(); + switch ( prevCh ) { + case EOS: + yyPos0 = yyPos; + return Tok_Eos; + case '$': + return Tok_Dollar; + case '(': + if ( yyCh == '?' ) { + prevCh = getChar(); + yyCh = getChar(); + switch ( prevCh ) { +#ifndef QT_NO_REGEXP_LOOKAHEAD + case '!': + return Tok_NegLookahead; + case '=': + return Tok_PosLookahead; +#endif + case ':': + return Tok_MagicLeftParen; + default: + error( RXERR_LOOKAHEAD ); + return Tok_MagicLeftParen; + } + } else { + return Tok_LeftParen; + } + case ')': + return Tok_RightParen; + case '*': + yyMinRep = 0; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '+': + yyMinRep = 1; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '.': +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->setNegative( TRUE ); +#endif + return Tok_CharClass; + case '?': + yyMinRep = 0; + yyMaxRep = 1; + return Tok_Quantifier; + case '[': +#ifndef QT_NO_REGEXP_CCLASS + if ( yyCh == '^' ) { + yyCharClass->setNegative( TRUE ); + yyCh = getChar(); + } + charPending = FALSE; + rangePending = FALSE; + do { + if ( yyCh == '-' && charPending && !rangePending ) { + rangePending = TRUE; + yyCh = getChar(); + } else { + if ( charPending && !rangePending ) { + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + } + if ( yyCh == '\\' ) { + yyCh = getChar(); + tok = getEscape(); + if ( tok == Tok_Word ) + tok = '\b'; + } else { + tok = Tok_Char | yyCh; + yyCh = getChar(); + } + if ( tok == Tok_CharClass ) { + if ( rangePending ) { + yyCharClass->addSingleton( '-' ); + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + rangePending = FALSE; + } + } else if ( (tok & Tok_Char) != 0 ) { + if ( rangePending ) { + yyCharClass->addRange( pendingCh, tok ^ Tok_Char ); + charPending = FALSE; + rangePending = FALSE; + } else { + pendingCh = tok ^ Tok_Char; + charPending = TRUE; + } + } else { + error( RXERR_CHARCLASS ); + } + } + } while ( yyCh != ']' && yyCh != EOS ); + if ( rangePending ) + yyCharClass->addSingleton( '-' ); + if ( charPending ) + yyCharClass->addSingleton( pendingCh ); + if ( yyCh == EOS ) + error( RXERR_END ); + else + yyCh = getChar(); + return Tok_CharClass; +#else + error( RXERR_END ); + return Tok_Char | '['; +#endif + case '\\': + return getEscape(); + case ']': + error( RXERR_LEFTDELIM ); + return Tok_Char | ']'; + case '^': + return Tok_Caret; + case '{': +#ifndef QT_NO_REGEXP_INTERVAL + yyMinRep = getRep( 0 ); + yyMaxRep = yyMinRep; + if ( yyCh == ',' ) { + yyCh = getChar(); + yyMaxRep = getRep( InftyRep ); + } + if ( yyMaxRep < yyMinRep ) + qSwap( yyMinRep, yyMaxRep ); + if ( yyCh != '}' ) + error( RXERR_REPETITION ); + yyCh = getChar(); + return Tok_Quantifier; +#else + error( RXERR_DISABLED ); + return Tok_Char | '{'; +#endif + case '|': + return Tok_Bar; + case '}': + error( RXERR_LEFTDELIM ); + return Tok_Char | '}'; + default: + return Tok_Char | prevCh; + } +} + +int QRegExpEngine::parse( const QChar *pattern, int len ) +{ + valid = TRUE; + startTokenizer( pattern, len ); + yyTok = getToken(); +#ifndef QT_NO_REGEXP_CAPTURE + yyMayCapture = TRUE; +#else + yyMayCapture = FALSE; +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + int atom = startAtom( FALSE ); +#endif + CharClass anything; + Box box( this ); // create InitialState + box.set( anything ); + Box rightBox( this ); // create FinalState + rightBox.set( anything ); + + Box middleBox( this ); + parseExpression( &middleBox ); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif +#ifndef QT_NO_REGEXP_OPTIM + middleBox.setupHeuristics(); +#endif + box.cat( middleBox ); + box.cat( rightBox ); + delete yyCharClass; + yyCharClass = 0; + + officialncap = ncap; +#ifndef QT_NO_REGEXP_BACKREF + if ( nbrefs > ncap ) + ncap = nbrefs; +#endif + + mmCaptured.resize( 2 + 2 * officialncap ); + mmCapturedNoMatch.fill( -1, 2 + 2 * officialncap ); + + /* + We use one QMemArray<int> for all the big data used a lot in + matchHere() and friends. + */ +#ifndef QT_NO_REGEXP_OPTIM + mmSlideTabSize = QMAX( minl + 1, 16 ); +#else + mmSlideTabSize = 0; +#endif + mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize ); + + mmInNextStack = mmBigArray.data(); + memset( mmInNextStack, -1, ns * sizeof(int) ); + mmCurStack = mmInNextStack + ns; + mmNextStack = mmInNextStack + 2 * ns; + + mmCurCapBegin = mmInNextStack + 3 * ns; + mmNextCapBegin = mmCurCapBegin + ncap * ns; + mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns; + mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns; + + mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns; + mmTempCapEnd = mmTempCapBegin + ncap; + mmCapBegin = mmTempCapBegin + 2 * ncap; + mmCapEnd = mmTempCapBegin + 3 * ncap; + + mmSlideTab = mmTempCapBegin + 4 * ncap; + + if ( !yyError.isEmpty() ) + return -1; + +#ifndef QT_NO_REGEXP_OPTIM + State *sinit = s[InitialState]; + caretAnchored = ( sinit->anchors != 0 ); + if ( caretAnchored ) { + QMap<int, int>& anchors = *sinit->anchors; + QMap<int, int>::ConstIterator a; + for ( a = anchors.begin(); a != anchors.end(); ++a ) { +#ifndef QT_NO_REGEXP_ANCHOR_ALT + if ( (*a & Anchor_Alternation) != 0 ) + break; +#endif + if ( (*a & Anchor_Caret) == 0 ) { + caretAnchored = FALSE; + break; + } + } + } +#endif + return yyPos0; +} + +void QRegExpEngine::parseAtom( Box *box ) +{ +#ifndef QT_NO_REGEXP_LOOKAHEAD + QRegExpEngine *eng = 0; + bool neg; + int len; +#endif + + switch ( yyTok ) { + case Tok_Dollar: + box->catAnchor( Anchor_Dollar ); + break; + case Tok_Caret: + box->catAnchor( Anchor_Caret ); + break; +#ifndef QT_NO_REGEXP_LOOKAHEAD + case Tok_PosLookahead: + case Tok_NegLookahead: + neg = ( yyTok == Tok_NegLookahead ); + eng = new QRegExpEngine( cs ); + len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 ); + if ( len >= 0 ) + skipChars( len ); + else + error( RXERR_LOOKAHEAD ); + box->catAnchor( addLookahead(eng, neg) ); + yyTok = getToken(); + if ( yyTok != Tok_RightParen ) + error( RXERR_LOOKAHEAD ); + break; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case Tok_Word: + box->catAnchor( Anchor_Word ); + break; + case Tok_NonWord: + box->catAnchor( Anchor_NonWord ); + break; +#endif + case Tok_LeftParen: + case Tok_MagicLeftParen: + yyTok = getToken(); + parseExpression( box ); + if ( yyTok != Tok_RightParen ) + error( RXERR_END ); + break; + case Tok_CharClass: + box->set( *yyCharClass ); + break; + case Tok_Quantifier: + error( RXERR_REPETITION ); + break; + default: + if ( (yyTok & Tok_Char) != 0 ) + box->set( QChar(yyTok ^ Tok_Char) ); +#ifndef QT_NO_REGEXP_BACKREF + else if ( (yyTok & Tok_BackRef) != 0 ) + box->set( yyTok ^ Tok_BackRef ); +#endif + else + error( RXERR_DISABLED ); + } + yyTok = getToken(); +} + +void QRegExpEngine::parseFactor( Box *box ) +{ +#ifndef QT_NO_REGEXP_CAPTURE + int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen ); +#else + static const int atom = 0; +#endif + +#ifndef QT_NO_REGEXP_INTERVAL +#define YYREDO() \ + yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ + *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok + + const QChar *in = yyIn; + int pos0 = yyPos0; + int pos = yyPos; + int len = yyLen; + int ch = yyCh; + CharClass charClass; + if ( yyTok == Tok_CharClass ) + charClass = *yyCharClass; + int tok = yyTok; + bool mayCapture = yyMayCapture; +#endif + + parseAtom( box ); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif + + if ( yyTok == Tok_Quantifier ) { + if ( yyMaxRep == InftyRep ) { + box->plus( atom ); +#ifndef QT_NO_REGEXP_INTERVAL + } else if ( yyMaxRep == 0 ) { + box->clear(); +#endif + } + if ( yyMinRep == 0 ) + box->opt(); + +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = FALSE; + int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1; + int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 ); + + Box rightBox( this ); + int i; + + for ( i = 0; i < beta; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + leftBox.opt(); + rightBox = leftBox; + } + for ( i = 0; i < alpha; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + rightBox = leftBox; + } + rightBox.cat( *box ); + *box = rightBox; +#endif + yyTok = getToken(); +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = mayCapture; +#endif + } +#undef YYREDO +} + +void QRegExpEngine::parseTerm( Box *box ) +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) + parseFactor( box ); +#endif + while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) { + Box rightBox( this ); + parseFactor( &rightBox ); + box->cat( rightBox ); + } +} + +void QRegExpEngine::parseExpression( Box *box ) +{ + parseTerm( box ); + while ( yyTok == Tok_Bar ) { + Box rightBox( this ); + yyTok = getToken(); + parseTerm( &rightBox ); + box->orx( rightBox ); + } +} + +/* + The struct QRegExpPrivate contains the private data of a regular + expression other than the automaton. It makes it possible for many + QRegExp objects to use the same QRegExpEngine object with different + QRegExpPrivate objects. +*/ +struct QRegExpPrivate +{ + QString pattern; // regular-expression or wildcard pattern + QString rxpattern; // regular-expression pattern +#ifndef QT_NO_REGEXP_WILDCARD + bool wc; // wildcard mode? +#endif + bool min; // minimal matching? (instead of maximal) +#ifndef QT_NO_REGEXP_CAPTURE + QString t; // last string passed to QRegExp::search() or searchRev() + QStringList capturedCache; // what QRegExp::capturedTexts() returned last +#endif + QMemArray<int> captured; // what QRegExpEngine::search() returned last + + QRegExpPrivate() { captured.fill( -1, 2 ); } +}; + +#ifndef QT_NO_REGEXP_OPTIM +static QCache<QRegExpEngine> *engineCache = 0; +static QSingleCleanupHandler<QCache<QRegExpEngine> > cleanup_cache; +#endif + +static QRegExpEngine *newEngine( const QString& pattern, bool caseSensitive ) +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( engineCache != 0 ) { +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &engineCache ) ); +#endif + QRegExpEngine *eng = engineCache->take( pattern ); + if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { + delete eng; + } else { + eng->ref(); + return eng; + } + } +#endif + return new QRegExpEngine( pattern, caseSensitive ); +} + +static void derefEngine( QRegExpEngine *eng, const QString& pattern ) +{ + if ( eng != 0 && eng->deref() ) { +#ifndef QT_NO_REGEXP_OPTIM +#ifdef QT_THREAD_SUPPORT + QMutexLocker locker( qt_global_mutexpool->get( &engineCache ) ); +#endif + if ( engineCache == 0 ) { + engineCache = new QCache<QRegExpEngine>; + engineCache->setAutoDelete( TRUE ); + cleanup_cache.set( &engineCache ); + } + if ( !pattern.isNull() && + engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) + return; +#else + Q_UNUSED( pattern ); +#endif + delete eng; + } +} + +/*! + \enum QRegExp::CaretMode + + The CaretMode enum defines the different meanings of the caret + (<b>^</b>) in a regular expression. The possible values are: + + \value CaretAtZero + The caret corresponds to index 0 in the searched string. + + \value CaretAtOffset + The caret corresponds to the start offset of the search. + + \value CaretWontMatch + The caret never matches. +*/ + +/*! + Constructs an empty regexp. + + \sa isValid() errorString() +*/ +QRegExp::QRegExp() +{ + eng = new QRegExpEngine( TRUE ); + priv = new QRegExpPrivate; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = FALSE; +#endif + priv->min = FALSE; + compile( TRUE ); +} + +/*! + Constructs a regular expression object for the given \a pattern + string. The pattern must be given using wildcard notation if \a + wildcard is TRUE (default is FALSE). The pattern is case + sensitive, unless \a caseSensitive is FALSE. Matching is greedy + (maximal), but can be changed by calling setMinimal(). + + \sa setPattern() setCaseSensitive() setWildcard() setMinimal() +*/ +QRegExp::QRegExp( const QString& pattern, bool caseSensitive, bool wildcard ) +{ + eng = 0; + priv = new QRegExpPrivate; + priv->pattern = pattern; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = wildcard; +#endif + priv->min = FALSE; + compile( caseSensitive ); +} + +/*! + Constructs a regular expression as a copy of \a rx. + + \sa operator=() +*/ +QRegExp::QRegExp( const QRegExp& rx ) +{ + eng = 0; + priv = new QRegExpPrivate; + operator=( rx ); +} + +/*! + Destroys the regular expression and cleans up its internal data. +*/ +QRegExp::~QRegExp() +{ + derefEngine( eng, priv->rxpattern ); + delete priv; +} + +/*! + Copies the regular expression \a rx and returns a reference to the + copy. The case sensitivity, wildcard and minimal matching options + are also copied. +*/ +QRegExp& QRegExp::operator=( const QRegExp& rx ) +{ + rx.eng->ref(); + derefEngine( eng, priv->rxpattern ); + eng = rx.eng; + priv->pattern = rx.priv->pattern; + priv->rxpattern = rx.priv->rxpattern; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = rx.priv->wc; +#endif + priv->min = rx.priv->min; +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = rx.priv->t; + priv->capturedCache = rx.priv->capturedCache; +#endif + priv->captured = rx.priv->captured; + return *this; +} + +/*! + Returns TRUE if this regular expression is equal to \a rx; + otherwise returns FALSE. + + Two QRegExp objects are equal if they have the same pattern + strings and the same settings for case sensitivity, wildcard and + minimal matching. +*/ +bool QRegExp::operator==( const QRegExp& rx ) const +{ + return priv->pattern == rx.priv->pattern && + eng->caseSensitive() == rx.eng->caseSensitive() && +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc == rx.priv->wc && +#endif + priv->min == rx.priv->min; +} + +/*! + \fn bool QRegExp::operator!=( const QRegExp& rx ) const + + Returns TRUE if this regular expression is not equal to \a rx; + otherwise returns FALSE. + + \sa operator==() +*/ + +/*! + Returns TRUE if the pattern string is empty; otherwise returns + FALSE. + + If you call exactMatch() with an empty pattern on an empty string + it will return TRUE; otherwise it returns FALSE since it operates + over the whole string. If you call search() with an empty pattern + on \e any string it will return the start offset (0 by default) + because the empty pattern matches the 'emptiness' at the start of + the string. In this case the length of the match returned by + matchedLength() will be 0. + + See QString::isEmpty(). +*/ + +bool QRegExp::isEmpty() const +{ + return priv->pattern.isEmpty(); +} + +/*! + Returns TRUE if the regular expression is valid; otherwise returns + FALSE. An invalid regular expression never matches. + + The pattern <b>[a-z</b> is an example of an invalid pattern, since + it lacks a closing square bracket. + + Note that the validity of a regexp may also depend on the setting + of the wildcard flag, for example <b>*.html</b> is a valid + wildcard regexp but an invalid full regexp. + + \sa errorString() +*/ +bool QRegExp::isValid() const +{ + return eng->isValid(); +} + +/*! + Returns the pattern string of the regular expression. The pattern + has either regular expression syntax or wildcard syntax, depending + on wildcard(). + + \sa setPattern() +*/ +QString QRegExp::pattern() const +{ + return priv->pattern; +} + +/*! + Sets the pattern string to \a pattern. The case sensitivity, + wildcard and minimal matching options are not changed. + + \sa pattern() +*/ +void QRegExp::setPattern( const QString& pattern ) +{ + if ( priv->pattern != pattern ) { + priv->pattern = pattern; + compile( caseSensitive() ); + } +} + +/*! + Returns TRUE if case sensitivity is enabled; otherwise returns + FALSE. The default is TRUE. + + \sa setCaseSensitive() +*/ +bool QRegExp::caseSensitive() const +{ + return eng->caseSensitive(); +} + +/*! + Sets case sensitive matching to \a sensitive. + + If \a sensitive is TRUE, <b>\\.txt$</b> matches \c{readme.txt} but + not \c{README.TXT}. + + \sa caseSensitive() +*/ +void QRegExp::setCaseSensitive( bool sensitive ) +{ + if ( sensitive != eng->caseSensitive() ) + compile( sensitive ); +} + +#ifndef QT_NO_REGEXP_WILDCARD +/*! + Returns TRUE if wildcard mode is enabled; otherwise returns FALSE. + The default is FALSE. + + \sa setWildcard() +*/ +bool QRegExp::wildcard() const +{ + return priv->wc; +} + +/*! + Sets the wildcard mode for the regular expression. The default is + FALSE. + + Setting \a wildcard to TRUE enables simple shell-like wildcard + matching. (See \link #wildcard-matching wildcard matching + (globbing) \endlink.) + + For example, <b>r*.txt</b> matches the string \c{readme.txt} in + wildcard mode, but does not match \c{readme}. + + \sa wildcard() +*/ +void QRegExp::setWildcard( bool wildcard ) +{ + if ( wildcard != priv->wc ) { + priv->wc = wildcard; + compile( caseSensitive() ); + } +} +#endif + +/*! + Returns TRUE if minimal (non-greedy) matching is enabled; + otherwise returns FALSE. + + \sa setMinimal() +*/ +bool QRegExp::minimal() const +{ + return priv->min; +} + +/*! + Enables or disables minimal matching. If \a minimal is FALSE, + matching is greedy (maximal) which is the default. + + For example, suppose we have the input string "We must be + \<b>bold\</b>, very \<b>bold\</b>!" and the pattern + <b>\<b>.*\</b></b>. With the default greedy (maximal) matching, + the match is "We must be <u>\<b>bold\</b>, very + \<b>bold\</b></u>!". But with minimal (non-greedy) matching the + first match is: "We must be <u>\<b>bold\</b></u>, very + \<b>bold\</b>!" and the second match is "We must be \<b>bold\</b>, + very <u>\<b>bold\</b></u>!". In practice we might use the pattern + <b>\<b>[^\<]+\</b></b> instead, although this will still fail for + nested tags. + + \sa minimal() +*/ +void QRegExp::setMinimal( bool minimal ) +{ + priv->min = minimal; +} + +/*! + Returns TRUE if \a str is matched exactly by this regular + expression; otherwise returns FALSE. You can determine how much of + the string was matched by calling matchedLength(). + + For a given regexp string, R, exactMatch("R") is the equivalent of + search("^R$") since exactMatch() effectively encloses the regexp + in the start of string and end of string anchors, except that it + sets matchedLength() differently. + + For example, if the regular expression is <b>blue</b>, then + exactMatch() returns TRUE only for input \c blue. For inputs \c + bluebell, \c blutak and \c lightblue, exactMatch() returns FALSE + and matchedLength() will return 4, 3 and 0 respectively. + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \sa search() searchRev() QRegExpValidator +*/ +bool QRegExp::exactMatch( const QString& str ) const +{ +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + + priv->captured = eng->match( str, 0, priv->min, TRUE, 0 ); + if ( priv->captured[1] == (int) str.length() ) { + return TRUE; + } else { + priv->captured.detach(); + priv->captured[0] = 0; + priv->captured[1] = eng->matchedLength(); + return FALSE; + } +} + +#ifndef QT_NO_COMPAT +/*! \obsolete + + Attempts to match in \a str, starting from position \a index. + Returns the position of the match, or -1 if there was no match. + + The length of the match is stored in \a *len, unless \a len is a + null pointer. + + If \a indexIsStart is TRUE (the default), the position \a index in + the string will match the start of string anchor, <b>^</b>, in the + regexp, if present. Otherwise, position 0 in \a str will match. + + Use search() and matchedLength() instead of this function. + + \sa QString::mid() QConstString +*/ +int QRegExp::match( const QString& str, int index, int *len, + bool indexIsStart ) const +{ + int pos = search( str, index, indexIsStart ? CaretAtOffset : CaretAtZero ); + if ( len != 0 ) + *len = matchedLength(); + return pos; +} +#endif // QT_NO_COMPAT + +/*! + \overload + + This convenience function searches with a \c CaretMode of \c + CaretAtZero which is the most common usage. +*/ + +int QRegExp::search( const QString& str, int offset ) const +{ + return search( str, offset, CaretAtZero ); +} + +/*! + Attempts to find a match in \a str from position \a offset (0 by + default). If \a offset is -1, the search starts at the last + character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether <b>^</b> + should match at index 0 or at \a offset. + + You might prefer to use QString::find(), QString::contains() or + even QStringList::grep(). To replace matches use + QString::replace(). + + Example: + \code + QString str = "offsets: 1.23 .50 71.00 6.00"; + QRegExp rx( "\\d*\\.\\d+" ); // primitive floating point matching + int count = 0; + int pos = 0; + while ( (pos = rx.search(str, pos)) != -1 ) { + count++; + pos += rx.matchedLength(); + } + // pos will be 9, 14, 18 and finally 24; count will end up as 4 + \endcode + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \sa searchRev() exactMatch() +*/ + +int QRegExp::search( const QString& str, int offset, CaretMode caretMode ) const +{ + if ( offset < 0 ) + offset += str.length(); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + priv->captured = eng->match( str, offset, priv->min, FALSE, + caretIndex(offset, caretMode) ); + return priv->captured[0]; +} + + +/*! + \overload + + This convenience function searches with a \c CaretMode of \c + CaretAtZero which is the most common usage. +*/ + +int QRegExp::searchRev( const QString& str, int offset ) const +{ + return searchRev( str, offset, CaretAtZero ); +} + +/*! + Attempts to find a match backwards in \a str from position \a + offset. If \a offset is -1 (the default), the search starts at the + last character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether <b>^</b> + should match at index 0 or at \a offset. + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \warning Searching backwards is much slower than searching + forwards. + + \sa search() exactMatch() +*/ + +int QRegExp::searchRev( const QString& str, int offset, + CaretMode caretMode ) const +{ + if ( offset < 0 ) + offset += str.length(); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + if ( offset < 0 || offset > (int) str.length() ) { + priv->captured.detach(); + priv->captured.fill( -1 ); + return -1; + } + + while ( offset >= 0 ) { + priv->captured = eng->match( str, offset, priv->min, TRUE, + caretIndex(offset, caretMode) ); + if ( priv->captured[0] == offset ) + return offset; + offset--; + } + return -1; +} + +/*! + Returns the length of the last matched string, or -1 if there was + no match. + + \sa exactMatch() search() searchRev() +*/ +int QRegExp::matchedLength() const +{ + return priv->captured[1]; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/*! + Returns the number of captures contained in the regular expression. + */ +int QRegExp::numCaptures() const +{ + return eng->numCaptures(); +} + + + +/*! + Returns a list of the captured text strings. + + The first string in the list is the entire matched string. Each + subsequent list element contains a string that matched a + (capturing) subexpression of the regexp. + + For example: + \code + QRegExp rx( "(\\d+)(\\s*)(cm|inch(es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + QStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", " ", "inches", "es" ) + \endcode + + The above example also captures elements that may be present but + which we have no interest in. This problem can be solved by using + non-capturing parentheses: + + \code + QRegExp rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + QStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", "inches" ) + \endcode + + Note that if you want to iterate over the list, you should iterate + over a copy, e.g. + \code + QStringList list = rx.capturedTexts(); + QStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + Some regexps can match an indeterminate number of times. For + example if the input string is "Offsets: 12 14 99 231 7" and the + regexp, \c{rx}, is <b>(\\d+)+</b>, we would hope to get a list of + all the numbers matched. However, after calling + \c{rx.search(str)}, capturedTexts() will return the list ( "12", + "12" ), i.e. the entire match was "12" and the first subexpression + matched was "12". The correct approach is to use cap() in a \link + #cap_in_a_loop loop \endlink. + + The order of elements in the string list is as follows. The first + element is the entire matching string. Each subsequent element + corresponds to the next capturing open left parentheses. Thus + capturedTexts()[1] is the text of the first capturing parentheses, + capturedTexts()[2] is the text of the second and so on + (corresponding to $1, $2, etc., in some other regexp languages). + + \sa cap() pos() exactMatch() search() searchRev() +*/ +QStringList QRegExp::capturedTexts() +{ + if ( priv->capturedCache.isEmpty() ) { + for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) { + QString m; + if ( priv->captured[i + 1] == 0 ) + m = QString::fromLatin1( "" ); + else if ( priv->captured[i] >= 0 ) + m = priv->t.mid( priv->captured[i], + priv->captured[i + 1] ); + priv->capturedCache.append( m ); + } + priv->t = QString::null; + } + return priv->capturedCache; +} + +/*! + Returns the text captured by the \a nth subexpression. The entire + match has index 0 and the parenthesized subexpressions have + indices starting from 1 (excluding non-capturing parentheses). + + \code + QRegExp rxlen( "(\\d+)(?:\\s*)(cm|inch)" ); + int pos = rxlen.search( "Length: 189cm" ); + if ( pos > -1 ) { + QString value = rxlen.cap( 1 ); // "189" + QString unit = rxlen.cap( 2 ); // "cm" + // ... + } + \endcode + + The order of elements matched by cap() is as follows. The first + element, cap(0), is the entire matching string. Each subsequent + element corresponds to the next capturing open left parentheses. + Thus cap(1) is the text of the first capturing parentheses, cap(2) + is the text of the second, and so on. + + \target cap_in_a_loop + Some patterns may lead to a number of matches which cannot be + determined in advance, for example: + + \code + QRegExp rx( "(\\d+)" ); + str = "Offsets: 12 14 99 231 7"; + QStringList list; + pos = 0; + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos > -1 ) { + list += rx.cap( 1 ); + pos += rx.matchedLength(); + } + } + // list contains "12", "14", "99", "231", "7" + \endcode + + \sa capturedTexts() pos() exactMatch() search() searchRev() +*/ +QString QRegExp::cap( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) + return QString::null; + else + return capturedTexts()[nth]; +} + +/*! + Returns the position of the \a nth captured text in the searched + string. If \a nth is 0 (the default), pos() returns the position + of the whole match. + + Example: + \code + QRegExp rx( "/([a-z]+)/([a-z]+)" ); + rx.search( "Output /dev/null" ); // returns 7 (position of /dev/null) + rx.pos( 0 ); // returns 7 (position of /dev/null) + rx.pos( 1 ); // returns 8 (position of dev) + rx.pos( 2 ); // returns 12 (position of null) + \endcode + + For zero-length matches, pos() always returns -1. (For example, if + cap(4) would return an empty string, pos(4) returns -1.) This is + due to an implementation tradeoff. + + \sa capturedTexts() exactMatch() search() searchRev() +*/ +int QRegExp::pos( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) + return -1; + else + return priv->captured[2 * nth]; +} + +/*! + Returns a text string that explains why a regexp pattern is + invalid the case being; otherwise returns "no error occurred". + + \sa isValid() +*/ +QString QRegExp::errorString() +{ + if ( isValid() ) { + return QString( RXERR_OK ); + } else { + return eng->errorString(); + } +} +#endif + +/*! + Returns the string \a str with every regexp special character + escaped with a backslash. The special characters are $, (, ), *, +, + ., ?, [, \, ], ^, {, | and }. + + Example: + \code + s1 = QRegExp::escape( "bingo" ); // s1 == "bingo" + s2 = QRegExp::escape( "f(x)" ); // s2 == "f\\(x\\)" + \endcode + + This function is useful to construct regexp patterns dynamically: + + \code + QRegExp rx( "(" + QRegExp::escape(name) + + "|" + QRegExp::escape(alias) + ")" ); + \endcode +*/ +QString QRegExp::escape( const QString& str ) +{ + static const char meta[] = "$()*+.?[\\]^{|}"; + QString quoted = str; + int i = 0; + + while ( i < (int) quoted.length() ) { + if ( strchr(meta, quoted[i].latin1()) != 0 ) + quoted.insert( i++, "\\" ); + i++; + } + return quoted; +} + +void QRegExp::compile( bool caseSensitive ) +{ + derefEngine( eng, priv->rxpattern ); +#ifndef QT_NO_REGEXP_WILDCARD + if ( priv->wc ) + priv->rxpattern = wc2rx( priv->pattern ); + else +#endif + priv->rxpattern = priv->pattern.isNull() ? QString::fromLatin1( "" ) + : priv->pattern; + eng = newEngine( priv->rxpattern, caseSensitive ); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = QString(); + priv->capturedCache.clear(); +#endif + priv->captured.detach(); + priv->captured.fill( -1, 2 + 2 * eng->numCaptures() ); +} + +int QRegExp::caretIndex( int offset, CaretMode caretMode ) +{ + if ( caretMode == CaretAtZero ) { + return 0; + } else if ( caretMode == CaretAtOffset ) { + return offset; + } else { // CaretWontMatch + return -1; + } +} + +#endif // QT_NO_REGEXP diff --git a/qmake/tools/qsemaphore_unix.cpp b/qmake/tools/qsemaphore_unix.cpp new file mode 100644 index 0000000..fcf28da --- a/dev/null +++ b/qmake/tools/qsemaphore_unix.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** $Id$ +** +** QSemaphore class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#if defined(QT_THREAD_SUPPORT) + +#include "qsemaphore.h" +#include "qmutex.h" +#include "qwaitcondition.h" + + +/*! + \class QSemaphore qsemaphore.h + \threadsafe + \brief The QSemaphore class provides a robust integer semaphore. + + \ingroup thread + \ingroup environment + + A QSemaphore can be used to serialize thread execution, in a + similar way to a QMutex. A semaphore differs from a mutex, in + that a semaphore can be accessed by more than one thread at a + time. + + For example, suppose we have an application that stores data in a + large tree structure. The application creates 10 threads + (commonly called a thread pool) to perform searches on the tree. + When the application searches the tree for some piece of data, it + uses one thread per base node to do the searching. A semaphore + could be used to make sure that two threads don't try to search + the same branch of the tree at the same time. + + A non-computing example of a semaphore would be dining at a + restuarant. A semaphore is initialized to have a maximum count + equal to the number of chairs in the restuarant. As people + arrive, they want a seat. As seats are filled, the semaphore is + accessed, once per person. As people leave, the access is + released, allowing more people to enter. If a party of 10 people + want to be seated, but there are only 9 seats, those 10 people + will wait, but a party of 4 people would be seated (taking the + available seats to 5, making the party of 10 people wait longer). + + When a semaphore is created it is given a number which is the + maximum number of concurrent accesses it will permit. This amount + may be changed using operator++(), operator--(), operator+=() and + operator-=(). The number of accesses allowed is retrieved with + available(), and the total number with total(). Note that the + incrementing functions will block if there aren't enough available + accesses. Use tryAccess() if you want to acquire accesses without + blocking. +*/ + + +class QSemaphorePrivate { +public: + QSemaphorePrivate(int); + + QMutex mutex; + QWaitCondition cond; + + int value, max; +}; + + +QSemaphorePrivate::QSemaphorePrivate(int m) + : mutex(FALSE), value(0), max(m) +{ +} + + +/*! + Creates a new semaphore. The semaphore can be concurrently + accessed at most \a maxcount times. +*/ +QSemaphore::QSemaphore(int maxcount) +{ + d = new QSemaphorePrivate(maxcount); +} + + +/*! + Destroys the semaphore. + + \warning If you destroy a semaphore that has accesses in use the + resultant behavior is undefined. +*/ +QSemaphore::~QSemaphore() +{ + delete d; +} + + +/*! + Postfix ++ operator. + + Try to get access to the semaphore. If \l available() == 0, this + call will block until it can get access, i.e. until available() \> + 0. +*/ +int QSemaphore::operator++(int) +{ + int ret; + + d->mutex.lock(); + + while (d->value >= d->max) + d->cond.wait(&(d->mutex)); + + ++(d->value); + if (d->value > d->max) d->value = d->max; + ret = d->value; + + d->mutex.unlock(); + + return ret; +} + + +/*! + Postfix -- operator. + + Release access of the semaphore. This wakes all threads waiting + for access to the semaphore. +*/ +int QSemaphore::operator--(int) +{ + int ret; + + d->mutex.lock(); + + --(d->value); + if (d->value < 0) d->value = 0; + ret = d->value; + + d->cond.wakeAll(); + d->mutex.unlock(); + + return ret; +} + + +/*! + Try to get access to the semaphore. If \l available() \< \a n, this + call will block until it can get all the accesses it wants, i.e. + until available() \>= \a n. +*/ +int QSemaphore::operator+=(int n) +{ + int ret; + + d->mutex.lock(); + + while (d->value + n > d->max) + d->cond.wait(&(d->mutex)); + + d->value += n; + +#ifdef QT_CHECK_RANGE + if (d->value > d->max) { + qWarning("QSemaphore::operator+=: attempt to allocate more resources than available"); + d->value = d->max; + } +#endif + + ret = d->value; + + d->mutex.unlock(); + + return ret; +} + + +/*! + Release \a n accesses to the semaphore. +*/ +int QSemaphore::operator-=(int n) +{ + int ret; + + d->mutex.lock(); + + d->value -= n; + +#ifdef QT_CHECK_RANGE + if (d->value < 0) { + qWarning("QSemaphore::operator-=: attempt to deallocate more resources than taken"); + d->value = 0; + } +#endif + + ret = d->value; + + d->cond.wakeOne(); + d->mutex.unlock(); + + return ret; +} + + +/*! + Returns the number of accesses currently available to the + semaphore. +*/ +int QSemaphore::available() const { + int ret; + + d->mutex.lock(); + ret = d->max - d->value; + d->mutex.unlock(); + + return ret; +} + + +/*! + Returns the total number of accesses to the semaphore. +*/ +int QSemaphore::total() const { + int ret; + + d->mutex.lock(); + ret = d->max; + d->mutex.unlock(); + + return ret; +} + + +/*! + Try to get access to the semaphore. If \l available() \< \a n, this + function will return FALSE immediately. If \l available() \>= \a n, + this function will take \a n accesses and return TRUE. This + function does \e not block. +*/ +bool QSemaphore::tryAccess(int n) +{ + if (! d->mutex.tryLock()) + return FALSE; + + if (d->value + n > d->max) { + d->mutex.unlock(); + return FALSE; + } + + d->value += n; + +#ifdef QT_CHECK_RANGE + if (d->value > d->max) { + qWarning("QSemaphore::operator+=: attempt to allocate more resources than available"); + d->value = d->max; + } +#endif + + d->mutex.unlock(); + + return TRUE; +} + +#endif // QT_THREAD_SUPPORT diff --git a/qmake/tools/qsettings.cpp b/qmake/tools/qsettings.cpp new file mode 100644 index 0000000..5de105c --- a/dev/null +++ b/qmake/tools/qsettings.cpp @@ -0,0 +1,1955 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QSettings class +** +** Created: 2000.06.26 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +// POSIX Large File Support redefines open -> open64 +static inline int qt_open( const char *pathname, int flags, mode_t mode ) +{ return ::open( pathname, flags, mode ); } +#if defined(open) +# undef open +#endif + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#include "qsettings.h" + +#ifndef QT_NO_SETTINGS + +#include "qdir.h" +#include "qfile.h" +#include "qfileinfo.h" +#include "qmap.h" +#include "qtextstream.h" +#include "qregexp.h" +#include <private/qsettings_p.h> +#include <errno.h> + +/*! + \class QSettings + \brief The QSettings class provides persistent platform-independent application settings. + + \ingroup io + \ingroup misc + \mainclass + + On Unix systems, QSettings uses text files to store settings. On Windows + systems, QSettings uses the system registry. On Mac OS X, QSettings will + behave as on Unix, and store to text files. + + Each setting comprises an identifying key and the data associated with + the key. A key is a unicode string which consists of \e two or more + subkeys. A subkey is a slash, '/', followed by one or more unicode + characters (excluding slashes, newlines, carriage returns and equals, + '=', signs). The associated data, called the entry or value, may be a + boolean, an integer, a double, a string or a list of strings. Entry + strings may contain any unicode characters. + + If you want to save and restore the entire desktop's settings, i.e. + which applications are running, use QSettings to save the settings + for each individual application and QSessionManager to save the + desktop's session. + + Example settings: + \code + /MyCompany/MyApplication/background color + /MyCompany/MyApplication/foreground color + /MyCompany/MyApplication/geometry/x + /MyCompany/MyApplication/geometry/y + /MyCompany/MyApplication/geometry/width + /MyCompany/MyApplication/geometry/height + /MyCompany/MyApplication/recent files/1 + /MyCompany/MyApplication/recent files/2 + /MyCompany/MyApplication/recent files/3 + \endcode + Each line above is a complete key, made up of subkeys. + + A typical usage pattern for application startup: + \code + QSettings settings; + settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); + // No search path needed for Unix; see notes further on. + // Use default values if the keys don't exist + QString bgColor = settings.readEntry( "/MyApplication/background color", "white" ); + int width = settings.readNumEntry( "/MyApplication/geometry/width", 640 ); + // ... + \endcode + + A typical usage pattern for application exit or 'save preferences': + \code + QSettings settings; + settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); + // No search path needed for Unix; see notes further on. + settings.writeEntry( "/MyApplication/background color", bgColor ); + settings.writeEntry( "/MyApplication/geometry/width", width ); + // ... + \endcode + + You can get a list of entry-holding keys by calling entryList(), and + a list of key-holding keys using subkeyList(). + + \code + QStringList keys = entryList( "/MyApplication" ); + // keys contains 'background color' and 'foreground color'. + + QStringList keys = entryList( "/MyApplication/recent files" ); + // keys contains '1', '2' and '3'. + + QStringList subkeys = subkeyList( "/MyApplication" ); + // subkeys contains 'geometry' and 'recent files' + + QStringList subkeys = subkeyList( "/MyApplication/recent files" ); + // subkeys is empty. + \endcode + + If you wish to use a different search path call insertSearchPath() + as often as necessary to add your preferred paths. Call + removeSearchPath() to remove any unwanted paths. + + Since settings for Windows are stored in the registry there are size + limits as follows: + \list + \i A subkey may not exceed 255 characters. + \i An entry's value may not exceed 16,300 characters. + \i All the values of a key (for example, all the 'recent files' + subkeys values), may not exceed 65,535 characters. + \endlist + + These limitations are not enforced on Unix. + + \section1 Notes for Unix Applications + + There is no universally accepted place for storing application + settings under Unix. In the examples the settings file will be + searched for in the following directories: + \list 1 + \i INSTALL/etc/settings + \i /opt/MyCompany/share/etc + \i /opt/MyCompany/share/MyApplication/etc + \i $HOME/.qt + \endlist + When reading settings the files are searched in the order shown + above, with later settings overriding earlier settings. Files for + which the user doesn't have read permission are ignored. When saving + settings QSettings works in the order shown above, writing + to the first settings file for which the user has write permission. + (\c INSTALL is the directory where Qt was installed. This can be + modified by using the configure script's -prefix argument ) + + If you want to put the settings in a particular place in the + filesystem you could do this: + \code + settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" ); + \endcode + + But in practice you may prefer not to use a search path for Unix. + For example the following code: + \code + settings.writeEntry( "/MyApplication/geometry/width", width ); + \endcode + will end up writing the "geometry/width" setting to the file + \c{$HOME/.qt/myapplicationrc} (assuming that the application is + being run by an ordinary user, i.e. not by root). + + For cross-platform applications you should ensure that the Windows + size limitations are not exceeded. +*/ + +/*! + \enum QSettings::System + + \value Mac Macintosh execution environments + \value Unix Mac OS X, Unix, Linux and Unix-like execution environments + \value Windows Windows execution environments +*/ + +/*! + \enum QSettings::Format + + \value Native Store the settings in a platform dependent location + \value Ini Store the settings in a text file +*/ + +/*! + \enum QSettings::Scope + + \value Global Save settings as global as possible + \value User Save settings in user space +*/ + +#if defined(Q_OS_UNIX) +typedef int HANDLE; +#define Q_LOCKREAD F_RDLCK +#define Q_LOCKWRITE F_WRLCK +/* + Locks the file specified by name. The lockfile is created as a + hidden file in the same directory as the target file, with .lock + appended to the name. For example, "/etc/settings/onerc" uses a + lockfile named "/etc/settings/.onerc.lock". The type argument + controls the type of the lock, it can be either F_RDLCK for a read + lock, or F_WRLCK for a write lock. + + A file descriptor for the lock file is returned, and should be + closed with closelock() when the lock is no longer needed. + */ +static HANDLE openlock( const QString &name, int type ) +{ + QFileInfo info( name ); + // lockfile should be hidden, and never removed + QString lockfile = info.dirPath() + "/." + info.fileName() + ".lock"; + + // open the lockfile + HANDLE fd = qt_open( QFile::encodeName( lockfile ), + O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); + + if ( fd < 0 ) { + // failed to open the lock file, most likely because of permissions + return fd; + } + + struct flock fl; + fl.l_type = type; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + if ( fcntl( fd, F_SETLKW, &fl ) == -1 ) { + // the lock failed, so we should fail silently, so that people + // using filesystems that do not support locking don't see + // numerous warnings about a failed lock + close( fd ); + fd = -1; + } + + return fd; +} + +/* + Closes the lock file specified by fd. fd is the file descriptor + returned by the openlock() function. +*/ +static void closelock( HANDLE fd ) +{ + if ( fd < 0 ) { + // the lock file is not open + return; + } + + struct flock fl; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + // ignore the return value, so that the unlock fails silently + (void) fcntl( fd, F_SETLKW, &fl ); + + close( fd ); +} +#elif defined(Q_WS_WIN) +#define Q_LOCKREAD 1 +#define Q_LOCKWRITE 2 + +static HANDLE openlock( const QString &name, int /*type*/ ) +{ + if ( !QFile::exists( name ) ) + return 0; + + return 0; + + HANDLE fd = 0; + + QT_WA( { + fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + } , { + fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + } ); + + if ( !LockFile( fd, 0, 0, -1, -1 ) ) { +#ifdef QT_CHECK_STATE + qWarning( "QSettings: openlock failed!" ); +#endif + } + return fd; +} + +void closelock( HANDLE fd ) +{ + if ( !fd ) + return; + + if ( !UnlockFile( fd, 0, 0, -1, -1 ) ) { +#ifdef QT_CHECK_STATE + qWarning( "QSettings: closelock failed!"); +#endif + } + CloseHandle( fd ); +} +#endif + + +QSettingsGroup::QSettingsGroup() + : modified(FALSE) +{ +} + + + + +void QSettingsHeading::read(const QString &filename) +{ + if (! QFileInfo(filename).exists()) + return; + + HANDLE lockfd = openlock( filename, Q_LOCKREAD ); + + QFile file(filename); + if (! file.open(IO_ReadOnly)) { +#if defined(QT_CHECK_STATE) + qWarning("QSettings: failed to open file '%s'", filename.latin1()); +#endif + return; + } + + git = end(); + + QTextStream stream(&file); + stream.setEncoding(QTextStream::UnicodeUTF8); + while (! stream.atEnd()) + parseLine(stream); + + git = end(); + + file.close(); + + closelock( lockfd ); +} + + +void QSettingsHeading::parseLine(QTextStream &stream) +{ + QString line = stream.readLine(); + if (line.isEmpty()) + // empty line... we'll allow it + return; + + if (line[0] == QChar('#')) + // commented line + return; + + if (line[0] == QChar('[')) { + QString gname = line; + + gname = gname.remove(0, 1); + if (gname[(int)gname.length() - 1] == QChar(']')) + gname = gname.remove(gname.length() - 1, 1); + + git = find(gname); + if (git == end()) + git = replace(gname, QSettingsGroup()); + } else { + if (git == end()) { +#if defined(QT_CHECK_STATE) + qWarning("QSettings: line '%s' out of group", line.latin1()); +#endif + return; + } + + int i = line.find('='); + if (i == -1) { +#if defined(QT_CHECK_STATE) + qWarning("QSettings: malformed line '%s' in group '%s'", + line.latin1(), git.key().latin1()); +#endif + return; + } else { + QString key, value; + key = line.left(i); + value = ""; + bool esc=TRUE; + i++; + while (esc) { + esc = FALSE; + for ( ; i < (int)line.length(); i++ ) { + if ( esc ) { + if ( line[i] == 'n' ) + value.append('\n'); // escaped newline + else if ( line[i] == '0' ) + value = QString::null; // escaped empty string + else + value.append(line[i]); + esc = FALSE; + } else if ( line[i] == '\\' ) + esc = TRUE; + else + value.append(line[i]); + } + if ( esc ) { + // Backwards-compatiblity... + // still escaped at EOL - manually escaped "newline" + if (stream.atEnd()) { +#if defined(QT_CHECK_STATE) + qWarning("QSettings: reached end of file, expected continued line"); +#endif + break; + } + value.append('\n'); + line = stream.readLine(); + i = 0; + } + } + + (*git).insert(key, value); + } + } +} + +#ifdef Q_WS_WIN // for homedirpath reading from registry +#include "qt_windows.h" +#include "qlibrary.h" + +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a // <user name>\Application Data +#endif +#ifndef CSIDL_COMMON_APPDATA +#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data +#endif + +#endif + +QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) + : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE) +{ +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( format != QSettings::Ini ) + return; +#endif + + QString appSettings(QDir::homeDirPath() + "/.qt/"); + QString defPath; +#ifdef Q_WS_WIN +#ifdef Q_OS_TEMP + TCHAR path[MAX_PATH]; + SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); + appSettings = QString::fromUcs2( path ); + SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); + defPath = QString::fromUcs2( path ); +#else + QLibrary library( "shell32" ); + library.setAutoUnload( FALSE ); + QT_WA( { + typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); + GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" ); + if ( SHGetSpecialFolderPath ) { + TCHAR path[MAX_PATH]; + SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); + appSettings = QString::fromUcs2( (ushort*)path ); + SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); + defPath = QString::fromUcs2( (ushort*)path ); + } + } , { + typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); + GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" ); + if ( SHGetSpecialFolderPath ) { + char path[MAX_PATH]; + SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); + appSettings = QString::fromLocal8Bit( path ); + SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); + defPath = QString::fromLocal8Bit( path ); + } + } ); +#endif // Q_OS_TEMP +#else +// for now +#define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings" + + defPath = qInstallPath(); + defPath += QSETTINGS_DEFAULT_PATH_SUFFIX; +#endif + QDir dir(appSettings); + if (! dir.exists()) { + if (! dir.mkdir(dir.path())) +#if defined(QT_CHECK_STATE) + qWarning("QSettings: error creating %s", dir.path().latin1()); +#endif + } + + if ( !!defPath ) + searchPaths.append(defPath); + searchPaths.append(dir.path()); +} + +QSettingsPrivate::~QSettingsPrivate() +{ +} + +QSettingsGroup QSettingsPrivate::readGroup() +{ + QSettingsHeading hd; + QSettingsGroup grp; + + QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); + if (headingsit != headings.end()) + hd = *headingsit; + + QSettingsHeading::Iterator grpit = hd.find(group); + if (grpit == hd.end()) { + QStringList::Iterator it = searchPaths.begin(); + while (it != searchPaths.end()) { + QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); + QString fn((*it++) + "/" + filebase + "rc"); + if (! hd.contains(fn + "cached")) { + hd.read(fn); + hd.insert(fn + "cached", QSettingsGroup()); + } + } + + headings.replace(heading, hd); + + grpit = hd.find(group); + if (grpit != hd.end()) + grp = *grpit; + } else if (hd.count() != 0) + grp = *grpit; + + return grp; +} + + +void QSettingsPrivate::removeGroup(const QString &key) +{ + QSettingsHeading hd; + QSettingsGroup grp; + bool found = FALSE; + + QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); + if (headingsit != headings.end()) + hd = *headingsit; + + QSettingsHeading::Iterator grpit = hd.find(group); + if (grpit == hd.end()) { + QStringList::Iterator it = searchPaths.begin(); + while (it != searchPaths.end()) { + QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); + QString fn((*it++) + "/" + filebase + "rc"); + if (! hd.contains(fn + "cached")) { + hd.read(fn); + hd.insert(fn + "cached", QSettingsGroup()); + } + } + + headings.replace(heading, hd); + + grpit = hd.find(group); + if (grpit != hd.end()) { + found = TRUE; + grp = *grpit; + } + } else if (hd.count() != 0) { + found = TRUE; + grp = *grpit; + } + + if (found) { + grp.remove(key); + + if (grp.count() > 0) + hd.replace(group, grp); + else + hd.remove(group); + + if (hd.count() > 0) + headings.replace(heading, hd); + else + headings.remove(heading); + + modified = TRUE; + } +} + + +void QSettingsPrivate::writeGroup(const QString &key, const QString &value) +{ + QSettingsHeading hd; + QSettingsGroup grp; + + QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); + if (headingsit != headings.end()) + hd = *headingsit; + + QSettingsHeading::Iterator grpit = hd.find(group); + if (grpit == hd.end()) { + QStringList::Iterator it = searchPaths.begin(); + while (it != searchPaths.end()) { + QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); + QString fn((*it++) + "/" + filebase + "rc"); + if (! hd.contains(fn + "cached")) { + hd.read(fn); + hd.insert(fn + "cached", QSettingsGroup()); + } + } + + headings.replace(heading, hd); + + grpit = hd.find(group); + if (grpit != hd.end()) + grp = *grpit; + } else if (hd.count() != 0) + grp = *grpit; + + grp.modified = TRUE; + grp.replace(key, value); + hd.replace(group, grp); + headings.replace(heading, hd); + + modified = TRUE; +} + + +QDateTime QSettingsPrivate::modificationTime() +{ + QSettingsHeading hd = headings[heading]; + QSettingsGroup grp = hd[group]; + + QDateTime datetime; + + QStringList::Iterator it = searchPaths.begin(); + while (it != searchPaths.end()) { + QFileInfo fi((*it++) + "/" + heading + "rc"); + if (fi.exists() && fi.lastModified() > datetime) + datetime = fi.lastModified(); + } + + return datetime; +} + +static bool verifyKey( const QString &key ) +{ + if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) ) + return FALSE; + return TRUE; +} + +static inline QString groupKey( const QString &group, const QString &key ) +{ + if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) + return group + key; + return group + "/" + key; +} + +/*! + Inserts \a path into the settings search path. The semantics of \a + path depends on the system \a s. + + When \a s is \e Windows and the execution environment is \e not + Windows the function does nothing. Similarly when \a s is \e Unix and + the execution environment is \e not Unix the function does nothing. + + When \a s is \e Windows, and the execution environment is Windows, the + search path list will be used as the first subfolder of the "Software" + folder in the registry. + + When reading settings the folders are searched forwards from the + first folder (listed below) to the last, returning the first + settings found, and ignoring any folders for which the user doesn't + have read permission. + \list 1 + \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication + \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication + \i HKEY_CURRENT_USER/Software/MyApplication + \i HKEY_LOCAL_MACHINE/Software/MyApplication + \endlist + + \code + QSettings settings; + settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); + settings.writeEntry( "/MyApplication/Tip of the day", TRUE ); + \endcode + The code above will write the subkey "Tip of the day" into the \e + first of the registry folders listed below that is found and for + which the user has write permission. + \list 1 + \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication + \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication + \i HKEY_LOCAL_MACHINE/Software/MyApplication + \i HKEY_CURRENT_USER/Software/MyApplication + \endlist + If a setting is found in the HKEY_CURRENT_USER space, this setting + is overwritten independently of write permissions in the + HKEY_LOCAL_MACHINE space. + + When \a s is \e Unix, and the execution environment is Unix, the + search path list will be used when trying to determine a suitable + filename for reading and writing settings files. By default, there are + two entries in the search path: + + \list 1 + \i INSTALL/etc - where \c INSTALL is the directory where Qt was installed. + \i $HOME/.qt/ - where \c $HOME is the user's home directory. + \endlist + + All insertions into the search path will go before $HOME/.qt/. + For example: + \code + QSettings settings; + settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/etc" ); + settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/MyApplication/etc" ); + // ... + \endcode + Will result in a search path of: + \list 1 + \i INSTALL/etc + \i /opt/MyCompany/share/etc + \i /opt/MyCompany/share/MyApplication/etc + \i $HOME/.qt + \endlist + When reading settings the files are searched in the order shown + above, with later settings overriding earlier settings. Files for + which the user doesn't have read permission are ignored. When saving + settings QSettings works in the order shown above, writing + to the first settings file for which the user has write permission. + + Settings under Unix are stored in files whose names are based on the + first subkey of the key (not including the search path). The algorithm + for creating names is essentially: lowercase the first subkey, replace + spaces with underscores and add 'rc', e.g. + <tt>/MyCompany/MyApplication/background color</tt> will be stored in + <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of + the search path). + + \sa removeSearchPath() + +*/ +void QSettings::insertSearchPath( System s, const QString &path) +{ +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) { + d->sysInsertSearchPath( s, path ); + return; + } +#endif + + if ( !verifyKey( path ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); +#endif + return; + } + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd && s != Unix ) { +#else + if ( s != Unix ) { +#endif +#ifdef Q_OS_MAC + if(s != Mac) //mac is respected on the mac as well +#endif + return; + } + + QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last()); + if (it != d->searchPaths.end()) { + d->searchPaths.insert(it, path); + } +} + + +/*! + Removes all occurrences of \a path (using exact matching) from the + settings search path for system \a s. Note that the default search + paths cannot be removed. + + \sa insertSearchPath() +*/ +void QSettings::removeSearchPath( System s, const QString &path) +{ + if ( !verifyKey( path ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); +#endif + return; + } + +#ifdef Q_WS_WIN + if ( d->sysd ) { + d->sysRemoveSearchPath( s, path ); + return; + } +#endif +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd && s != Unix ) { +#else + if ( s != Unix ) { +#endif +#ifdef Q_OS_MAC + if(s != Mac) //mac is respected on the mac as well +#endif + return; + } + + if (path == d->searchPaths.first() || path == d->searchPaths.last()) + return; + + d->searchPaths.remove(path); +} + + +/*! + Creates a settings object. +*/ +QSettings::QSettings() +{ + d = new QSettingsPrivate( Native ); + Q_CHECK_PTR(d); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + d->sysd = 0; + d->sysInit(); +#endif +} + +/*! + Creates a settings object. If \a format is 'Ini' the settings will + be stored in a text file, using the Unix strategy (see above). If \a format + is 'Native', the settings will be stored in a platform specific way + (ie. the Windows registry). +*/ +QSettings::QSettings( Format format ) +{ + d = new QSettingsPrivate( format ); + Q_CHECK_PTR(d); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + d->sysd = 0; + if ( format == Native ) + d->sysInit(); +#else + Q_UNUSED(format); +#endif +} + +/*! + Destroys the settings object. All modifications made to the settings + will automatically be saved. + +*/ +QSettings::~QSettings() +{ + sync(); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + d->sysClear(); +#endif + + delete d; +} + + +/*! \internal + Writes all modifications to the settings to disk. If any errors are + encountered, this function returns FALSE, otherwise it will return TRUE. +*/ +bool QSettings::sync() +{ +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysSync(); +#endif + if (! d->modified) + // fake success + return TRUE; + + bool success = TRUE; + QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); + + while (it != d->headings.end()) { + // determine filename + QSettingsHeading hd(*it); + QSettingsHeading::Iterator hdit = hd.begin(); + QFile file; + + QStringList::Iterator pit = d->searchPaths.begin(); + while (pit != d->searchPaths.end()) { + QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_"); + QFileInfo di(*pit); + QFileInfo fi((*pit++) + "/" + filebase + "rc"); + + if ((fi.exists() && fi.isFile() && fi.isWritable()) || + (! fi.exists() && di.isDir() && di.isWritable())) { + file.setName(fi.filePath()); + break; + } + } + + it++; + + if (file.name().isNull() || file.name().isEmpty()) { + +#ifdef QT_CHECK_STATE + qWarning("QSettings::sync: filename is null/empty"); +#endif // QT_CHECK_STATE + + success = FALSE; + continue; + } + + HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE ); + + if (! file.open(IO_WriteOnly)) { + +#ifdef QT_CHECK_STATE + qWarning("QSettings::sync: failed to open '%s' for writing", + file.name().latin1()); +#endif // QT_CHECK_STATE + + success = FALSE; + continue; + } + + // spew to file + QTextStream stream(&file); + stream.setEncoding(QTextStream::UnicodeUTF8); + + while (hdit != hd.end()) { + if ((*hdit).count() > 0) { + stream << "[" << hdit.key() << "]" << endl; + + QSettingsGroup grp(*hdit); + QSettingsGroup::Iterator grpit = grp.begin(); + + while (grpit != grp.end()) { + QString v = grpit.data(); + if ( v.isNull() ) { + v = "\\0"; // escape null string + } else { + v.replace("\\", "\\\\"); // escape backslash + v.replace("\n", "\\n"); // escape newlines + } + + stream << grpit.key() << "=" << v << endl; + grpit++; + } + + stream << endl; + } + + hdit++; + } + + if (file.status() != IO_Ok) { + +#ifdef QT_CHECK_STATE + qWarning("QSettings::sync: error at end of write"); +#endif // QT_CHECK_STATE + + success = FALSE; + } + + file.close(); + + closelock( lockfd ); + } + + d->modified = FALSE; + + return success; +} + + +/*! + \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const + + Reads the entry specified by \a key, and returns a bool, or the + default value, \a def, if the entry couldn't be read. + If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE + otherwise. + + \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry() +*/ + +/*! + \internal +*/ +bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + if ( ok ) + *ok = FALSE; + + return def; + } + + QString theKey = groupKey( group(), key ); +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysReadBoolEntry( theKey, def, ok ); +#endif + + QString value = readEntry( theKey, ( def ? "true" : "false" ), ok ); + + if (value.lower() == "true") + return TRUE; + else if (value.lower() == "false") + return FALSE; + else if (value == "1") + return TRUE; + else if (value == "0") + return FALSE; + + if (! value.isEmpty()) + qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'", + value.latin1()); + if ( ok ) + *ok = FALSE; + return def; +} + + +/*! + \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const + + Reads the entry specified by \a key, and returns a double, or the + default value, \a def, if the entry couldn't be read. + If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE + otherwise. + + \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry() +*/ + +/*! + \internal +*/ +double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + if ( ok ) + *ok = FALSE; + + return def; + } + + QString theKey = groupKey( group(), key ); +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysReadDoubleEntry( theKey, def, ok ); +#endif + + QString value = readEntry( theKey, QString::number(def), ok ); + bool conv_ok; + double retval = value.toDouble( &conv_ok ); + if ( conv_ok ) + return retval; + if ( ! value.isEmpty() ) + qWarning( "QSettings::readDoubleEntry: '%s' is not a number", + value.latin1() ); + if ( ok ) + *ok = FALSE; + return def; +} + + +/*! + \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const + + Reads the entry specified by \a key, and returns an integer, or the + default value, \a def, if the entry couldn't be read. + If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE + otherwise. + + \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() +*/ + +/*! + \internal +*/ +int QSettings::readNumEntry(const QString &key, int def, bool *ok ) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + if ( ok ) + *ok = FALSE; + return def; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysReadNumEntry( theKey, def, ok ); +#endif + + QString value = readEntry( theKey, QString::number( def ), ok ); + bool conv_ok; + int retval = value.toInt( &conv_ok ); + if ( conv_ok ) + return retval; + if ( ! value.isEmpty() ) + qWarning( "QSettings::readNumEntry: '%s' is not a number", + value.latin1() ); + if ( ok ) + *ok = FALSE; + return def; +} + + +/*! + \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const + + Reads the entry specified by \a key, and returns a QString, or the + default value, \a def, if the entry couldn't be read. + If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE + otherwise. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() +*/ + +/*! + \internal +*/ +QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + if ( ok ) + *ok = FALSE; + + return def; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysReadEntry( theKey, def, ok ); +#endif + + if ( ok ) // no, everything is not ok + *ok = FALSE; + + QString realkey; + + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 2) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + if ( ok ) + *ok = FALSE; + return def; + } + + if (list.count() == 2) { + d->heading = list[0]; + d->group = "General"; + realkey = list[1]; + } else { + d->heading = list[0]; + d->group = list[1]; + + // remove the group from the list + list.remove(list.at(1)); + // remove the heading from the list + list.remove(list.at(0)); + + realkey = list.join("/"); + } + } else + realkey = theKey; + + QSettingsGroup grp = d->readGroup(); + QString retval = grp[realkey]; + if ( retval.isNull() ) + retval = def; + else if ( ok ) // everything is ok + *ok = TRUE; + return retval; +} + + +#if !defined(Q_NO_BOOL_TYPE) +/*! + Writes the boolean entry \a value into key \a key. The \a key is + created if it doesn't exist. Any previous value is overwritten by \a + value. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise TRUE is returned. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, bool value) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysWriteEntry( theKey, value ); +#endif + QString s(value ? "true" : "false"); + return writeEntry(theKey, s); +} +#endif + + +/*! + \overload + Writes the double entry \a value into key \a key. The \a key is + created if it doesn't exist. Any previous value is overwritten by \a + value. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise TRUE is returned. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, double value) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysWriteEntry( theKey, value ); +#endif + QString s(QString::number(value)); + return writeEntry(theKey, s); +} + + +/*! + \overload + Writes the integer entry \a value into key \a key. The \a key is + created if it doesn't exist. Any previous value is overwritten by \a + value. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise TRUE is returned. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, int value) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysWriteEntry( theKey, value ); +#endif + QString s(QString::number(value)); + return writeEntry(theKey, s); +} + + +/*! + \internal + + Writes the entry specified by \a key with the string-literal \a value, + replacing any previous setting. If \a value is zero-length or null, the + entry is replaced by an empty setting. + + \e NOTE: This function is provided because some compilers use the + writeEntry (const QString &, bool) overload for this code: + writeEntry ("/foo/bar", "baz") + + If an error occurs, this functions returns FALSE and the object is left + unchanged. + + \sa readEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, const char *value) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + + return writeEntry(theKey, QString(value)); +} + + +/*! + \overload + Writes the string entry \a value into key \a key. The \a key is + created if it doesn't exist. Any previous value is overwritten by \a + value. If \a value is an empty string or a null string the key's + value will be an empty string. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise TRUE is returned. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, const QString &value) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysWriteEntry( theKey, value ); +#endif + // NOTE: we *do* allow value to be a null/empty string + + QString realkey; + + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 2) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + + return FALSE; + } + + if (list.count() == 2) { + d->heading = list[0]; + d->group = "General"; + realkey = list[1]; + } else { + d->heading = list[0]; + d->group = list[1]; + + // remove the group from the list + list.remove(list.at(1)); + // remove the heading from the list + list.remove(list.at(0)); + + realkey = list.join("/"); + } + } else + realkey = theKey; + + d->writeGroup(realkey, value); + return TRUE; +} + + +/*! + Removes the entry specified by \a key. + + Returns TRUE if the entry existed and was removed; otherwise returns FALSE. + + \sa readEntry(), writeEntry() +*/ +bool QSettings::removeEntry(const QString &key) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return FALSE; + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysRemoveEntry( theKey ); +#endif + + QString realkey; + + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 2) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + + return FALSE; + } + + if (list.count() == 2) { + d->heading = list[0]; + d->group = "General"; + realkey = list[1]; + } else { + d->heading = list[0]; + d->group = list[1]; + + // remove the group from the list + list.remove(list.at(1)); + // remove the heading from the list + list.remove(list.at(0)); + + realkey = list.join("/"); + } + } else + realkey = theKey; + + d->removeGroup(realkey); + return TRUE; +} + + +/*! + Returns a list of the keys which contain entries under \a key. Does \e + not return any keys that contain keys. + + Example settings: + \code + /MyCompany/MyApplication/background color + /MyCompany/MyApplication/foreground color + /MyCompany/MyApplication/geometry/x + /MyCompany/MyApplication/geometry/y + /MyCompany/MyApplication/geometry/width + /MyCompany/MyApplication/geometry/height + \endcode + \code + QStringList keys = entryList( "/MyCompany/MyApplication" ); + \endcode + \c keys contains 'background color' and 'foreground color'. It does + not contain 'geometry' because this key contains keys not entries. + + To access the geometry values could either use subkeyList() to read + the keys and then read each entry, or simply read each entry + directly by specifying its full key, e.g. + "/MyCompany/MyApplication/geometry/y". + + \sa subkeyList() +*/ +QStringList QSettings::entryList(const QString &key) const +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); +#endif + return QStringList(); + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysEntryList( theKey ); +#endif + + QString realkey; + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 1) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + + return QStringList(); + } + + if (list.count() == 1) { + d->heading = list[0]; + d->group = "General"; + } else { + d->heading = list[0]; + d->group = list[1]; + + // remove the group from the list + list.remove(list.at(1)); + // remove the heading from the list + list.remove(list.at(0)); + + realkey = list.join("/"); + } + } else + realkey = theKey; + + QSettingsGroup grp = d->readGroup(); + QSettingsGroup::Iterator it = grp.begin(); + QStringList ret; + QString itkey; + while (it != grp.end()) { + itkey = it.key(); + it++; + + if ( realkey.length() > 0 ) { + if ( itkey.left( realkey.length() ) != realkey ) + continue; + else + itkey.remove( 0, realkey.length() + 1 ); + } + + if ( itkey.find( '/' ) != -1 ) + continue; + + ret << itkey; + } + + return ret; +} + + +/*! + Returns a list of the keys which contain keys under \a key. Does \e + not return any keys that contain entries. + + Example settings: + \code + /MyCompany/MyApplication/background color + /MyCompany/MyApplication/foreground color + /MyCompany/MyApplication/geometry/x + /MyCompany/MyApplication/geometry/y + /MyCompany/MyApplication/geometry/width + /MyCompany/MyApplication/geometry/height + /MyCompany/MyApplication/recent files/1 + /MyCompany/MyApplication/recent files/2 + /MyCompany/MyApplication/recent files/3 + \endcode + \code + QStringList keys = subkeyList( "/MyCompany/MyApplication" ); + \endcode + \c keys contains 'geometry' and 'recent files'. It does not contain + 'background color' or 'foreground color' because they are keys which + contain entries not keys. To get a list of keys that have values + rather than subkeys use entryList(). + + \sa entryList() +*/ +QStringList QSettings::subkeyList(const QString &key) const +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); +#endif + return QStringList(); + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return d->sysSubkeyList( theKey ); +#endif + + QString realkey; + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 1) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + + return QStringList(); + } + + if (list.count() == 1) { + d->heading = list[0]; + d->group = "General"; + } else { + d->heading = list[0]; + d->group = list[1]; + + // remove the group from the list + list.remove(list.at(1)); + // remove the heading from the list + list.remove(list.at(0)); + + realkey = list.join("/"); + } + } else + realkey = theKey; + + QSettingsGroup grp = d->readGroup(); + QSettingsGroup::Iterator it = grp.begin(); + QStringList ret; + QString itkey; + while (it != grp.end()) { + itkey = it.key(); + it++; + + if ( realkey.length() > 0 ) { + if ( itkey.left( realkey.length() ) != realkey ) + continue; + else + itkey.remove( 0, realkey.length() + 1 ); + } + + int slash = itkey.find( '/' ); + if ( slash == -1 ) + continue; + itkey.truncate( slash ); + + if ( ! ret.contains( itkey ) ) + ret << itkey; + } + + return ret; +} + + +/*! + \internal + + This function returns the time of last modification for \a key. +*/ +QDateTime QSettings::lastModficationTime(const QString &key) +{ + if ( !verifyKey( key ) ) { +#if defined(QT_CHECK_STATE) + qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); +#endif + return QDateTime(); + } + + QString theKey = groupKey( group(), key ); + +#if defined(Q_WS_WIN) || defined(Q_OS_MAC) + if ( d->sysd ) + return QDateTime(); +#endif + + if (theKey[0] == '/') { + // parse our key + QStringList list(QStringList::split('/', theKey)); + + if (list.count() < 2) { +#ifdef QT_CHECK_STATE + qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1()); +#endif // QT_CHECK_STATE + + return QDateTime(); + } + + if (list.count() == 2) { + d->heading = list[0]; + d->group = "General"; + } else { + d->heading = list[0]; + d->group = list[1]; + } + } + + return d->modificationTime(); +} + + +/*! + \overload + + Writes the string list entry \a value into key \a key. The \a key + is created if it doesn't exist. Any previous value is overwritten + by \a value. The list is stored as a sequence of strings separated + by \a separator, so none of the strings in the list should contain + the separator. If the list is empty or null the key's value will + be an empty string. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise returns TRUE. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, const QStringList &value, + const QChar &separator) +{ + QString s(value.join(separator)); + return writeEntry(key, s); +} + +/*! + \overload + + Writes the string list entry \a value into key \a key. The \a key + is created if it doesn't exist. Any previous value is overwritten + by \a value. + + If an error occurs the settings are left unchanged and FALSE is + returned; otherwise returns TRUE. + + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() +*/ +bool QSettings::writeEntry(const QString &key, const QStringList &value) +{ + QString s; + for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) { + QString el = *it; + if ( el.isNull() ) { + el = "^0"; + } else { + el.replace("^", "^^"); + } + s+=el; + s+="^e"; // end of element + } + return writeEntry(key, s); +} + + +/*! + \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const + + Reads the entry specified by \a key as a string. The \a separator + is used to create a QStringList by calling QStringList::split(\a + separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the + key was read, otherwise \a *ok is set to FALSE. + + Note that if you want to iterate over the list, you should iterate + over a copy, e.g. + \code + QStringList list = mySettings.readListEntry( "size", " " ); + QStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() +*/ + +/*! + \internal +*/ +QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) +{ + QString value = readEntry( key, QString::null, ok ); + if ( ok && !*ok ) + return QStringList(); + + return QStringList::split(separator, value); +} + +/*! + \fn QStringList QSettings::readListEntry(const QString &key, bool *ok ) const + Reads the entry specified by \a key as a string. If \a ok is not + 0, \a *ok is set to TRUE if the key was read, otherwise \a *ok is + set to FALSE. + + Note that if you want to iterate over the list, you should iterate + over a copy, e.g. + \code + QStringList list = mySettings.readListEntry( "recentfiles" ); + QStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() +*/ + +/*! + \internal +*/ +QStringList QSettings::readListEntry(const QString &key, bool *ok ) +{ + QString value = readEntry( key, QString::null, ok ); + if ( ok && !*ok ) + return QStringList(); + QStringList l; + QString s; + bool esc=FALSE; + for (int i=0; i<(int)value.length(); i++) { + if ( esc ) { + if ( value[i] == 'e' ) { // end-of-string + l.append(s); + s=""; + } else if ( value[i] == '0' ) { // null string + s=QString::null; + } else { + s.append(value[i]); + } + esc=FALSE; + } else if ( value[i] == '^' ) { + esc = TRUE; + } else { + s.append(value[i]); + if ( i == (int)value.length()-1 ) + l.append(s); + } + } + return l; +} + +/*! + Insert platform-dependent paths from platform-independent information. + + The \a domain should be an Internet domain name + controlled by the producer of the software, eg. Trolltech products + use "trolltech.com". + + The \a product should be the official name of the product. + + The \a scope should be + QSettings::User for user-specific settings, or + QSettings::Global for system-wide settings (generally + these will be read-only to many users). +*/ + +void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) +{ +// On Windows, any trailing ".com(\..*)" is stripped from the domain. The +// Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to +// HKEY_CURRENT_USER. Note that on some installations, not all users can +// write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped +// from the domain. The Global scope corresponds to "/opt" (this would be +// configurable at library build time - eg. to "/usr/local" or "/usr"), +// while the User scope corresponds to $HOME/.*rc. +// Note that on most installations, not all users can write to the System +// scope. +// +// On MacOS X, if there is no "." in domain, append ".com", then reverse the +// order of the elements (Mac OS uses "com.apple.finder" as domain+product). +// The Global scope corresponds to /Library/Preferences/*.plist, while the +// User scope corresponds to ~/Library/Preferences/*.plist. +// Note that on most installations, not all users can write to the System +// scope. + QString actualSearchPath; + int lastDot = domain.findRev( '.' ); + +#if defined(Q_WS_WIN) + actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; + insertSearchPath( Windows, actualSearchPath ); +#elif defined(Q_WS_MAC) + QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; + if ( topLevelDomain.isEmpty() ) + topLevelDomain = "com."; + actualSearchPath = "/" + topLevelDomain + domain.left( lastDot ) + product; + insertSearchPath( Mac, actualSearchPath ); +#else + actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; + insertSearchPath( Unix, actualSearchPath ); +#endif + + d->globalScope = scope == Global; +} + +/*! + Appends \a group to the current key prefix. +*/ +void QSettings::beginGroup( const QString &group ) +{ + d->groupStack.push( group ); + d->groupDirty = TRUE; +} + +/*! + Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone + by a single call to endGroup(). +*/ +void QSettings::endGroup() +{ + d->groupStack.pop(); + d->groupDirty = TRUE; +} + +/*! + Set the current key prefix to the empty string. +*/ +void QSettings::resetGroup() +{ + d->groupStack.clear(); + d->groupDirty = FALSE; + d->groupPrefix = QString::null; +} + +/*! + Returns the current key prefix, or a null string if there is no key prefix set. + + \sa beginGroup(); +*/ +QString QSettings::group() const +{ + if ( d->groupDirty ) { + d->groupDirty = FALSE; + d->groupPrefix = QString::null; + + QValueStack<QString>::Iterator it = d->groupStack.begin(); + while ( it != d->groupStack.end() ) { + QString group = *it; + ++it; + if ( group[0] != '/' ) + group = "/" + group; + d->groupPrefix += group; + } + } + return d->groupPrefix; +} + +#endif diff --git a/qmake/tools/qstring.cpp b/qmake/tools/qstring.cpp new file mode 100644 index 0000000..56df62b --- a/dev/null +++ b/qmake/tools/qstring.cpp @@ -0,0 +1,17867 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of the QString class and related Unicode functions +** +** Created : 920722 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +// Don't define it while compiling this module, or USERS of Qt will +// not be able to link. +#ifdef QT_NO_CAST_ASCII +#undef QT_NO_CAST_ASCII +#endif + +#include "qstring.h" +#include "qregexp.h" +#include "qdatastream.h" +#ifndef QT_NO_TEXTCODEC +#include "qtextcodec.h" +#endif +#include <ctype.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#if defined(Q_WS_WIN) +#include "qt_windows.h" +#endif +#if !defined( QT_NO_COMPONENT ) && !defined( QT_LITE_COMPONENT ) +#include "qcleanuphandler.h" +#endif + + +/* ------------------------------------------------------------------------- + * unicode information + * these tables are generated from the unicode reference file + * ftp://ftp.unicode.org/Public/3.2-Update/UnicodeData.txt + * + * Lars + * ------------------------------------------------------------------------- + */ + +/* Perl script to generate (run perl -x tools/qstring.cpp) + +#!perl + +sub numberize +{ + my(%r, $n, $id); + for $id ( @_ ) { + $i = $id; + $i="" if $i eq "EMPTY"; + $r{$i}=$n++; + } + return %r; +} + + +sub readUnicodeDataLine { + $code = shift @_; + for $n (qw{ + name category combining_class bidi_category + character_decomposition decimal_digit_value digit_value + numeric_value mirrored oldname comment + uppercase lowercase titlecase}) + { + $id = shift @_; + $codes = "${n}_code"; + if ( defined %$codes && defined $$codes{$id} ) { + $id = $$codes{$id}; + } + ${$n}{$code}=$id; + } + $decomp = $character_decomposition{$code}; + if ( length $decomp == 0 ) { + $decomp = "<single>"; + } + if (substr($decomp, 0, 1) ne '<') { + $decomp = "<canonical> " . $decomp; + } + @_ = split(" ", $decomp); + $tag = shift @_; + $tag = $character_decomposition_tag{$tag}; + $decomp = join( ", 0x", @_ ); + $decomp = "0x".$decomp; + $decomposition{$code} = $decomp; + $decomposition_tag{$code} = $tag; + $decomposition_pos{$code} = $position; + $len = scalar(@_); + $decomposition_len{$code} = $len; + +# we use canonical decompositions longer than 1 char +# we exlude Arabic ligatures from the table + if($len > 1 and $tag == 1) { +# ligature to add... + $start = shift @_; + $ligature{$start} = $ligature{$start}." ".$code; + } + +# adjust position + if($len != 0) { + $position += $len + 3; + } +} + + +# Code to integer mappings... +# +%category_code = numberize(qw{ + EMPTY + Mn Mc Me + Nd Nl No + Zs Zl Zp + Cc Cf Cs Co Cn + + Lu Ll Lt Lm Lo + Pc Pd Ps Pe Pi Pf Po + Sm Sc Sk So +}); +%bidi_category_code = numberize(qw{ + L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN}); +%character_decomposition_tag = numberize(qw{ + <single> <canonical> <font> <noBreak> <initial> <medial> + <final> <isolated> <circle> <super> <sub> <vertical> + <wide> <narrow> <small> <square> <compat> <fraction> +}); +%mirrored_code = numberize(qw{N Y}); + +%joining_code = numberize(qw{U D R C}); + +# Read data into hashes... +# +open IN, "UnicodeData.txt"; +$position = 1; +while (<IN>) { + @fields = split /;/; + if ( length($fields[0]) < 5 ) { + if ( $fields[1] =~ /, First>/ ) { + $codeRangeBegin = $fields[0]; + } elsif ( $fields[1] =~ /, Last>/ ) { + for ( $i=hex($codeRangeBegin); $i<=hex($fields[0]); $i+=1 ) { + @fields2 = @fields; + $fields2[0] = sprintf "%lX", $i; + readUnicodeDataLine @fields2; + } + } else { + readUnicodeDataLine @fields; + } + } +} + +open IN2, "ArabicShaping.txt"; +$position = 1; +while (<IN2>) { + @fields = split /;/; + $code = shift @fields; + $dummy = shift @fields; + $join = shift @fields; + $join =~ s/ //g; + $join = $joining_code{$join}; + $joining{$code}=$join; +} + +# Build pages... +# +$rowtable_txt = + "static const Q_UINT8 * const unicode_info[256] = {"; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $category{$code}; + $info = 0 if !defined $info; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $row{$txt}; + if ( !defined $therow ) { + $size+=256; + $therow = "ui_".sprintf("%02X",$row); + $rowtext{$therow} = + "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; + $row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +print "// START OF GENERATED DATA\n\n"; +print "#ifndef QT_NO_UNICODETABLES\n\n"; + +# Print pages... +# +for $r ( sort keys %rowtext ) { + print $rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + +# Build decomposition tables +# +$rowtable_txt = + "static const Q_UINT16 * const decomposition_info[256] = {"; +$table_txt = + "static const Q_UINT16 decomposition_map[] = {\n 0,\n"; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $txt .= "\n " if $cell%8 == 0; + if( $decomposition_tag{$code} != 0 ) { + $txt .= " $decomposition_pos{$code},"; + $table_txt .= " $decomposition_tag{$code},"; + $table_txt .= " 0x$code,"; + $table_txt .= " $decomposition{$code}, 0,\n"; + $size += 2 * $decomposition_len{$code} + 6; + } else { + $txt .= " 0,"; + } + } + $therow = $row{$txt}; + if ( !defined $therow ) { + $size+=512; + $therow = "di_".sprintf("%02X",$row); + $dec_rowtext{$therow} = + "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; + $row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print decomposition tables +# +print "$table_txt\n};\n\n"; +for $r ( sort keys %dec_rowtext ) { + print $dec_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + + +# build ligature tables +# +$size = 0; +$position = 1; +$rowtable_txt = + "static const Q_UINT16 * const ligature_info[256] = {"; +$table_txt = + "static const Q_UINT16 ligature_map[] = {\n 0,\n"; +for $lig_row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$lig_row,$cell); + $txt .= "\n " if $cell%8 == 0; + if( defined $ligature{$code} ) { + $txt .= " $position,"; + @ligature = split(" ", $ligature{$code}); +# we need to sort ligatures according to their length. +# long ones have to come first! + @ligature_sort = sort { $decomposition_len{$b} <=> $decomposition_len{$a} } @ligature; +# now replace each code by its position in +# the decomposition map. + undef(@lig_pos); + for $n (@ligature_sort) { + push(@lig_pos, $decomposition_pos{$n}); + } +# debug info + if( 0 ) { + print "ligatures: $ligature{$code}\n"; + $sort = join(" ", @ligature_sort); + print "sorted : $sort\n"; + } + $lig = join(", ", @lig_pos); + $table_txt .= " $lig, 0,\n"; + $size += 2 * scalar(@ligature) + 2; + $position += scalar(@ligature) + 1; + } else { + $txt .= " 0,"; + } + } + $therow = $lig_row{$txt}; + if ( !defined $therow ) { + $size+=512; + $therow = "li_".sprintf("%02X",$lig_row); + $lig_rowtext{$therow} = + "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; + $lig_row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $lig_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print ligature tables +# +print "$table_txt\n};\n\n"; +for $r ( sort keys %lig_rowtext ) { + print $lig_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + + + +# Build direction/joining/mirrored pages... +# +$rowtable_txt = + "static const Q_UINT8 * const direction_info[256] = {"; +for $dir_row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$dir_row,$cell); + $dir = $bidi_category{$code}; + $dir = 0 if !defined $dir; + $join = $joining{$code}; + $join = 0 if !defined $join; + $mirr = $mirrored{$code}; + $mirr = 0 if !defined $mirr; + $info = $dir + 32*$join + 128*$mirr; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $dir_row{$txt}; + if ( !defined $therow ) { + $size+=256; + $therow = "dir_".sprintf("%02X",$dir_row); + $dir_rowtext{$therow} = + "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; + $dir_row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $dir_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print pages... +# +for $r ( sort keys %dir_rowtext ) { + print $dir_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + +# Build table of combining classes +# +$rowtable_txt = + "static const Q_UINT8 * const combining_info[256] = {"; +for $combining_row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$combining_row,$cell); + $info = $combining_class{$code}; + $info = 0 if !defined $info; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $combining_row{$txt}; + if ( !defined $therow ) { + $size+=256; + $therow = "cmb_".sprintf("%02X",$combining_row); + $combining_rowtext{$therow} = + "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; + $combining_row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $combining_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print pages... +# +for $r ( sort keys %combining_rowtext ) { + print $combining_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + +# Build case info +# +$rowtable_txt = + "static const Q_UINT16 * const case_info[256] = {"; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $uppercase{$code}; + if ( length( $info ) eq 0 ) { + $info = $lowercase{$code}; + } + $info =~ s/^0+//; + if ( length( $info ) eq 0 ) { + $info = "0"; + } else { + $info = "0x".lc($info); + } + if ( length( $info ) ne 1 ) { + $nonzero = 1; + } + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $case_row{$txt}; + if ( !defined $therow && $nonzero ne 0 ) { + $size+=512; + $therow = "case_".sprintf("%02X",$row); + $case_rowtext{$therow} = + "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; + $case_row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $row%8 == 0; + if ( $nonzero ne 0 ) { + $rowtable_txt .= "$therow, "; + } else { + $rowtable_txt .= "0, "; + } +} + +# Print pages... +# +for $r ( sort keys %case_rowtext ) { + print $case_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + +# Build decimal info +# +$rowtable_txt = + "static const Q_INT8 * const decimal_info[256] = {"; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $digit_value{$code}; + if ( length( $info ) eq 0 ) { + $info = -1; + } else { + $nonzero = 1; + } + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $decimal_row{$txt}; + if ( !defined $therow && $nonzero ne 0 ) { + $size+=512; + $therow = "num_".sprintf("%02X",$row); + $decimal_rowtext{$therow} = + "static const Q_INT8 ${therow}[] = {$txt\n};\n\n"; + $decimal_row{$txt}=$therow; + } + $rowtable_txt .= "\n " if $row%8 == 0; + if ( $nonzero ne 0 ) { + $rowtable_txt .= "$therow, "; + } else { + $rowtable_txt .= "0, "; + } +} + +# Print pages... +# +for $r ( sort keys %decimal_rowtext ) { + print $decimal_rowtext{$r}; +} +print "$rowtable_txt\n};\n"; +$size += 256*4; +print "// $size bytes\n\n"; + + + +print "#endif\n\n"; +print "// END OF GENERATED DATA\n\n"; + + + +__END__ + +*/ + +// START OF GENERATED DATA + +static const Q_UINT8 ui_00[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 26, 26, 28, 26, 26, 26, + 22, 23, 26, 27, 26, 21, 26, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 27, 27, 27, 26, + 26, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 26, 23, 29, 20, + 29, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 27, 23, 27, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 28, 28, 28, 28, 30, 30, + 29, 30, 16, 24, 27, 21, 30, 29, + 30, 27, 6, 6, 29, 16, 30, 26, + 29, 6, 16, 25, 6, 6, 6, 26, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 27, + 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 27, + 16, 16, 16, 16, 16, 16, 16, 16, +}; + +#ifndef QT_NO_UNICODETABLES + +static const Q_UINT8 ui_01[] = { + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 15, 16, 15, 16, 15, 16, 16, + 16, 15, 15, 16, 15, 16, 15, 15, + 16, 15, 15, 15, 16, 16, 15, 15, + 15, 15, 16, 15, 15, 16, 15, 15, + 15, 16, 16, 16, 15, 15, 16, 15, + 15, 16, 15, 16, 15, 16, 15, 15, + 16, 15, 16, 16, 15, 16, 15, 15, + 16, 15, 15, 15, 16, 15, 16, 15, + 15, 16, 16, 19, 15, 16, 16, 16, + 19, 19, 19, 19, 15, 17, 16, 15, + 17, 16, 15, 17, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 15, 17, 16, 15, 16, 15, 15, + 15, 16, 15, 16, 15, 16, 15, 16, +}; + +static const Q_UINT8 ui_02[] = { + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 0, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 29, 29, 18, 18, 18, 18, 18, + 18, 18, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 18, 18, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 18, 18, 18, 18, 18, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 18, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_03[] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 29, 29, 0, 0, + 0, 0, 18, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 29, 29, 15, 26, + 15, 15, 15, 0, 15, 0, 15, 15, + 16, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, + 16, 16, 15, 15, 15, 16, 16, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 16, 16, 16, 15, 16, 27, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_04[] = { + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 30, 1, 1, 1, 1, 0, + 3, 3, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 0, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 0, 0, + 15, 16, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_05[] = { + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, + 0, 18, 26, 26, 26, 26, 26, 26, + 0, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 0, 26, 21, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 26, 1, + 26, 1, 1, 26, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 19, 19, 19, 26, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_06[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 26, 0, 0, 0, 26, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 26, 26, 19, 19, + 1, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 26, 19, 1, 1, + 1, 1, 1, 1, 1, 11, 3, 1, + 1, 1, 1, 1, 1, 18, 18, 1, + 1, 30, 1, 1, 1, 1, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 19, 19, 19, 30, 30, 0, +}; + +static const Q_UINT8 ui_07[] = { + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 0, 11, + 19, 1, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_08[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_09[] = { + 0, 1, 1, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 1, 0, 0, + 19, 1, 1, 1, 1, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 26, 26, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 0, 0, 0, 19, 19, + 19, 19, 0, 0, 1, 0, 2, 2, + 2, 1, 1, 1, 1, 0, 0, 2, + 2, 0, 0, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 19, 19, 0, 19, + 19, 19, 1, 1, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 19, 19, 28, 28, 6, 6, 6, 6, + 6, 6, 30, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0A[] = { + 0, 0, 1, 0, 0, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 0, + 19, 19, 0, 0, 1, 0, 2, 2, + 2, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 19, 19, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 19, 19, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 0, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 2, + 2, 1, 1, 1, 1, 1, 0, 1, + 1, 2, 0, 2, 2, 1, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0B[] = { + 0, 1, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 0, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 1, + 2, 1, 1, 1, 0, 0, 0, 2, + 2, 0, 0, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 0, 19, 19, 0, 19, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 30, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 19, 0, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 0, 0, + 0, 19, 19, 0, 19, 0, 19, 19, + 0, 0, 0, 19, 19, 0, 0, 0, + 19, 19, 19, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 19, + 19, 19, 0, 0, 0, 0, 2, 2, + 1, 2, 2, 0, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 6, 6, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0C[] = { + 0, 2, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 1, 1, + 1, 2, 2, 2, 2, 0, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 2, 1, + 2, 2, 2, 2, 2, 0, 1, 2, + 2, 0, 2, 2, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 19, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0D[] = { + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 2, 2, + 2, 1, 1, 1, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 1, 0, 0, 0, 0, 2, + 2, 2, 1, 1, 1, 0, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0E[] = { + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 1, 19, 19, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 28, + 19, 19, 19, 19, 19, 19, 18, 1, + 1, 1, 1, 1, 1, 1, 1, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 0, 19, 0, 0, 19, + 19, 0, 19, 0, 0, 19, 0, 0, + 0, 0, 0, 0, 19, 19, 19, 19, + 0, 19, 19, 19, 19, 19, 19, 19, + 0, 19, 19, 19, 0, 19, 0, 19, + 0, 0, 19, 19, 0, 19, 19, 19, + 19, 1, 19, 19, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 19, 0, 0, + 19, 19, 19, 19, 19, 0, 18, 0, + 1, 1, 1, 1, 1, 1, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_0F[] = { + 19, 30, 30, 30, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 30, 30, 30, 30, 30, + 1, 1, 30, 30, 30, 30, 30, 30, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 1, 30, 1, + 30, 1, 22, 23, 22, 23, 2, 2, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 26, 1, 1, + 19, 19, 19, 19, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 30, + 30, 30, 30, 30, 30, 0, 0, 30, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_10[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 0, 19, 19, 0, 2, 1, 1, 1, + 1, 2, 1, 0, 0, 0, 1, 1, + 2, 1, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 26, 26, 26, 26, + 19, 19, 19, 19, 19, 19, 2, 2, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 26, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_11[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_12[] = { + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const Q_UINT8 ui_13[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 26, 26, 26, 26, 26, 26, 26, + 26, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_14[] = { + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const Q_UINT8 ui_15[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const Q_UINT8 ui_16[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 26, 26, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 22, 23, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 26, 26, 26, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_17[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 19, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 1, 26, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 26, 26, 26, 18, + 26, 26, 26, 28, 19, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_18[] = { + 26, 26, 26, 26, 26, 26, 21, 26, + 26, 26, 26, 1, 1, 1, 11, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_1E[] = { + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 0, 0, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_1F[] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 0, 15, 0, 15, 0, 15, 0, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 16, 29, + 29, 29, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 29, 29, + 16, 16, 16, 16, 0, 0, 16, 16, + 15, 15, 15, 15, 0, 29, 29, 29, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 29, 29, 29, + 0, 0, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 29, 0, +}; + +static const Q_UINT8 ui_20[] = { + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 11, 11, 11, 11, + 21, 21, 21, 21, 21, 21, 26, 26, + 24, 25, 22, 24, 24, 25, 22, 24, + 26, 26, 26, 26, 26, 26, 26, 26, + 8, 9, 11, 11, 11, 11, 11, 7, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 24, 25, 26, 26, 26, 26, 20, + 20, 26, 26, 26, 27, 22, 23, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 27, 0, 0, 0, 0, 26, + 0, 0, 0, 0, 0, 0, 0, 7, + 11, 11, 11, 11, 0, 0, 0, 0, + 0, 0, 11, 11, 11, 11, 11, 11, + 6, 16, 0, 0, 6, 6, 6, 6, + 6, 6, 27, 27, 27, 22, 23, 16, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 27, 27, 27, 22, 23, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 3, + 3, 1, 3, 3, 3, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_21[] = { + 30, 30, 15, 30, 30, 30, 30, 15, + 30, 30, 16, 15, 15, 15, 16, 16, + 15, 15, 15, 16, 30, 15, 30, 30, + 30, 15, 15, 15, 15, 15, 30, 30, + 30, 30, 30, 30, 15, 30, 15, 30, + 15, 30, 15, 15, 15, 15, 30, 16, + 15, 15, 30, 15, 16, 19, 19, 19, + 19, 16, 30, 0, 0, 16, 15, 15, + 27, 27, 27, 27, 27, 15, 16, 16, + 16, 16, 30, 27, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 30, 30, 30, + 30, 30, 27, 27, 30, 30, 30, 30, + 27, 30, 30, 27, 30, 30, 27, 30, + 30, 30, 30, 30, 30, 30, 27, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 27, 27, + 30, 30, 27, 30, 27, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, +}; + +static const Q_UINT8 ui_22[] = { + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, +}; + +static const Q_UINT8 ui_23[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 27, 27, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 30, 30, 30, 30, 30, 30, + 30, 22, 23, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 27, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 22, 23, 26, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_24[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, +}; + +static const Q_UINT8 ui_25[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 27, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 27, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 27, 27, 27, 27, 27, 27, +}; + +static const Q_UINT8 ui_26[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 27, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_27[] = { + 0, 30, 30, 30, 30, 0, 30, 30, + 30, 30, 0, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 30, 0, 30, + 30, 30, 30, 0, 0, 0, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 30, 30, 30, 30, 30, 30, 30, + 22, 23, 22, 23, 22, 23, 22, 23, + 22, 23, 22, 23, 22, 23, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 22, 23, + 22, 23, 22, 23, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, +}; + +static const Q_UINT8 ui_28[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, +}; + +static const Q_UINT8 ui_29[] = { + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 22, 23, 22, 23, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 22, 23, 27, 27, +}; + +static const Q_UINT8 ui_2E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 0, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_2F[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_30[] = { + 7, 26, 26, 26, 30, 18, 19, 5, + 22, 23, 22, 23, 22, 23, 22, 23, + 22, 23, 30, 30, 22, 23, 22, 23, + 22, 23, 22, 23, 21, 22, 23, 23, + 30, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 1, 1, 1, 1, 1, 1, + 21, 18, 18, 18, 18, 18, 30, 30, + 5, 5, 5, 18, 19, 26, 30, 30, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 1, 1, 29, 29, 18, 18, 19, + 21, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 20, 18, 18, 18, 19, +}; + +static const Q_UINT8 ui_31[] = { + 0, 0, 0, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 30, 30, 6, 6, 6, 6, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const Q_UINT8 ui_32[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 30, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, +}; + +static const Q_UINT8 ui_33[] = { + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, +}; + +static const Q_UINT8 ui_4D[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_9F[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_A4[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_D7[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_D8[] = { + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, +}; + +static const Q_UINT8 ui_E0[] = { + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, +}; + +static const Q_UINT8 ui_FA[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_FB[] = { + 16, 16, 16, 16, 16, 16, 16, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 16, 16, 16, 16, + 0, 0, 0, 0, 0, 19, 1, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 27, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 0, 19, 0, + 19, 19, 0, 19, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const Q_UINT8 ui_FD[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 28, 0, 0, 0, +}; + +static const Q_UINT8 ui_FE[] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 26, 21, 21, 20, 20, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 26, 26, 0, + 0, 26, 26, 26, 26, 20, 20, 20, + 26, 26, 26, 0, 26, 26, 26, 26, + 21, 22, 23, 22, 23, 22, 23, 26, + 26, 26, 27, 21, 27, 27, 27, 0, + 26, 28, 26, 26, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 11, +}; + +static const Q_UINT8 ui_FF[] = { + 0, 26, 26, 26, 28, 26, 26, 26, + 22, 23, 26, 27, 26, 21, 26, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 27, 27, 27, 26, + 26, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 26, 23, 29, 20, + 29, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 27, 23, 27, 22, + 23, 26, 22, 23, 26, 20, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 0, 0, 0, + 28, 28, 27, 29, 30, 28, 28, 0, + 30, 27, 27, 27, 27, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 11, 30, 30, 0, 0, +}; + +static const Q_UINT8 * const unicode_info[256] = { + ui_00, ui_01, ui_02, ui_03, ui_04, ui_05, ui_06, ui_07, + ui_08, ui_09, ui_0A, ui_0B, ui_0C, ui_0D, ui_0E, ui_0F, + ui_10, ui_11, ui_12, ui_13, ui_14, ui_15, ui_16, ui_17, + ui_18, ui_08, ui_08, ui_08, ui_08, ui_08, ui_1E, ui_1F, + ui_20, ui_21, ui_22, ui_23, ui_24, ui_25, ui_26, ui_27, + ui_28, ui_29, ui_22, ui_08, ui_08, ui_08, ui_2E, ui_2F, + ui_30, ui_31, ui_32, ui_33, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_4D, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_9F, + ui_15, ui_15, ui_15, ui_15, ui_A4, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, + ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_15, ui_D7, + ui_D8, ui_D8, ui_D8, ui_D8, ui_D8, ui_D8, ui_D8, ui_D8, + ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, + ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, + ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, ui_E0, + ui_E0, ui_15, ui_FA, ui_FB, ui_15, ui_FD, ui_FE, ui_FF, +}; +// 14848 bytes + +static const Q_UINT16 decomposition_map[] = { + 0, + 3, 0x00A0, 0x0020, 0, + 16, 0x00A8, 0x0020, 0x0308, 0, + 9, 0x00AA, 0x0061, 0, + 16, 0x00AF, 0x0020, 0x0304, 0, + 9, 0x00B2, 0x0032, 0, + 9, 0x00B3, 0x0033, 0, + 16, 0x00B4, 0x0020, 0x0301, 0, + 16, 0x00B5, 0x03BC, 0, + 16, 0x00B8, 0x0020, 0x0327, 0, + 9, 0x00B9, 0x0031, 0, + 9, 0x00BA, 0x006F, 0, + 17, 0x00BC, 0x0031, 0x2044, 0x0034, 0, + 17, 0x00BD, 0x0031, 0x2044, 0x0032, 0, + 17, 0x00BE, 0x0033, 0x2044, 0x0034, 0, + 1, 0x00C0, 0x0041, 0x0300, 0, + 1, 0x00C1, 0x0041, 0x0301, 0, + 1, 0x00C2, 0x0041, 0x0302, 0, + 1, 0x00C3, 0x0041, 0x0303, 0, + 1, 0x00C4, 0x0041, 0x0308, 0, + 1, 0x00C5, 0x0041, 0x030A, 0, + 1, 0x00C7, 0x0043, 0x0327, 0, + 1, 0x00C8, 0x0045, 0x0300, 0, + 1, 0x00C9, 0x0045, 0x0301, 0, + 1, 0x00CA, 0x0045, 0x0302, 0, + 1, 0x00CB, 0x0045, 0x0308, 0, + 1, 0x00CC, 0x0049, 0x0300, 0, + 1, 0x00CD, 0x0049, 0x0301, 0, + 1, 0x00CE, 0x0049, 0x0302, 0, + 1, 0x00CF, 0x0049, 0x0308, 0, + 1, 0x00D1, 0x004E, 0x0303, 0, + 1, 0x00D2, 0x004F, 0x0300, 0, + 1, 0x00D3, 0x004F, 0x0301, 0, + 1, 0x00D4, 0x004F, 0x0302, 0, + 1, 0x00D5, 0x004F, 0x0303, 0, + 1, 0x00D6, 0x004F, 0x0308, 0, + 1, 0x00D9, 0x0055, 0x0300, 0, + 1, 0x00DA, 0x0055, 0x0301, 0, + 1, 0x00DB, 0x0055, 0x0302, 0, + 1, 0x00DC, 0x0055, 0x0308, 0, + 1, 0x00DD, 0x0059, 0x0301, 0, + 1, 0x00E0, 0x0061, 0x0300, 0, + 1, 0x00E1, 0x0061, 0x0301, 0, + 1, 0x00E2, 0x0061, 0x0302, 0, + 1, 0x00E3, 0x0061, 0x0303, 0, + 1, 0x00E4, 0x0061, 0x0308, 0, + 1, 0x00E5, 0x0061, 0x030A, 0, + 1, 0x00E7, 0x0063, 0x0327, 0, + 1, 0x00E8, 0x0065, 0x0300, 0, + 1, 0x00E9, 0x0065, 0x0301, 0, + 1, 0x00EA, 0x0065, 0x0302, 0, + 1, 0x00EB, 0x0065, 0x0308, 0, + 1, 0x00EC, 0x0069, 0x0300, 0, + 1, 0x00ED, 0x0069, 0x0301, 0, + 1, 0x00EE, 0x0069, 0x0302, 0, + 1, 0x00EF, 0x0069, 0x0308, 0, + 1, 0x00F1, 0x006E, 0x0303, 0, + 1, 0x00F2, 0x006F, 0x0300, 0, + 1, 0x00F3, 0x006F, 0x0301, 0, + 1, 0x00F4, 0x006F, 0x0302, 0, + 1, 0x00F5, 0x006F, 0x0303, 0, + 1, 0x00F6, 0x006F, 0x0308, 0, + 1, 0x00F9, 0x0075, 0x0300, 0, + 1, 0x00FA, 0x0075, 0x0301, 0, + 1, 0x00FB, 0x0075, 0x0302, 0, + 1, 0x00FC, 0x0075, 0x0308, 0, + 1, 0x00FD, 0x0079, 0x0301, 0, + 1, 0x00FF, 0x0079, 0x0308, 0, + 1, 0x0100, 0x0041, 0x0304, 0, + 1, 0x0101, 0x0061, 0x0304, 0, + 1, 0x0102, 0x0041, 0x0306, 0, + 1, 0x0103, 0x0061, 0x0306, 0, + 1, 0x0104, 0x0041, 0x0328, 0, + 1, 0x0105, 0x0061, 0x0328, 0, + 1, 0x0106, 0x0043, 0x0301, 0, + 1, 0x0107, 0x0063, 0x0301, 0, + 1, 0x0108, 0x0043, 0x0302, 0, + 1, 0x0109, 0x0063, 0x0302, 0, + 1, 0x010A, 0x0043, 0x0307, 0, + 1, 0x010B, 0x0063, 0x0307, 0, + 1, 0x010C, 0x0043, 0x030C, 0, + 1, 0x010D, 0x0063, 0x030C, 0, + 1, 0x010E, 0x0044, 0x030C, 0, + 1, 0x010F, 0x0064, 0x030C, 0, + 1, 0x0112, 0x0045, 0x0304, 0, + 1, 0x0113, 0x0065, 0x0304, 0, + 1, 0x0114, 0x0045, 0x0306, 0, + 1, 0x0115, 0x0065, 0x0306, 0, + 1, 0x0116, 0x0045, 0x0307, 0, + 1, 0x0117, 0x0065, 0x0307, 0, + 1, 0x0118, 0x0045, 0x0328, 0, + 1, 0x0119, 0x0065, 0x0328, 0, + 1, 0x011A, 0x0045, 0x030C, 0, + 1, 0x011B, 0x0065, 0x030C, 0, + 1, 0x011C, 0x0047, 0x0302, 0, + 1, 0x011D, 0x0067, 0x0302, 0, + 1, 0x011E, 0x0047, 0x0306, 0, + 1, 0x011F, 0x0067, 0x0306, 0, + 1, 0x0120, 0x0047, 0x0307, 0, + 1, 0x0121, 0x0067, 0x0307, 0, + 1, 0x0122, 0x0047, 0x0327, 0, + 1, 0x0123, 0x0067, 0x0327, 0, + 1, 0x0124, 0x0048, 0x0302, 0, + 1, 0x0125, 0x0068, 0x0302, 0, + 1, 0x0128, 0x0049, 0x0303, 0, + 1, 0x0129, 0x0069, 0x0303, 0, + 1, 0x012A, 0x0049, 0x0304, 0, + 1, 0x012B, 0x0069, 0x0304, 0, + 1, 0x012C, 0x0049, 0x0306, 0, + 1, 0x012D, 0x0069, 0x0306, 0, + 1, 0x012E, 0x0049, 0x0328, 0, + 1, 0x012F, 0x0069, 0x0328, 0, + 1, 0x0130, 0x0049, 0x0307, 0, + 16, 0x0132, 0x0049, 0x004A, 0, + 16, 0x0133, 0x0069, 0x006A, 0, + 1, 0x0134, 0x004A, 0x0302, 0, + 1, 0x0135, 0x006A, 0x0302, 0, + 1, 0x0136, 0x004B, 0x0327, 0, + 1, 0x0137, 0x006B, 0x0327, 0, + 1, 0x0139, 0x004C, 0x0301, 0, + 1, 0x013A, 0x006C, 0x0301, 0, + 1, 0x013B, 0x004C, 0x0327, 0, + 1, 0x013C, 0x006C, 0x0327, 0, + 1, 0x013D, 0x004C, 0x030C, 0, + 1, 0x013E, 0x006C, 0x030C, 0, + 16, 0x013F, 0x004C, 0x00B7, 0, + 16, 0x0140, 0x006C, 0x00B7, 0, + 1, 0x0143, 0x004E, 0x0301, 0, + 1, 0x0144, 0x006E, 0x0301, 0, + 1, 0x0145, 0x004E, 0x0327, 0, + 1, 0x0146, 0x006E, 0x0327, 0, + 1, 0x0147, 0x004E, 0x030C, 0, + 1, 0x0148, 0x006E, 0x030C, 0, + 16, 0x0149, 0x02BC, 0x006E, 0, + 1, 0x014C, 0x004F, 0x0304, 0, + 1, 0x014D, 0x006F, 0x0304, 0, + 1, 0x014E, 0x004F, 0x0306, 0, + 1, 0x014F, 0x006F, 0x0306, 0, + 1, 0x0150, 0x004F, 0x030B, 0, + 1, 0x0151, 0x006F, 0x030B, 0, + 1, 0x0154, 0x0052, 0x0301, 0, + 1, 0x0155, 0x0072, 0x0301, 0, + 1, 0x0156, 0x0052, 0x0327, 0, + 1, 0x0157, 0x0072, 0x0327, 0, + 1, 0x0158, 0x0052, 0x030C, 0, + 1, 0x0159, 0x0072, 0x030C, 0, + 1, 0x015A, 0x0053, 0x0301, 0, + 1, 0x015B, 0x0073, 0x0301, 0, + 1, 0x015C, 0x0053, 0x0302, 0, + 1, 0x015D, 0x0073, 0x0302, 0, + 1, 0x015E, 0x0053, 0x0327, 0, + 1, 0x015F, 0x0073, 0x0327, 0, + 1, 0x0160, 0x0053, 0x030C, 0, + 1, 0x0161, 0x0073, 0x030C, 0, + 1, 0x0162, 0x0054, 0x0327, 0, + 1, 0x0163, 0x0074, 0x0327, 0, + 1, 0x0164, 0x0054, 0x030C, 0, + 1, 0x0165, 0x0074, 0x030C, 0, + 1, 0x0168, 0x0055, 0x0303, 0, + 1, 0x0169, 0x0075, 0x0303, 0, + 1, 0x016A, 0x0055, 0x0304, 0, + 1, 0x016B, 0x0075, 0x0304, 0, + 1, 0x016C, 0x0055, 0x0306, 0, + 1, 0x016D, 0x0075, 0x0306, 0, + 1, 0x016E, 0x0055, 0x030A, 0, + 1, 0x016F, 0x0075, 0x030A, 0, + 1, 0x0170, 0x0055, 0x030B, 0, + 1, 0x0171, 0x0075, 0x030B, 0, + 1, 0x0172, 0x0055, 0x0328, 0, + 1, 0x0173, 0x0075, 0x0328, 0, + 1, 0x0174, 0x0057, 0x0302, 0, + 1, 0x0175, 0x0077, 0x0302, 0, + 1, 0x0176, 0x0059, 0x0302, 0, + 1, 0x0177, 0x0079, 0x0302, 0, + 1, 0x0178, 0x0059, 0x0308, 0, + 1, 0x0179, 0x005A, 0x0301, 0, + 1, 0x017A, 0x007A, 0x0301, 0, + 1, 0x017B, 0x005A, 0x0307, 0, + 1, 0x017C, 0x007A, 0x0307, 0, + 1, 0x017D, 0x005A, 0x030C, 0, + 1, 0x017E, 0x007A, 0x030C, 0, + 16, 0x017F, 0x0073, 0, + 1, 0x01A0, 0x004F, 0x031B, 0, + 1, 0x01A1, 0x006F, 0x031B, 0, + 1, 0x01AF, 0x0055, 0x031B, 0, + 1, 0x01B0, 0x0075, 0x031B, 0, + 16, 0x01C4, 0x0044, 0x017D, 0, + 16, 0x01C5, 0x0044, 0x017E, 0, + 16, 0x01C6, 0x0064, 0x017E, 0, + 16, 0x01C7, 0x004C, 0x004A, 0, + 16, 0x01C8, 0x004C, 0x006A, 0, + 16, 0x01C9, 0x006C, 0x006A, 0, + 16, 0x01CA, 0x004E, 0x004A, 0, + 16, 0x01CB, 0x004E, 0x006A, 0, + 16, 0x01CC, 0x006E, 0x006A, 0, + 1, 0x01CD, 0x0041, 0x030C, 0, + 1, 0x01CE, 0x0061, 0x030C, 0, + 1, 0x01CF, 0x0049, 0x030C, 0, + 1, 0x01D0, 0x0069, 0x030C, 0, + 1, 0x01D1, 0x004F, 0x030C, 0, + 1, 0x01D2, 0x006F, 0x030C, 0, + 1, 0x01D3, 0x0055, 0x030C, 0, + 1, 0x01D4, 0x0075, 0x030C, 0, + 1, 0x01D5, 0x00DC, 0x0304, 0, + 1, 0x01D6, 0x00FC, 0x0304, 0, + 1, 0x01D7, 0x00DC, 0x0301, 0, + 1, 0x01D8, 0x00FC, 0x0301, 0, + 1, 0x01D9, 0x00DC, 0x030C, 0, + 1, 0x01DA, 0x00FC, 0x030C, 0, + 1, 0x01DB, 0x00DC, 0x0300, 0, + 1, 0x01DC, 0x00FC, 0x0300, 0, + 1, 0x01DE, 0x00C4, 0x0304, 0, + 1, 0x01DF, 0x00E4, 0x0304, 0, + 1, 0x01E0, 0x0226, 0x0304, 0, + 1, 0x01E1, 0x0227, 0x0304, 0, + 1, 0x01E2, 0x00C6, 0x0304, 0, + 1, 0x01E3, 0x00E6, 0x0304, 0, + 1, 0x01E6, 0x0047, 0x030C, 0, + 1, 0x01E7, 0x0067, 0x030C, 0, + 1, 0x01E8, 0x004B, 0x030C, 0, + 1, 0x01E9, 0x006B, 0x030C, 0, + 1, 0x01EA, 0x004F, 0x0328, 0, + 1, 0x01EB, 0x006F, 0x0328, 0, + 1, 0x01EC, 0x01EA, 0x0304, 0, + 1, 0x01ED, 0x01EB, 0x0304, 0, + 1, 0x01EE, 0x01B7, 0x030C, 0, + 1, 0x01EF, 0x0292, 0x030C, 0, + 1, 0x01F0, 0x006A, 0x030C, 0, + 16, 0x01F1, 0x0044, 0x005A, 0, + 16, 0x01F2, 0x0044, 0x007A, 0, + 16, 0x01F3, 0x0064, 0x007A, 0, + 1, 0x01F4, 0x0047, 0x0301, 0, + 1, 0x01F5, 0x0067, 0x0301, 0, + 1, 0x01F8, 0x004E, 0x0300, 0, + 1, 0x01F9, 0x006E, 0x0300, 0, + 1, 0x01FA, 0x00C5, 0x0301, 0, + 1, 0x01FB, 0x00E5, 0x0301, 0, + 1, 0x01FC, 0x00C6, 0x0301, 0, + 1, 0x01FD, 0x00E6, 0x0301, 0, + 1, 0x01FE, 0x00D8, 0x0301, 0, + 1, 0x01FF, 0x00F8, 0x0301, 0, + 1, 0x0200, 0x0041, 0x030F, 0, + 1, 0x0201, 0x0061, 0x030F, 0, + 1, 0x0202, 0x0041, 0x0311, 0, + 1, 0x0203, 0x0061, 0x0311, 0, + 1, 0x0204, 0x0045, 0x030F, 0, + 1, 0x0205, 0x0065, 0x030F, 0, + 1, 0x0206, 0x0045, 0x0311, 0, + 1, 0x0207, 0x0065, 0x0311, 0, + 1, 0x0208, 0x0049, 0x030F, 0, + 1, 0x0209, 0x0069, 0x030F, 0, + 1, 0x020A, 0x0049, 0x0311, 0, + 1, 0x020B, 0x0069, 0x0311, 0, + 1, 0x020C, 0x004F, 0x030F, 0, + 1, 0x020D, 0x006F, 0x030F, 0, + 1, 0x020E, 0x004F, 0x0311, 0, + 1, 0x020F, 0x006F, 0x0311, 0, + 1, 0x0210, 0x0052, 0x030F, 0, + 1, 0x0211, 0x0072, 0x030F, 0, + 1, 0x0212, 0x0052, 0x0311, 0, + 1, 0x0213, 0x0072, 0x0311, 0, + 1, 0x0214, 0x0055, 0x030F, 0, + 1, 0x0215, 0x0075, 0x030F, 0, + 1, 0x0216, 0x0055, 0x0311, 0, + 1, 0x0217, 0x0075, 0x0311, 0, + 1, 0x0218, 0x0053, 0x0326, 0, + 1, 0x0219, 0x0073, 0x0326, 0, + 1, 0x021A, 0x0054, 0x0326, 0, + 1, 0x021B, 0x0074, 0x0326, 0, + 1, 0x021E, 0x0048, 0x030C, 0, + 1, 0x021F, 0x0068, 0x030C, 0, + 1, 0x0226, 0x0041, 0x0307, 0, + 1, 0x0227, 0x0061, 0x0307, 0, + 1, 0x0228, 0x0045, 0x0327, 0, + 1, 0x0229, 0x0065, 0x0327, 0, + 1, 0x022A, 0x00D6, 0x0304, 0, + 1, 0x022B, 0x00F6, 0x0304, 0, + 1, 0x022C, 0x00D5, 0x0304, 0, + 1, 0x022D, 0x00F5, 0x0304, 0, + 1, 0x022E, 0x004F, 0x0307, 0, + 1, 0x022F, 0x006F, 0x0307, 0, + 1, 0x0230, 0x022E, 0x0304, 0, + 1, 0x0231, 0x022F, 0x0304, 0, + 1, 0x0232, 0x0059, 0x0304, 0, + 1, 0x0233, 0x0079, 0x0304, 0, + 9, 0x02B0, 0x0068, 0, + 9, 0x02B1, 0x0266, 0, + 9, 0x02B2, 0x006A, 0, + 9, 0x02B3, 0x0072, 0, + 9, 0x02B4, 0x0279, 0, + 9, 0x02B5, 0x027B, 0, + 9, 0x02B6, 0x0281, 0, + 9, 0x02B7, 0x0077, 0, + 9, 0x02B8, 0x0079, 0, + 16, 0x02D8, 0x0020, 0x0306, 0, + 16, 0x02D9, 0x0020, 0x0307, 0, + 16, 0x02DA, 0x0020, 0x030A, 0, + 16, 0x02DB, 0x0020, 0x0328, 0, + 16, 0x02DC, 0x0020, 0x0303, 0, + 16, 0x02DD, 0x0020, 0x030B, 0, + 9, 0x02E0, 0x0263, 0, + 9, 0x02E1, 0x006C, 0, + 9, 0x02E2, 0x0073, 0, + 9, 0x02E3, 0x0078, 0, + 9, 0x02E4, 0x0295, 0, + 1, 0x0340, 0x0300, 0, + 1, 0x0341, 0x0301, 0, + 1, 0x0343, 0x0313, 0, + 1, 0x0344, 0x0308, 0x0301, 0, + 1, 0x0374, 0x02B9, 0, + 16, 0x037A, 0x0020, 0x0345, 0, + 1, 0x037E, 0x003B, 0, + 16, 0x0384, 0x0020, 0x0301, 0, + 1, 0x0385, 0x00A8, 0x0301, 0, + 1, 0x0386, 0x0391, 0x0301, 0, + 1, 0x0387, 0x00B7, 0, + 1, 0x0388, 0x0395, 0x0301, 0, + 1, 0x0389, 0x0397, 0x0301, 0, + 1, 0x038A, 0x0399, 0x0301, 0, + 1, 0x038C, 0x039F, 0x0301, 0, + 1, 0x038E, 0x03A5, 0x0301, 0, + 1, 0x038F, 0x03A9, 0x0301, 0, + 1, 0x0390, 0x03CA, 0x0301, 0, + 1, 0x03AA, 0x0399, 0x0308, 0, + 1, 0x03AB, 0x03A5, 0x0308, 0, + 1, 0x03AC, 0x03B1, 0x0301, 0, + 1, 0x03AD, 0x03B5, 0x0301, 0, + 1, 0x03AE, 0x03B7, 0x0301, 0, + 1, 0x03AF, 0x03B9, 0x0301, 0, + 1, 0x03B0, 0x03CB, 0x0301, 0, + 1, 0x03CA, 0x03B9, 0x0308, 0, + 1, 0x03CB, 0x03C5, 0x0308, 0, + 1, 0x03CC, 0x03BF, 0x0301, 0, + 1, 0x03CD, 0x03C5, 0x0301, 0, + 1, 0x03CE, 0x03C9, 0x0301, 0, + 16, 0x03D0, 0x03B2, 0, + 16, 0x03D1, 0x03B8, 0, + 16, 0x03D2, 0x03A5, 0, + 1, 0x03D3, 0x03D2, 0x0301, 0, + 1, 0x03D4, 0x03D2, 0x0308, 0, + 16, 0x03D5, 0x03C6, 0, + 16, 0x03D6, 0x03C0, 0, + 16, 0x03F0, 0x03BA, 0, + 16, 0x03F1, 0x03C1, 0, + 16, 0x03F2, 0x03C2, 0, + 16, 0x03F4, 0x0398, 0, + 16, 0x03F5, 0x03B5, 0, + 1, 0x0400, 0x0415, 0x0300, 0, + 1, 0x0401, 0x0415, 0x0308, 0, + 1, 0x0403, 0x0413, 0x0301, 0, + 1, 0x0407, 0x0406, 0x0308, 0, + 1, 0x040C, 0x041A, 0x0301, 0, + 1, 0x040D, 0x0418, 0x0300, 0, + 1, 0x040E, 0x0423, 0x0306, 0, + 1, 0x0419, 0x0418, 0x0306, 0, + 1, 0x0439, 0x0438, 0x0306, 0, + 1, 0x0450, 0x0435, 0x0300, 0, + 1, 0x0451, 0x0435, 0x0308, 0, + 1, 0x0453, 0x0433, 0x0301, 0, + 1, 0x0457, 0x0456, 0x0308, 0, + 1, 0x045C, 0x043A, 0x0301, 0, + 1, 0x045D, 0x0438, 0x0300, 0, + 1, 0x045E, 0x0443, 0x0306, 0, + 1, 0x0476, 0x0474, 0x030F, 0, + 1, 0x0477, 0x0475, 0x030F, 0, + 1, 0x04C1, 0x0416, 0x0306, 0, + 1, 0x04C2, 0x0436, 0x0306, 0, + 1, 0x04D0, 0x0410, 0x0306, 0, + 1, 0x04D1, 0x0430, 0x0306, 0, + 1, 0x04D2, 0x0410, 0x0308, 0, + 1, 0x04D3, 0x0430, 0x0308, 0, + 1, 0x04D6, 0x0415, 0x0306, 0, + 1, 0x04D7, 0x0435, 0x0306, 0, + 1, 0x04DA, 0x04D8, 0x0308, 0, + 1, 0x04DB, 0x04D9, 0x0308, 0, + 1, 0x04DC, 0x0416, 0x0308, 0, + 1, 0x04DD, 0x0436, 0x0308, 0, + 1, 0x04DE, 0x0417, 0x0308, 0, + 1, 0x04DF, 0x0437, 0x0308, 0, + 1, 0x04E2, 0x0418, 0x0304, 0, + 1, 0x04E3, 0x0438, 0x0304, 0, + 1, 0x04E4, 0x0418, 0x0308, 0, + 1, 0x04E5, 0x0438, 0x0308, 0, + 1, 0x04E6, 0x041E, 0x0308, 0, + 1, 0x04E7, 0x043E, 0x0308, 0, + 1, 0x04EA, 0x04E8, 0x0308, 0, + 1, 0x04EB, 0x04E9, 0x0308, 0, + 1, 0x04EC, 0x042D, 0x0308, 0, + 1, 0x04ED, 0x044D, 0x0308, 0, + 1, 0x04EE, 0x0423, 0x0304, 0, + 1, 0x04EF, 0x0443, 0x0304, 0, + 1, 0x04F0, 0x0423, 0x0308, 0, + 1, 0x04F1, 0x0443, 0x0308, 0, + 1, 0x04F2, 0x0423, 0x030B, 0, + 1, 0x04F3, 0x0443, 0x030B, 0, + 1, 0x04F4, 0x0427, 0x0308, 0, + 1, 0x04F5, 0x0447, 0x0308, 0, + 1, 0x04F8, 0x042B, 0x0308, 0, + 1, 0x04F9, 0x044B, 0x0308, 0, + 16, 0x0587, 0x0565, 0x0582, 0, + 1, 0x0622, 0x0627, 0x0653, 0, + 1, 0x0623, 0x0627, 0x0654, 0, + 1, 0x0624, 0x0648, 0x0654, 0, + 1, 0x0625, 0x0627, 0x0655, 0, + 1, 0x0626, 0x064A, 0x0654, 0, + 16, 0x0675, 0x0627, 0x0674, 0, + 16, 0x0676, 0x0648, 0x0674, 0, + 16, 0x0677, 0x06C7, 0x0674, 0, + 16, 0x0678, 0x064A, 0x0674, 0, + 1, 0x06C0, 0x06D5, 0x0654, 0, + 1, 0x06C2, 0x06C1, 0x0654, 0, + 1, 0x06D3, 0x06D2, 0x0654, 0, + 1, 0x0929, 0x0928, 0x093C, 0, + 1, 0x0931, 0x0930, 0x093C, 0, + 1, 0x0934, 0x0933, 0x093C, 0, + 1, 0x0958, 0x0915, 0x093C, 0, + 1, 0x0959, 0x0916, 0x093C, 0, + 1, 0x095A, 0x0917, 0x093C, 0, + 1, 0x095B, 0x091C, 0x093C, 0, + 1, 0x095C, 0x0921, 0x093C, 0, + 1, 0x095D, 0x0922, 0x093C, 0, + 1, 0x095E, 0x092B, 0x093C, 0, + 1, 0x095F, 0x092F, 0x093C, 0, + 1, 0x09CB, 0x09C7, 0x09BE, 0, + 1, 0x09CC, 0x09C7, 0x09D7, 0, + 1, 0x09DC, 0x09A1, 0x09BC, 0, + 1, 0x09DD, 0x09A2, 0x09BC, 0, + 1, 0x09DF, 0x09AF, 0x09BC, 0, + 1, 0x0A33, 0x0A32, 0x0A3C, 0, + 1, 0x0A36, 0x0A38, 0x0A3C, 0, + 1, 0x0A59, 0x0A16, 0x0A3C, 0, + 1, 0x0A5A, 0x0A17, 0x0A3C, 0, + 1, 0x0A5B, 0x0A1C, 0x0A3C, 0, + 1, 0x0A5E, 0x0A2B, 0x0A3C, 0, + 1, 0x0B48, 0x0B47, 0x0B56, 0, + 1, 0x0B4B, 0x0B47, 0x0B3E, 0, + 1, 0x0B4C, 0x0B47, 0x0B57, 0, + 1, 0x0B5C, 0x0B21, 0x0B3C, 0, + 1, 0x0B5D, 0x0B22, 0x0B3C, 0, + 1, 0x0B94, 0x0B92, 0x0BD7, 0, + 1, 0x0BCA, 0x0BC6, 0x0BBE, 0, + 1, 0x0BCB, 0x0BC7, 0x0BBE, 0, + 1, 0x0BCC, 0x0BC6, 0x0BD7, 0, + 1, 0x0C48, 0x0C46, 0x0C56, 0, + 1, 0x0CC0, 0x0CBF, 0x0CD5, 0, + 1, 0x0CC7, 0x0CC6, 0x0CD5, 0, + 1, 0x0CC8, 0x0CC6, 0x0CD6, 0, + 1, 0x0CCA, 0x0CC6, 0x0CC2, 0, + 1, 0x0CCB, 0x0CCA, 0x0CD5, 0, + 1, 0x0D4A, 0x0D46, 0x0D3E, 0, + 1, 0x0D4B, 0x0D47, 0x0D3E, 0, + 1, 0x0D4C, 0x0D46, 0x0D57, 0, + 1, 0x0DDA, 0x0DD9, 0x0DCA, 0, + 1, 0x0DDC, 0x0DD9, 0x0DCF, 0, + 1, 0x0DDD, 0x0DDC, 0x0DCA, 0, + 1, 0x0DDE, 0x0DD9, 0x0DDF, 0, + 16, 0x0E33, 0x0E4D, 0x0E32, 0, + 16, 0x0EB3, 0x0ECD, 0x0EB2, 0, + 16, 0x0EDC, 0x0EAB, 0x0E99, 0, + 16, 0x0EDD, 0x0EAB, 0x0EA1, 0, + 3, 0x0F0C, 0x0F0B, 0, + 1, 0x0F43, 0x0F42, 0x0FB7, 0, + 1, 0x0F4D, 0x0F4C, 0x0FB7, 0, + 1, 0x0F52, 0x0F51, 0x0FB7, 0, + 1, 0x0F57, 0x0F56, 0x0FB7, 0, + 1, 0x0F5C, 0x0F5B, 0x0FB7, 0, + 1, 0x0F69, 0x0F40, 0x0FB5, 0, + 1, 0x0F73, 0x0F71, 0x0F72, 0, + 1, 0x0F75, 0x0F71, 0x0F74, 0, + 1, 0x0F76, 0x0FB2, 0x0F80, 0, + 16, 0x0F77, 0x0FB2, 0x0F81, 0, + 1, 0x0F78, 0x0FB3, 0x0F80, 0, + 16, 0x0F79, 0x0FB3, 0x0F81, 0, + 1, 0x0F81, 0x0F71, 0x0F80, 0, + 1, 0x0F93, 0x0F92, 0x0FB7, 0, + 1, 0x0F9D, 0x0F9C, 0x0FB7, 0, + 1, 0x0FA2, 0x0FA1, 0x0FB7, 0, + 1, 0x0FA7, 0x0FA6, 0x0FB7, 0, + 1, 0x0FAC, 0x0FAB, 0x0FB7, 0, + 1, 0x0FB9, 0x0F90, 0x0FB5, 0, + 1, 0x1026, 0x1025, 0x102E, 0, + 1, 0x1E00, 0x0041, 0x0325, 0, + 1, 0x1E01, 0x0061, 0x0325, 0, + 1, 0x1E02, 0x0042, 0x0307, 0, + 1, 0x1E03, 0x0062, 0x0307, 0, + 1, 0x1E04, 0x0042, 0x0323, 0, + 1, 0x1E05, 0x0062, 0x0323, 0, + 1, 0x1E06, 0x0042, 0x0331, 0, + 1, 0x1E07, 0x0062, 0x0331, 0, + 1, 0x1E08, 0x00C7, 0x0301, 0, + 1, 0x1E09, 0x00E7, 0x0301, 0, + 1, 0x1E0A, 0x0044, 0x0307, 0, + 1, 0x1E0B, 0x0064, 0x0307, 0, + 1, 0x1E0C, 0x0044, 0x0323, 0, + 1, 0x1E0D, 0x0064, 0x0323, 0, + 1, 0x1E0E, 0x0044, 0x0331, 0, + 1, 0x1E0F, 0x0064, 0x0331, 0, + 1, 0x1E10, 0x0044, 0x0327, 0, + 1, 0x1E11, 0x0064, 0x0327, 0, + 1, 0x1E12, 0x0044, 0x032D, 0, + 1, 0x1E13, 0x0064, 0x032D, 0, + 1, 0x1E14, 0x0112, 0x0300, 0, + 1, 0x1E15, 0x0113, 0x0300, 0, + 1, 0x1E16, 0x0112, 0x0301, 0, + 1, 0x1E17, 0x0113, 0x0301, 0, + 1, 0x1E18, 0x0045, 0x032D, 0, + 1, 0x1E19, 0x0065, 0x032D, 0, + 1, 0x1E1A, 0x0045, 0x0330, 0, + 1, 0x1E1B, 0x0065, 0x0330, 0, + 1, 0x1E1C, 0x0228, 0x0306, 0, + 1, 0x1E1D, 0x0229, 0x0306, 0, + 1, 0x1E1E, 0x0046, 0x0307, 0, + 1, 0x1E1F, 0x0066, 0x0307, 0, + 1, 0x1E20, 0x0047, 0x0304, 0, + 1, 0x1E21, 0x0067, 0x0304, 0, + 1, 0x1E22, 0x0048, 0x0307, 0, + 1, 0x1E23, 0x0068, 0x0307, 0, + 1, 0x1E24, 0x0048, 0x0323, 0, + 1, 0x1E25, 0x0068, 0x0323, 0, + 1, 0x1E26, 0x0048, 0x0308, 0, + 1, 0x1E27, 0x0068, 0x0308, 0, + 1, 0x1E28, 0x0048, 0x0327, 0, + 1, 0x1E29, 0x0068, 0x0327, 0, + 1, 0x1E2A, 0x0048, 0x032E, 0, + 1, 0x1E2B, 0x0068, 0x032E, 0, + 1, 0x1E2C, 0x0049, 0x0330, 0, + 1, 0x1E2D, 0x0069, 0x0330, 0, + 1, 0x1E2E, 0x00CF, 0x0301, 0, + 1, 0x1E2F, 0x00EF, 0x0301, 0, + 1, 0x1E30, 0x004B, 0x0301, 0, + 1, 0x1E31, 0x006B, 0x0301, 0, + 1, 0x1E32, 0x004B, 0x0323, 0, + 1, 0x1E33, 0x006B, 0x0323, 0, + 1, 0x1E34, 0x004B, 0x0331, 0, + 1, 0x1E35, 0x006B, 0x0331, 0, + 1, 0x1E36, 0x004C, 0x0323, 0, + 1, 0x1E37, 0x006C, 0x0323, 0, + 1, 0x1E38, 0x1E36, 0x0304, 0, + 1, 0x1E39, 0x1E37, 0x0304, 0, + 1, 0x1E3A, 0x004C, 0x0331, 0, + 1, 0x1E3B, 0x006C, 0x0331, 0, + 1, 0x1E3C, 0x004C, 0x032D, 0, + 1, 0x1E3D, 0x006C, 0x032D, 0, + 1, 0x1E3E, 0x004D, 0x0301, 0, + 1, 0x1E3F, 0x006D, 0x0301, 0, + 1, 0x1E40, 0x004D, 0x0307, 0, + 1, 0x1E41, 0x006D, 0x0307, 0, + 1, 0x1E42, 0x004D, 0x0323, 0, + 1, 0x1E43, 0x006D, 0x0323, 0, + 1, 0x1E44, 0x004E, 0x0307, 0, + 1, 0x1E45, 0x006E, 0x0307, 0, + 1, 0x1E46, 0x004E, 0x0323, 0, + 1, 0x1E47, 0x006E, 0x0323, 0, + 1, 0x1E48, 0x004E, 0x0331, 0, + 1, 0x1E49, 0x006E, 0x0331, 0, + 1, 0x1E4A, 0x004E, 0x032D, 0, + 1, 0x1E4B, 0x006E, 0x032D, 0, + 1, 0x1E4C, 0x00D5, 0x0301, 0, + 1, 0x1E4D, 0x00F5, 0x0301, 0, + 1, 0x1E4E, 0x00D5, 0x0308, 0, + 1, 0x1E4F, 0x00F5, 0x0308, 0, + 1, 0x1E50, 0x014C, 0x0300, 0, + 1, 0x1E51, 0x014D, 0x0300, 0, + 1, 0x1E52, 0x014C, 0x0301, 0, + 1, 0x1E53, 0x014D, 0x0301, 0, + 1, 0x1E54, 0x0050, 0x0301, 0, + 1, 0x1E55, 0x0070, 0x0301, 0, + 1, 0x1E56, 0x0050, 0x0307, 0, + 1, 0x1E57, 0x0070, 0x0307, 0, + 1, 0x1E58, 0x0052, 0x0307, 0, + 1, 0x1E59, 0x0072, 0x0307, 0, + 1, 0x1E5A, 0x0052, 0x0323, 0, + 1, 0x1E5B, 0x0072, 0x0323, 0, + 1, 0x1E5C, 0x1E5A, 0x0304, 0, + 1, 0x1E5D, 0x1E5B, 0x0304, 0, + 1, 0x1E5E, 0x0052, 0x0331, 0, + 1, 0x1E5F, 0x0072, 0x0331, 0, + 1, 0x1E60, 0x0053, 0x0307, 0, + 1, 0x1E61, 0x0073, 0x0307, 0, + 1, 0x1E62, 0x0053, 0x0323, 0, + 1, 0x1E63, 0x0073, 0x0323, 0, + 1, 0x1E64, 0x015A, 0x0307, 0, + 1, 0x1E65, 0x015B, 0x0307, 0, + 1, 0x1E66, 0x0160, 0x0307, 0, + 1, 0x1E67, 0x0161, 0x0307, 0, + 1, 0x1E68, 0x1E62, 0x0307, 0, + 1, 0x1E69, 0x1E63, 0x0307, 0, + 1, 0x1E6A, 0x0054, 0x0307, 0, + 1, 0x1E6B, 0x0074, 0x0307, 0, + 1, 0x1E6C, 0x0054, 0x0323, 0, + 1, 0x1E6D, 0x0074, 0x0323, 0, + 1, 0x1E6E, 0x0054, 0x0331, 0, + 1, 0x1E6F, 0x0074, 0x0331, 0, + 1, 0x1E70, 0x0054, 0x032D, 0, + 1, 0x1E71, 0x0074, 0x032D, 0, + 1, 0x1E72, 0x0055, 0x0324, 0, + 1, 0x1E73, 0x0075, 0x0324, 0, + 1, 0x1E74, 0x0055, 0x0330, 0, + 1, 0x1E75, 0x0075, 0x0330, 0, + 1, 0x1E76, 0x0055, 0x032D, 0, + 1, 0x1E77, 0x0075, 0x032D, 0, + 1, 0x1E78, 0x0168, 0x0301, 0, + 1, 0x1E79, 0x0169, 0x0301, 0, + 1, 0x1E7A, 0x016A, 0x0308, 0, + 1, 0x1E7B, 0x016B, 0x0308, 0, + 1, 0x1E7C, 0x0056, 0x0303, 0, + 1, 0x1E7D, 0x0076, 0x0303, 0, + 1, 0x1E7E, 0x0056, 0x0323, 0, + 1, 0x1E7F, 0x0076, 0x0323, 0, + 1, 0x1E80, 0x0057, 0x0300, 0, + 1, 0x1E81, 0x0077, 0x0300, 0, + 1, 0x1E82, 0x0057, 0x0301, 0, + 1, 0x1E83, 0x0077, 0x0301, 0, + 1, 0x1E84, 0x0057, 0x0308, 0, + 1, 0x1E85, 0x0077, 0x0308, 0, + 1, 0x1E86, 0x0057, 0x0307, 0, + 1, 0x1E87, 0x0077, 0x0307, 0, + 1, 0x1E88, 0x0057, 0x0323, 0, + 1, 0x1E89, 0x0077, 0x0323, 0, + 1, 0x1E8A, 0x0058, 0x0307, 0, + 1, 0x1E8B, 0x0078, 0x0307, 0, + 1, 0x1E8C, 0x0058, 0x0308, 0, + 1, 0x1E8D, 0x0078, 0x0308, 0, + 1, 0x1E8E, 0x0059, 0x0307, 0, + 1, 0x1E8F, 0x0079, 0x0307, 0, + 1, 0x1E90, 0x005A, 0x0302, 0, + 1, 0x1E91, 0x007A, 0x0302, 0, + 1, 0x1E92, 0x005A, 0x0323, 0, + 1, 0x1E93, 0x007A, 0x0323, 0, + 1, 0x1E94, 0x005A, 0x0331, 0, + 1, 0x1E95, 0x007A, 0x0331, 0, + 1, 0x1E96, 0x0068, 0x0331, 0, + 1, 0x1E97, 0x0074, 0x0308, 0, + 1, 0x1E98, 0x0077, 0x030A, 0, + 1, 0x1E99, 0x0079, 0x030A, 0, + 16, 0x1E9A, 0x0061, 0x02BE, 0, + 1, 0x1E9B, 0x017F, 0x0307, 0, + 1, 0x1EA0, 0x0041, 0x0323, 0, + 1, 0x1EA1, 0x0061, 0x0323, 0, + 1, 0x1EA2, 0x0041, 0x0309, 0, + 1, 0x1EA3, 0x0061, 0x0309, 0, + 1, 0x1EA4, 0x00C2, 0x0301, 0, + 1, 0x1EA5, 0x00E2, 0x0301, 0, + 1, 0x1EA6, 0x00C2, 0x0300, 0, + 1, 0x1EA7, 0x00E2, 0x0300, 0, + 1, 0x1EA8, 0x00C2, 0x0309, 0, + 1, 0x1EA9, 0x00E2, 0x0309, 0, + 1, 0x1EAA, 0x00C2, 0x0303, 0, + 1, 0x1EAB, 0x00E2, 0x0303, 0, + 1, 0x1EAC, 0x1EA0, 0x0302, 0, + 1, 0x1EAD, 0x1EA1, 0x0302, 0, + 1, 0x1EAE, 0x0102, 0x0301, 0, + 1, 0x1EAF, 0x0103, 0x0301, 0, + 1, 0x1EB0, 0x0102, 0x0300, 0, + 1, 0x1EB1, 0x0103, 0x0300, 0, + 1, 0x1EB2, 0x0102, 0x0309, 0, + 1, 0x1EB3, 0x0103, 0x0309, 0, + 1, 0x1EB4, 0x0102, 0x0303, 0, + 1, 0x1EB5, 0x0103, 0x0303, 0, + 1, 0x1EB6, 0x1EA0, 0x0306, 0, + 1, 0x1EB7, 0x1EA1, 0x0306, 0, + 1, 0x1EB8, 0x0045, 0x0323, 0, + 1, 0x1EB9, 0x0065, 0x0323, 0, + 1, 0x1EBA, 0x0045, 0x0309, 0, + 1, 0x1EBB, 0x0065, 0x0309, 0, + 1, 0x1EBC, 0x0045, 0x0303, 0, + 1, 0x1EBD, 0x0065, 0x0303, 0, + 1, 0x1EBE, 0x00CA, 0x0301, 0, + 1, 0x1EBF, 0x00EA, 0x0301, 0, + 1, 0x1EC0, 0x00CA, 0x0300, 0, + 1, 0x1EC1, 0x00EA, 0x0300, 0, + 1, 0x1EC2, 0x00CA, 0x0309, 0, + 1, 0x1EC3, 0x00EA, 0x0309, 0, + 1, 0x1EC4, 0x00CA, 0x0303, 0, + 1, 0x1EC5, 0x00EA, 0x0303, 0, + 1, 0x1EC6, 0x1EB8, 0x0302, 0, + 1, 0x1EC7, 0x1EB9, 0x0302, 0, + 1, 0x1EC8, 0x0049, 0x0309, 0, + 1, 0x1EC9, 0x0069, 0x0309, 0, + 1, 0x1ECA, 0x0049, 0x0323, 0, + 1, 0x1ECB, 0x0069, 0x0323, 0, + 1, 0x1ECC, 0x004F, 0x0323, 0, + 1, 0x1ECD, 0x006F, 0x0323, 0, + 1, 0x1ECE, 0x004F, 0x0309, 0, + 1, 0x1ECF, 0x006F, 0x0309, 0, + 1, 0x1ED0, 0x00D4, 0x0301, 0, + 1, 0x1ED1, 0x00F4, 0x0301, 0, + 1, 0x1ED2, 0x00D4, 0x0300, 0, + 1, 0x1ED3, 0x00F4, 0x0300, 0, + 1, 0x1ED4, 0x00D4, 0x0309, 0, + 1, 0x1ED5, 0x00F4, 0x0309, 0, + 1, 0x1ED6, 0x00D4, 0x0303, 0, + 1, 0x1ED7, 0x00F4, 0x0303, 0, + 1, 0x1ED8, 0x1ECC, 0x0302, 0, + 1, 0x1ED9, 0x1ECD, 0x0302, 0, + 1, 0x1EDA, 0x01A0, 0x0301, 0, + 1, 0x1EDB, 0x01A1, 0x0301, 0, + 1, 0x1EDC, 0x01A0, 0x0300, 0, + 1, 0x1EDD, 0x01A1, 0x0300, 0, + 1, 0x1EDE, 0x01A0, 0x0309, 0, + 1, 0x1EDF, 0x01A1, 0x0309, 0, + 1, 0x1EE0, 0x01A0, 0x0303, 0, + 1, 0x1EE1, 0x01A1, 0x0303, 0, + 1, 0x1EE2, 0x01A0, 0x0323, 0, + 1, 0x1EE3, 0x01A1, 0x0323, 0, + 1, 0x1EE4, 0x0055, 0x0323, 0, + 1, 0x1EE5, 0x0075, 0x0323, 0, + 1, 0x1EE6, 0x0055, 0x0309, 0, + 1, 0x1EE7, 0x0075, 0x0309, 0, + 1, 0x1EE8, 0x01AF, 0x0301, 0, + 1, 0x1EE9, 0x01B0, 0x0301, 0, + 1, 0x1EEA, 0x01AF, 0x0300, 0, + 1, 0x1EEB, 0x01B0, 0x0300, 0, + 1, 0x1EEC, 0x01AF, 0x0309, 0, + 1, 0x1EED, 0x01B0, 0x0309, 0, + 1, 0x1EEE, 0x01AF, 0x0303, 0, + 1, 0x1EEF, 0x01B0, 0x0303, 0, + 1, 0x1EF0, 0x01AF, 0x0323, 0, + 1, 0x1EF1, 0x01B0, 0x0323, 0, + 1, 0x1EF2, 0x0059, 0x0300, 0, + 1, 0x1EF3, 0x0079, 0x0300, 0, + 1, 0x1EF4, 0x0059, 0x0323, 0, + 1, 0x1EF5, 0x0079, 0x0323, 0, + 1, 0x1EF6, 0x0059, 0x0309, 0, + 1, 0x1EF7, 0x0079, 0x0309, 0, + 1, 0x1EF8, 0x0059, 0x0303, 0, + 1, 0x1EF9, 0x0079, 0x0303, 0, + 1, 0x1F00, 0x03B1, 0x0313, 0, + 1, 0x1F01, 0x03B1, 0x0314, 0, + 1, 0x1F02, 0x1F00, 0x0300, 0, + 1, 0x1F03, 0x1F01, 0x0300, 0, + 1, 0x1F04, 0x1F00, 0x0301, 0, + 1, 0x1F05, 0x1F01, 0x0301, 0, + 1, 0x1F06, 0x1F00, 0x0342, 0, + 1, 0x1F07, 0x1F01, 0x0342, 0, + 1, 0x1F08, 0x0391, 0x0313, 0, + 1, 0x1F09, 0x0391, 0x0314, 0, + 1, 0x1F0A, 0x1F08, 0x0300, 0, + 1, 0x1F0B, 0x1F09, 0x0300, 0, + 1, 0x1F0C, 0x1F08, 0x0301, 0, + 1, 0x1F0D, 0x1F09, 0x0301, 0, + 1, 0x1F0E, 0x1F08, 0x0342, 0, + 1, 0x1F0F, 0x1F09, 0x0342, 0, + 1, 0x1F10, 0x03B5, 0x0313, 0, + 1, 0x1F11, 0x03B5, 0x0314, 0, + 1, 0x1F12, 0x1F10, 0x0300, 0, + 1, 0x1F13, 0x1F11, 0x0300, 0, + 1, 0x1F14, 0x1F10, 0x0301, 0, + 1, 0x1F15, 0x1F11, 0x0301, 0, + 1, 0x1F18, 0x0395, 0x0313, 0, + 1, 0x1F19, 0x0395, 0x0314, 0, + 1, 0x1F1A, 0x1F18, 0x0300, 0, + 1, 0x1F1B, 0x1F19, 0x0300, 0, + 1, 0x1F1C, 0x1F18, 0x0301, 0, + 1, 0x1F1D, 0x1F19, 0x0301, 0, + 1, 0x1F20, 0x03B7, 0x0313, 0, + 1, 0x1F21, 0x03B7, 0x0314, 0, + 1, 0x1F22, 0x1F20, 0x0300, 0, + 1, 0x1F23, 0x1F21, 0x0300, 0, + 1, 0x1F24, 0x1F20, 0x0301, 0, + 1, 0x1F25, 0x1F21, 0x0301, 0, + 1, 0x1F26, 0x1F20, 0x0342, 0, + 1, 0x1F27, 0x1F21, 0x0342, 0, + 1, 0x1F28, 0x0397, 0x0313, 0, + 1, 0x1F29, 0x0397, 0x0314, 0, + 1, 0x1F2A, 0x1F28, 0x0300, 0, + 1, 0x1F2B, 0x1F29, 0x0300, 0, + 1, 0x1F2C, 0x1F28, 0x0301, 0, + 1, 0x1F2D, 0x1F29, 0x0301, 0, + 1, 0x1F2E, 0x1F28, 0x0342, 0, + 1, 0x1F2F, 0x1F29, 0x0342, 0, + 1, 0x1F30, 0x03B9, 0x0313, 0, + 1, 0x1F31, 0x03B9, 0x0314, 0, + 1, 0x1F32, 0x1F30, 0x0300, 0, + 1, 0x1F33, 0x1F31, 0x0300, 0, + 1, 0x1F34, 0x1F30, 0x0301, 0, + 1, 0x1F35, 0x1F31, 0x0301, 0, + 1, 0x1F36, 0x1F30, 0x0342, 0, + 1, 0x1F37, 0x1F31, 0x0342, 0, + 1, 0x1F38, 0x0399, 0x0313, 0, + 1, 0x1F39, 0x0399, 0x0314, 0, + 1, 0x1F3A, 0x1F38, 0x0300, 0, + 1, 0x1F3B, 0x1F39, 0x0300, 0, + 1, 0x1F3C, 0x1F38, 0x0301, 0, + 1, 0x1F3D, 0x1F39, 0x0301, 0, + 1, 0x1F3E, 0x1F38, 0x0342, 0, + 1, 0x1F3F, 0x1F39, 0x0342, 0, + 1, 0x1F40, 0x03BF, 0x0313, 0, + 1, 0x1F41, 0x03BF, 0x0314, 0, + 1, 0x1F42, 0x1F40, 0x0300, 0, + 1, 0x1F43, 0x1F41, 0x0300, 0, + 1, 0x1F44, 0x1F40, 0x0301, 0, + 1, 0x1F45, 0x1F41, 0x0301, 0, + 1, 0x1F48, 0x039F, 0x0313, 0, + 1, 0x1F49, 0x039F, 0x0314, 0, + 1, 0x1F4A, 0x1F48, 0x0300, 0, + 1, 0x1F4B, 0x1F49, 0x0300, 0, + 1, 0x1F4C, 0x1F48, 0x0301, 0, + 1, 0x1F4D, 0x1F49, 0x0301, 0, + 1, 0x1F50, 0x03C5, 0x0313, 0, + 1, 0x1F51, 0x03C5, 0x0314, 0, + 1, 0x1F52, 0x1F50, 0x0300, 0, + 1, 0x1F53, 0x1F51, 0x0300, 0, + 1, 0x1F54, 0x1F50, 0x0301, 0, + 1, 0x1F55, 0x1F51, 0x0301, 0, + 1, 0x1F56, 0x1F50, 0x0342, 0, + 1, 0x1F57, 0x1F51, 0x0342, 0, + 1, 0x1F59, 0x03A5, 0x0314, 0, + 1, 0x1F5B, 0x1F59, 0x0300, 0, + 1, 0x1F5D, 0x1F59, 0x0301, 0, + 1, 0x1F5F, 0x1F59, 0x0342, 0, + 1, 0x1F60, 0x03C9, 0x0313, 0, + 1, 0x1F61, 0x03C9, 0x0314, 0, + 1, 0x1F62, 0x1F60, 0x0300, 0, + 1, 0x1F63, 0x1F61, 0x0300, 0, + 1, 0x1F64, 0x1F60, 0x0301, 0, + 1, 0x1F65, 0x1F61, 0x0301, 0, + 1, 0x1F66, 0x1F60, 0x0342, 0, + 1, 0x1F67, 0x1F61, 0x0342, 0, + 1, 0x1F68, 0x03A9, 0x0313, 0, + 1, 0x1F69, 0x03A9, 0x0314, 0, + 1, 0x1F6A, 0x1F68, 0x0300, 0, + 1, 0x1F6B, 0x1F69, 0x0300, 0, + 1, 0x1F6C, 0x1F68, 0x0301, 0, + 1, 0x1F6D, 0x1F69, 0x0301, 0, + 1, 0x1F6E, 0x1F68, 0x0342, 0, + 1, 0x1F6F, 0x1F69, 0x0342, 0, + 1, 0x1F70, 0x03B1, 0x0300, 0, + 1, 0x1F71, 0x03AC, 0, + 1, 0x1F72, 0x03B5, 0x0300, 0, + 1, 0x1F73, 0x03AD, 0, + 1, 0x1F74, 0x03B7, 0x0300, 0, + 1, 0x1F75, 0x03AE, 0, + 1, 0x1F76, 0x03B9, 0x0300, 0, + 1, 0x1F77, 0x03AF, 0, + 1, 0x1F78, 0x03BF, 0x0300, 0, + 1, 0x1F79, 0x03CC, 0, + 1, 0x1F7A, 0x03C5, 0x0300, 0, + 1, 0x1F7B, 0x03CD, 0, + 1, 0x1F7C, 0x03C9, 0x0300, 0, + 1, 0x1F7D, 0x03CE, 0, + 1, 0x1F80, 0x1F00, 0x0345, 0, + 1, 0x1F81, 0x1F01, 0x0345, 0, + 1, 0x1F82, 0x1F02, 0x0345, 0, + 1, 0x1F83, 0x1F03, 0x0345, 0, + 1, 0x1F84, 0x1F04, 0x0345, 0, + 1, 0x1F85, 0x1F05, 0x0345, 0, + 1, 0x1F86, 0x1F06, 0x0345, 0, + 1, 0x1F87, 0x1F07, 0x0345, 0, + 1, 0x1F88, 0x1F08, 0x0345, 0, + 1, 0x1F89, 0x1F09, 0x0345, 0, + 1, 0x1F8A, 0x1F0A, 0x0345, 0, + 1, 0x1F8B, 0x1F0B, 0x0345, 0, + 1, 0x1F8C, 0x1F0C, 0x0345, 0, + 1, 0x1F8D, 0x1F0D, 0x0345, 0, + 1, 0x1F8E, 0x1F0E, 0x0345, 0, + 1, 0x1F8F, 0x1F0F, 0x0345, 0, + 1, 0x1F90, 0x1F20, 0x0345, 0, + 1, 0x1F91, 0x1F21, 0x0345, 0, + 1, 0x1F92, 0x1F22, 0x0345, 0, + 1, 0x1F93, 0x1F23, 0x0345, 0, + 1, 0x1F94, 0x1F24, 0x0345, 0, + 1, 0x1F95, 0x1F25, 0x0345, 0, + 1, 0x1F96, 0x1F26, 0x0345, 0, + 1, 0x1F97, 0x1F27, 0x0345, 0, + 1, 0x1F98, 0x1F28, 0x0345, 0, + 1, 0x1F99, 0x1F29, 0x0345, 0, + 1, 0x1F9A, 0x1F2A, 0x0345, 0, + 1, 0x1F9B, 0x1F2B, 0x0345, 0, + 1, 0x1F9C, 0x1F2C, 0x0345, 0, + 1, 0x1F9D, 0x1F2D, 0x0345, 0, + 1, 0x1F9E, 0x1F2E, 0x0345, 0, + 1, 0x1F9F, 0x1F2F, 0x0345, 0, + 1, 0x1FA0, 0x1F60, 0x0345, 0, + 1, 0x1FA1, 0x1F61, 0x0345, 0, + 1, 0x1FA2, 0x1F62, 0x0345, 0, + 1, 0x1FA3, 0x1F63, 0x0345, 0, + 1, 0x1FA4, 0x1F64, 0x0345, 0, + 1, 0x1FA5, 0x1F65, 0x0345, 0, + 1, 0x1FA6, 0x1F66, 0x0345, 0, + 1, 0x1FA7, 0x1F67, 0x0345, 0, + 1, 0x1FA8, 0x1F68, 0x0345, 0, + 1, 0x1FA9, 0x1F69, 0x0345, 0, + 1, 0x1FAA, 0x1F6A, 0x0345, 0, + 1, 0x1FAB, 0x1F6B, 0x0345, 0, + 1, 0x1FAC, 0x1F6C, 0x0345, 0, + 1, 0x1FAD, 0x1F6D, 0x0345, 0, + 1, 0x1FAE, 0x1F6E, 0x0345, 0, + 1, 0x1FAF, 0x1F6F, 0x0345, 0, + 1, 0x1FB0, 0x03B1, 0x0306, 0, + 1, 0x1FB1, 0x03B1, 0x0304, 0, + 1, 0x1FB2, 0x1F70, 0x0345, 0, + 1, 0x1FB3, 0x03B1, 0x0345, 0, + 1, 0x1FB4, 0x03AC, 0x0345, 0, + 1, 0x1FB6, 0x03B1, 0x0342, 0, + 1, 0x1FB7, 0x1FB6, 0x0345, 0, + 1, 0x1FB8, 0x0391, 0x0306, 0, + 1, 0x1FB9, 0x0391, 0x0304, 0, + 1, 0x1FBA, 0x0391, 0x0300, 0, + 1, 0x1FBB, 0x0386, 0, + 1, 0x1FBC, 0x0391, 0x0345, 0, + 16, 0x1FBD, 0x0020, 0x0313, 0, + 1, 0x1FBE, 0x03B9, 0, + 16, 0x1FBF, 0x0020, 0x0313, 0, + 16, 0x1FC0, 0x0020, 0x0342, 0, + 1, 0x1FC1, 0x00A8, 0x0342, 0, + 1, 0x1FC2, 0x1F74, 0x0345, 0, + 1, 0x1FC3, 0x03B7, 0x0345, 0, + 1, 0x1FC4, 0x03AE, 0x0345, 0, + 1, 0x1FC6, 0x03B7, 0x0342, 0, + 1, 0x1FC7, 0x1FC6, 0x0345, 0, + 1, 0x1FC8, 0x0395, 0x0300, 0, + 1, 0x1FC9, 0x0388, 0, + 1, 0x1FCA, 0x0397, 0x0300, 0, + 1, 0x1FCB, 0x0389, 0, + 1, 0x1FCC, 0x0397, 0x0345, 0, + 1, 0x1FCD, 0x1FBF, 0x0300, 0, + 1, 0x1FCE, 0x1FBF, 0x0301, 0, + 1, 0x1FCF, 0x1FBF, 0x0342, 0, + 1, 0x1FD0, 0x03B9, 0x0306, 0, + 1, 0x1FD1, 0x03B9, 0x0304, 0, + 1, 0x1FD2, 0x03CA, 0x0300, 0, + 1, 0x1FD3, 0x0390, 0, + 1, 0x1FD6, 0x03B9, 0x0342, 0, + 1, 0x1FD7, 0x03CA, 0x0342, 0, + 1, 0x1FD8, 0x0399, 0x0306, 0, + 1, 0x1FD9, 0x0399, 0x0304, 0, + 1, 0x1FDA, 0x0399, 0x0300, 0, + 1, 0x1FDB, 0x038A, 0, + 1, 0x1FDD, 0x1FFE, 0x0300, 0, + 1, 0x1FDE, 0x1FFE, 0x0301, 0, + 1, 0x1FDF, 0x1FFE, 0x0342, 0, + 1, 0x1FE0, 0x03C5, 0x0306, 0, + 1, 0x1FE1, 0x03C5, 0x0304, 0, + 1, 0x1FE2, 0x03CB, 0x0300, 0, + 1, 0x1FE3, 0x03B0, 0, + 1, 0x1FE4, 0x03C1, 0x0313, 0, + 1, 0x1FE5, 0x03C1, 0x0314, 0, + 1, 0x1FE6, 0x03C5, 0x0342, 0, + 1, 0x1FE7, 0x03CB, 0x0342, 0, + 1, 0x1FE8, 0x03A5, 0x0306, 0, + 1, 0x1FE9, 0x03A5, 0x0304, 0, + 1, 0x1FEA, 0x03A5, 0x0300, 0, + 1, 0x1FEB, 0x038E, 0, + 1, 0x1FEC, 0x03A1, 0x0314, 0, + 1, 0x1FED, 0x00A8, 0x0300, 0, + 1, 0x1FEE, 0x0385, 0, + 1, 0x1FEF, 0x0060, 0, + 1, 0x1FF2, 0x1F7C, 0x0345, 0, + 1, 0x1FF3, 0x03C9, 0x0345, 0, + 1, 0x1FF4, 0x03CE, 0x0345, 0, + 1, 0x1FF6, 0x03C9, 0x0342, 0, + 1, 0x1FF7, 0x1FF6, 0x0345, 0, + 1, 0x1FF8, 0x039F, 0x0300, 0, + 1, 0x1FF9, 0x038C, 0, + 1, 0x1FFA, 0x03A9, 0x0300, 0, + 1, 0x1FFB, 0x038F, 0, + 1, 0x1FFC, 0x03A9, 0x0345, 0, + 1, 0x1FFD, 0x00B4, 0, + 16, 0x1FFE, 0x0020, 0x0314, 0, + 1, 0x2000, 0x2002, 0, + 1, 0x2001, 0x2003, 0, + 16, 0x2002, 0x0020, 0, + 16, 0x2003, 0x0020, 0, + 16, 0x2004, 0x0020, 0, + 16, 0x2005, 0x0020, 0, + 16, 0x2006, 0x0020, 0, + 3, 0x2007, 0x0020, 0, + 16, 0x2008, 0x0020, 0, + 16, 0x2009, 0x0020, 0, + 16, 0x200A, 0x0020, 0, + 3, 0x2011, 0x2010, 0, + 16, 0x2017, 0x0020, 0x0333, 0, + 16, 0x2024, 0x002E, 0, + 16, 0x2025, 0x002E, 0x002E, 0, + 16, 0x2026, 0x002E, 0x002E, 0x002E, 0, + 3, 0x202F, 0x0020, 0, + 16, 0x2033, 0x2032, 0x2032, 0, + 16, 0x2034, 0x2032, 0x2032, 0x2032, 0, + 16, 0x2036, 0x2035, 0x2035, 0, + 16, 0x2037, 0x2035, 0x2035, 0x2035, 0, + 16, 0x203C, 0x0021, 0x0021, 0, + 16, 0x203E, 0x0020, 0x0305, 0, + 16, 0x2047, 0x003F, 0x003F, 0, + 16, 0x2048, 0x003F, 0x0021, 0, + 16, 0x2049, 0x0021, 0x003F, 0, + 16, 0x2057, 0x2032, 0x2032, 0x2032, 0x2032, 0, + 16, 0x205F, 0x0020, 0, + 9, 0x2070, 0x0030, 0, + 9, 0x2071, 0x0069, 0, + 9, 0x2074, 0x0034, 0, + 9, 0x2075, 0x0035, 0, + 9, 0x2076, 0x0036, 0, + 9, 0x2077, 0x0037, 0, + 9, 0x2078, 0x0038, 0, + 9, 0x2079, 0x0039, 0, + 9, 0x207A, 0x002B, 0, + 9, 0x207B, 0x2212, 0, + 9, 0x207C, 0x003D, 0, + 9, 0x207D, 0x0028, 0, + 9, 0x207E, 0x0029, 0, + 9, 0x207F, 0x006E, 0, + 10, 0x2080, 0x0030, 0, + 10, 0x2081, 0x0031, 0, + 10, 0x2082, 0x0032, 0, + 10, 0x2083, 0x0033, 0, + 10, 0x2084, 0x0034, 0, + 10, 0x2085, 0x0035, 0, + 10, 0x2086, 0x0036, 0, + 10, 0x2087, 0x0037, 0, + 10, 0x2088, 0x0038, 0, + 10, 0x2089, 0x0039, 0, + 10, 0x208A, 0x002B, 0, + 10, 0x208B, 0x2212, 0, + 10, 0x208C, 0x003D, 0, + 10, 0x208D, 0x0028, 0, + 10, 0x208E, 0x0029, 0, + 16, 0x20A8, 0x0052, 0x0073, 0, + 16, 0x2100, 0x0061, 0x002F, 0x0063, 0, + 16, 0x2101, 0x0061, 0x002F, 0x0073, 0, + 2, 0x2102, 0x0043, 0, + 16, 0x2103, 0x00B0, 0x0043, 0, + 16, 0x2105, 0x0063, 0x002F, 0x006F, 0, + 16, 0x2106, 0x0063, 0x002F, 0x0075, 0, + 16, 0x2107, 0x0190, 0, + 16, 0x2109, 0x00B0, 0x0046, 0, + 2, 0x210A, 0x0067, 0, + 2, 0x210B, 0x0048, 0, + 2, 0x210C, 0x0048, 0, + 2, 0x210D, 0x0048, 0, + 2, 0x210E, 0x0068, 0, + 2, 0x210F, 0x0127, 0, + 2, 0x2110, 0x0049, 0, + 2, 0x2111, 0x0049, 0, + 2, 0x2112, 0x004C, 0, + 2, 0x2113, 0x006C, 0, + 2, 0x2115, 0x004E, 0, + 16, 0x2116, 0x004E, 0x006F, 0, + 2, 0x2119, 0x0050, 0, + 2, 0x211A, 0x0051, 0, + 2, 0x211B, 0x0052, 0, + 2, 0x211C, 0x0052, 0, + 2, 0x211D, 0x0052, 0, + 9, 0x2120, 0x0053, 0x004D, 0, + 16, 0x2121, 0x0054, 0x0045, 0x004C, 0, + 9, 0x2122, 0x0054, 0x004D, 0, + 2, 0x2124, 0x005A, 0, + 1, 0x2126, 0x03A9, 0, + 2, 0x2128, 0x005A, 0, + 1, 0x212A, 0x004B, 0, + 1, 0x212B, 0x00C5, 0, + 2, 0x212C, 0x0042, 0, + 2, 0x212D, 0x0043, 0, + 2, 0x212F, 0x0065, 0, + 2, 0x2130, 0x0045, 0, + 2, 0x2131, 0x0046, 0, + 2, 0x2133, 0x004D, 0, + 2, 0x2134, 0x006F, 0, + 16, 0x2135, 0x05D0, 0, + 16, 0x2136, 0x05D1, 0, + 16, 0x2137, 0x05D2, 0, + 16, 0x2138, 0x05D3, 0, + 2, 0x2139, 0x0069, 0, + 2, 0x213D, 0x03B3, 0, + 2, 0x213E, 0x0393, 0, + 2, 0x213F, 0x03A0, 0, + 2, 0x2140, 0x2211, 0, + 2, 0x2145, 0x0044, 0, + 2, 0x2146, 0x0064, 0, + 2, 0x2147, 0x0065, 0, + 2, 0x2148, 0x0069, 0, + 2, 0x2149, 0x006A, 0, + 17, 0x2153, 0x0031, 0x2044, 0x0033, 0, + 17, 0x2154, 0x0032, 0x2044, 0x0033, 0, + 17, 0x2155, 0x0031, 0x2044, 0x0035, 0, + 17, 0x2156, 0x0032, 0x2044, 0x0035, 0, + 17, 0x2157, 0x0033, 0x2044, 0x0035, 0, + 17, 0x2158, 0x0034, 0x2044, 0x0035, 0, + 17, 0x2159, 0x0031, 0x2044, 0x0036, 0, + 17, 0x215A, 0x0035, 0x2044, 0x0036, 0, + 17, 0x215B, 0x0031, 0x2044, 0x0038, 0, + 17, 0x215C, 0x0033, 0x2044, 0x0038, 0, + 17, 0x215D, 0x0035, 0x2044, 0x0038, 0, + 17, 0x215E, 0x0037, 0x2044, 0x0038, 0, + 17, 0x215F, 0x0031, 0x2044, 0, + 16, 0x2160, 0x0049, 0, + 16, 0x2161, 0x0049, 0x0049, 0, + 16, 0x2162, 0x0049, 0x0049, 0x0049, 0, + 16, 0x2163, 0x0049, 0x0056, 0, + 16, 0x2164, 0x0056, 0, + 16, 0x2165, 0x0056, 0x0049, 0, + 16, 0x2166, 0x0056, 0x0049, 0x0049, 0, + 16, 0x2167, 0x0056, 0x0049, 0x0049, 0x0049, 0, + 16, 0x2168, 0x0049, 0x0058, 0, + 16, 0x2169, 0x0058, 0, + 16, 0x216A, 0x0058, 0x0049, 0, + 16, 0x216B, 0x0058, 0x0049, 0x0049, 0, + 16, 0x216C, 0x004C, 0, + 16, 0x216D, 0x0043, 0, + 16, 0x216E, 0x0044, 0, + 16, 0x216F, 0x004D, 0, + 16, 0x2170, 0x0069, 0, + 16, 0x2171, 0x0069, 0x0069, 0, + 16, 0x2172, 0x0069, 0x0069, 0x0069, 0, + 16, 0x2173, 0x0069, 0x0076, 0, + 16, 0x2174, 0x0076, 0, + 16, 0x2175, 0x0076, 0x0069, 0, + 16, 0x2176, 0x0076, 0x0069, 0x0069, 0, + 16, 0x2177, 0x0076, 0x0069, 0x0069, 0x0069, 0, + 16, 0x2178, 0x0069, 0x0078, 0, + 16, 0x2179, 0x0078, 0, + 16, 0x217A, 0x0078, 0x0069, 0, + 16, 0x217B, 0x0078, 0x0069, 0x0069, 0, + 16, 0x217C, 0x006C, 0, + 16, 0x217D, 0x0063, 0, + 16, 0x217E, 0x0064, 0, + 16, 0x217F, 0x006D, 0, + 1, 0x219A, 0x2190, 0x0338, 0, + 1, 0x219B, 0x2192, 0x0338, 0, + 1, 0x21AE, 0x2194, 0x0338, 0, + 1, 0x21CD, 0x21D0, 0x0338, 0, + 1, 0x21CE, 0x21D4, 0x0338, 0, + 1, 0x21CF, 0x21D2, 0x0338, 0, + 1, 0x2204, 0x2203, 0x0338, 0, + 1, 0x2209, 0x2208, 0x0338, 0, + 1, 0x220C, 0x220B, 0x0338, 0, + 1, 0x2224, 0x2223, 0x0338, 0, + 1, 0x2226, 0x2225, 0x0338, 0, + 16, 0x222C, 0x222B, 0x222B, 0, + 16, 0x222D, 0x222B, 0x222B, 0x222B, 0, + 16, 0x222F, 0x222E, 0x222E, 0, + 16, 0x2230, 0x222E, 0x222E, 0x222E, 0, + 1, 0x2241, 0x223C, 0x0338, 0, + 1, 0x2244, 0x2243, 0x0338, 0, + 1, 0x2247, 0x2245, 0x0338, 0, + 1, 0x2249, 0x2248, 0x0338, 0, + 1, 0x2260, 0x003D, 0x0338, 0, + 1, 0x2262, 0x2261, 0x0338, 0, + 1, 0x226D, 0x224D, 0x0338, 0, + 1, 0x226E, 0x003C, 0x0338, 0, + 1, 0x226F, 0x003E, 0x0338, 0, + 1, 0x2270, 0x2264, 0x0338, 0, + 1, 0x2271, 0x2265, 0x0338, 0, + 1, 0x2274, 0x2272, 0x0338, 0, + 1, 0x2275, 0x2273, 0x0338, 0, + 1, 0x2278, 0x2276, 0x0338, 0, + 1, 0x2279, 0x2277, 0x0338, 0, + 1, 0x2280, 0x227A, 0x0338, 0, + 1, 0x2281, 0x227B, 0x0338, 0, + 1, 0x2284, 0x2282, 0x0338, 0, + 1, 0x2285, 0x2283, 0x0338, 0, + 1, 0x2288, 0x2286, 0x0338, 0, + 1, 0x2289, 0x2287, 0x0338, 0, + 1, 0x22AC, 0x22A2, 0x0338, 0, + 1, 0x22AD, 0x22A8, 0x0338, 0, + 1, 0x22AE, 0x22A9, 0x0338, 0, + 1, 0x22AF, 0x22AB, 0x0338, 0, + 1, 0x22E0, 0x227C, 0x0338, 0, + 1, 0x22E1, 0x227D, 0x0338, 0, + 1, 0x22E2, 0x2291, 0x0338, 0, + 1, 0x22E3, 0x2292, 0x0338, 0, + 1, 0x22EA, 0x22B2, 0x0338, 0, + 1, 0x22EB, 0x22B3, 0x0338, 0, + 1, 0x22EC, 0x22B4, 0x0338, 0, + 1, 0x22ED, 0x22B5, 0x0338, 0, + 1, 0x2329, 0x3008, 0, + 1, 0x232A, 0x3009, 0, + 8, 0x2460, 0x0031, 0, + 8, 0x2461, 0x0032, 0, + 8, 0x2462, 0x0033, 0, + 8, 0x2463, 0x0034, 0, + 8, 0x2464, 0x0035, 0, + 8, 0x2465, 0x0036, 0, + 8, 0x2466, 0x0037, 0, + 8, 0x2467, 0x0038, 0, + 8, 0x2468, 0x0039, 0, + 8, 0x2469, 0x0031, 0x0030, 0, + 8, 0x246A, 0x0031, 0x0031, 0, + 8, 0x246B, 0x0031, 0x0032, 0, + 8, 0x246C, 0x0031, 0x0033, 0, + 8, 0x246D, 0x0031, 0x0034, 0, + 8, 0x246E, 0x0031, 0x0035, 0, + 8, 0x246F, 0x0031, 0x0036, 0, + 8, 0x2470, 0x0031, 0x0037, 0, + 8, 0x2471, 0x0031, 0x0038, 0, + 8, 0x2472, 0x0031, 0x0039, 0, + 8, 0x2473, 0x0032, 0x0030, 0, + 16, 0x2474, 0x0028, 0x0031, 0x0029, 0, + 16, 0x2475, 0x0028, 0x0032, 0x0029, 0, + 16, 0x2476, 0x0028, 0x0033, 0x0029, 0, + 16, 0x2477, 0x0028, 0x0034, 0x0029, 0, + 16, 0x2478, 0x0028, 0x0035, 0x0029, 0, + 16, 0x2479, 0x0028, 0x0036, 0x0029, 0, + 16, 0x247A, 0x0028, 0x0037, 0x0029, 0, + 16, 0x247B, 0x0028, 0x0038, 0x0029, 0, + 16, 0x247C, 0x0028, 0x0039, 0x0029, 0, + 16, 0x247D, 0x0028, 0x0031, 0x0030, 0x0029, 0, + 16, 0x247E, 0x0028, 0x0031, 0x0031, 0x0029, 0, + 16, 0x247F, 0x0028, 0x0031, 0x0032, 0x0029, 0, + 16, 0x2480, 0x0028, 0x0031, 0x0033, 0x0029, 0, + 16, 0x2481, 0x0028, 0x0031, 0x0034, 0x0029, 0, + 16, 0x2482, 0x0028, 0x0031, 0x0035, 0x0029, 0, + 16, 0x2483, 0x0028, 0x0031, 0x0036, 0x0029, 0, + 16, 0x2484, 0x0028, 0x0031, 0x0037, 0x0029, 0, + 16, 0x2485, 0x0028, 0x0031, 0x0038, 0x0029, 0, + 16, 0x2486, 0x0028, 0x0031, 0x0039, 0x0029, 0, + 16, 0x2487, 0x0028, 0x0032, 0x0030, 0x0029, 0, + 16, 0x2488, 0x0031, 0x002E, 0, + 16, 0x2489, 0x0032, 0x002E, 0, + 16, 0x248A, 0x0033, 0x002E, 0, + 16, 0x248B, 0x0034, 0x002E, 0, + 16, 0x248C, 0x0035, 0x002E, 0, + 16, 0x248D, 0x0036, 0x002E, 0, + 16, 0x248E, 0x0037, 0x002E, 0, + 16, 0x248F, 0x0038, 0x002E, 0, + 16, 0x2490, 0x0039, 0x002E, 0, + 16, 0x2491, 0x0031, 0x0030, 0x002E, 0, + 16, 0x2492, 0x0031, 0x0031, 0x002E, 0, + 16, 0x2493, 0x0031, 0x0032, 0x002E, 0, + 16, 0x2494, 0x0031, 0x0033, 0x002E, 0, + 16, 0x2495, 0x0031, 0x0034, 0x002E, 0, + 16, 0x2496, 0x0031, 0x0035, 0x002E, 0, + 16, 0x2497, 0x0031, 0x0036, 0x002E, 0, + 16, 0x2498, 0x0031, 0x0037, 0x002E, 0, + 16, 0x2499, 0x0031, 0x0038, 0x002E, 0, + 16, 0x249A, 0x0031, 0x0039, 0x002E, 0, + 16, 0x249B, 0x0032, 0x0030, 0x002E, 0, + 16, 0x249C, 0x0028, 0x0061, 0x0029, 0, + 16, 0x249D, 0x0028, 0x0062, 0x0029, 0, + 16, 0x249E, 0x0028, 0x0063, 0x0029, 0, + 16, 0x249F, 0x0028, 0x0064, 0x0029, 0, + 16, 0x24A0, 0x0028, 0x0065, 0x0029, 0, + 16, 0x24A1, 0x0028, 0x0066, 0x0029, 0, + 16, 0x24A2, 0x0028, 0x0067, 0x0029, 0, + 16, 0x24A3, 0x0028, 0x0068, 0x0029, 0, + 16, 0x24A4, 0x0028, 0x0069, 0x0029, 0, + 16, 0x24A5, 0x0028, 0x006A, 0x0029, 0, + 16, 0x24A6, 0x0028, 0x006B, 0x0029, 0, + 16, 0x24A7, 0x0028, 0x006C, 0x0029, 0, + 16, 0x24A8, 0x0028, 0x006D, 0x0029, 0, + 16, 0x24A9, 0x0028, 0x006E, 0x0029, 0, + 16, 0x24AA, 0x0028, 0x006F, 0x0029, 0, + 16, 0x24AB, 0x0028, 0x0070, 0x0029, 0, + 16, 0x24AC, 0x0028, 0x0071, 0x0029, 0, + 16, 0x24AD, 0x0028, 0x0072, 0x0029, 0, + 16, 0x24AE, 0x0028, 0x0073, 0x0029, 0, + 16, 0x24AF, 0x0028, 0x0074, 0x0029, 0, + 16, 0x24B0, 0x0028, 0x0075, 0x0029, 0, + 16, 0x24B1, 0x0028, 0x0076, 0x0029, 0, + 16, 0x24B2, 0x0028, 0x0077, 0x0029, 0, + 16, 0x24B3, 0x0028, 0x0078, 0x0029, 0, + 16, 0x24B4, 0x0028, 0x0079, 0x0029, 0, + 16, 0x24B5, 0x0028, 0x007A, 0x0029, 0, + 8, 0x24B6, 0x0041, 0, + 8, 0x24B7, 0x0042, 0, + 8, 0x24B8, 0x0043, 0, + 8, 0x24B9, 0x0044, 0, + 8, 0x24BA, 0x0045, 0, + 8, 0x24BB, 0x0046, 0, + 8, 0x24BC, 0x0047, 0, + 8, 0x24BD, 0x0048, 0, + 8, 0x24BE, 0x0049, 0, + 8, 0x24BF, 0x004A, 0, + 8, 0x24C0, 0x004B, 0, + 8, 0x24C1, 0x004C, 0, + 8, 0x24C2, 0x004D, 0, + 8, 0x24C3, 0x004E, 0, + 8, 0x24C4, 0x004F, 0, + 8, 0x24C5, 0x0050, 0, + 8, 0x24C6, 0x0051, 0, + 8, 0x24C7, 0x0052, 0, + 8, 0x24C8, 0x0053, 0, + 8, 0x24C9, 0x0054, 0, + 8, 0x24CA, 0x0055, 0, + 8, 0x24CB, 0x0056, 0, + 8, 0x24CC, 0x0057, 0, + 8, 0x24CD, 0x0058, 0, + 8, 0x24CE, 0x0059, 0, + 8, 0x24CF, 0x005A, 0, + 8, 0x24D0, 0x0061, 0, + 8, 0x24D1, 0x0062, 0, + 8, 0x24D2, 0x0063, 0, + 8, 0x24D3, 0x0064, 0, + 8, 0x24D4, 0x0065, 0, + 8, 0x24D5, 0x0066, 0, + 8, 0x24D6, 0x0067, 0, + 8, 0x24D7, 0x0068, 0, + 8, 0x24D8, 0x0069, 0, + 8, 0x24D9, 0x006A, 0, + 8, 0x24DA, 0x006B, 0, + 8, 0x24DB, 0x006C, 0, + 8, 0x24DC, 0x006D, 0, + 8, 0x24DD, 0x006E, 0, + 8, 0x24DE, 0x006F, 0, + 8, 0x24DF, 0x0070, 0, + 8, 0x24E0, 0x0071, 0, + 8, 0x24E1, 0x0072, 0, + 8, 0x24E2, 0x0073, 0, + 8, 0x24E3, 0x0074, 0, + 8, 0x24E4, 0x0075, 0, + 8, 0x24E5, 0x0076, 0, + 8, 0x24E6, 0x0077, 0, + 8, 0x24E7, 0x0078, 0, + 8, 0x24E8, 0x0079, 0, + 8, 0x24E9, 0x007A, 0, + 8, 0x24EA, 0x0030, 0, + 16, 0x2A0C, 0x222B, 0x222B, 0x222B, 0x222B, 0, + 16, 0x2A74, 0x003A, 0x003A, 0x003D, 0, + 16, 0x2A75, 0x003D, 0x003D, 0, + 16, 0x2A76, 0x003D, 0x003D, 0x003D, 0, + 1, 0x2ADC, 0x2ADD, 0x0338, 0, + 16, 0x2E9F, 0x6BCD, 0, + 16, 0x2EF3, 0x9F9F, 0, + 16, 0x2F00, 0x4E00, 0, + 16, 0x2F01, 0x4E28, 0, + 16, 0x2F02, 0x4E36, 0, + 16, 0x2F03, 0x4E3F, 0, + 16, 0x2F04, 0x4E59, 0, + 16, 0x2F05, 0x4E85, 0, + 16, 0x2F06, 0x4E8C, 0, + 16, 0x2F07, 0x4EA0, 0, + 16, 0x2F08, 0x4EBA, 0, + 16, 0x2F09, 0x513F, 0, + 16, 0x2F0A, 0x5165, 0, + 16, 0x2F0B, 0x516B, 0, + 16, 0x2F0C, 0x5182, 0, + 16, 0x2F0D, 0x5196, 0, + 16, 0x2F0E, 0x51AB, 0, + 16, 0x2F0F, 0x51E0, 0, + 16, 0x2F10, 0x51F5, 0, + 16, 0x2F11, 0x5200, 0, + 16, 0x2F12, 0x529B, 0, + 16, 0x2F13, 0x52F9, 0, + 16, 0x2F14, 0x5315, 0, + 16, 0x2F15, 0x531A, 0, + 16, 0x2F16, 0x5338, 0, + 16, 0x2F17, 0x5341, 0, + 16, 0x2F18, 0x535C, 0, + 16, 0x2F19, 0x5369, 0, + 16, 0x2F1A, 0x5382, 0, + 16, 0x2F1B, 0x53B6, 0, + 16, 0x2F1C, 0x53C8, 0, + 16, 0x2F1D, 0x53E3, 0, + 16, 0x2F1E, 0x56D7, 0, + 16, 0x2F1F, 0x571F, 0, + 16, 0x2F20, 0x58EB, 0, + 16, 0x2F21, 0x5902, 0, + 16, 0x2F22, 0x590A, 0, + 16, 0x2F23, 0x5915, 0, + 16, 0x2F24, 0x5927, 0, + 16, 0x2F25, 0x5973, 0, + 16, 0x2F26, 0x5B50, 0, + 16, 0x2F27, 0x5B80, 0, + 16, 0x2F28, 0x5BF8, 0, + 16, 0x2F29, 0x5C0F, 0, + 16, 0x2F2A, 0x5C22, 0, + 16, 0x2F2B, 0x5C38, 0, + 16, 0x2F2C, 0x5C6E, 0, + 16, 0x2F2D, 0x5C71, 0, + 16, 0x2F2E, 0x5DDB, 0, + 16, 0x2F2F, 0x5DE5, 0, + 16, 0x2F30, 0x5DF1, 0, + 16, 0x2F31, 0x5DFE, 0, + 16, 0x2F32, 0x5E72, 0, + 16, 0x2F33, 0x5E7A, 0, + 16, 0x2F34, 0x5E7F, 0, + 16, 0x2F35, 0x5EF4, 0, + 16, 0x2F36, 0x5EFE, 0, + 16, 0x2F37, 0x5F0B, 0, + 16, 0x2F38, 0x5F13, 0, + 16, 0x2F39, 0x5F50, 0, + 16, 0x2F3A, 0x5F61, 0, + 16, 0x2F3B, 0x5F73, 0, + 16, 0x2F3C, 0x5FC3, 0, + 16, 0x2F3D, 0x6208, 0, + 16, 0x2F3E, 0x6236, 0, + 16, 0x2F3F, 0x624B, 0, + 16, 0x2F40, 0x652F, 0, + 16, 0x2F41, 0x6534, 0, + 16, 0x2F42, 0x6587, 0, + 16, 0x2F43, 0x6597, 0, + 16, 0x2F44, 0x65A4, 0, + 16, 0x2F45, 0x65B9, 0, + 16, 0x2F46, 0x65E0, 0, + 16, 0x2F47, 0x65E5, 0, + 16, 0x2F48, 0x66F0, 0, + 16, 0x2F49, 0x6708, 0, + 16, 0x2F4A, 0x6728, 0, + 16, 0x2F4B, 0x6B20, 0, + 16, 0x2F4C, 0x6B62, 0, + 16, 0x2F4D, 0x6B79, 0, + 16, 0x2F4E, 0x6BB3, 0, + 16, 0x2F4F, 0x6BCB, 0, + 16, 0x2F50, 0x6BD4, 0, + 16, 0x2F51, 0x6BDB, 0, + 16, 0x2F52, 0x6C0F, 0, + 16, 0x2F53, 0x6C14, 0, + 16, 0x2F54, 0x6C34, 0, + 16, 0x2F55, 0x706B, 0, + 16, 0x2F56, 0x722A, 0, + 16, 0x2F57, 0x7236, 0, + 16, 0x2F58, 0x723B, 0, + 16, 0x2F59, 0x723F, 0, + 16, 0x2F5A, 0x7247, 0, + 16, 0x2F5B, 0x7259, 0, + 16, 0x2F5C, 0x725B, 0, + 16, 0x2F5D, 0x72AC, 0, + 16, 0x2F5E, 0x7384, 0, + 16, 0x2F5F, 0x7389, 0, + 16, 0x2F60, 0x74DC, 0, + 16, 0x2F61, 0x74E6, 0, + 16, 0x2F62, 0x7518, 0, + 16, 0x2F63, 0x751F, 0, + 16, 0x2F64, 0x7528, 0, + 16, 0x2F65, 0x7530, 0, + 16, 0x2F66, 0x758B, 0, + 16, 0x2F67, 0x7592, 0, + 16, 0x2F68, 0x7676, 0, + 16, 0x2F69, 0x767D, 0, + 16, 0x2F6A, 0x76AE, 0, + 16, 0x2F6B, 0x76BF, 0, + 16, 0x2F6C, 0x76EE, 0, + 16, 0x2F6D, 0x77DB, 0, + 16, 0x2F6E, 0x77E2, 0, + 16, 0x2F6F, 0x77F3, 0, + 16, 0x2F70, 0x793A, 0, + 16, 0x2F71, 0x79B8, 0, + 16, 0x2F72, 0x79BE, 0, + 16, 0x2F73, 0x7A74, 0, + 16, 0x2F74, 0x7ACB, 0, + 16, 0x2F75, 0x7AF9, 0, + 16, 0x2F76, 0x7C73, 0, + 16, 0x2F77, 0x7CF8, 0, + 16, 0x2F78, 0x7F36, 0, + 16, 0x2F79, 0x7F51, 0, + 16, 0x2F7A, 0x7F8A, 0, + 16, 0x2F7B, 0x7FBD, 0, + 16, 0x2F7C, 0x8001, 0, + 16, 0x2F7D, 0x800C, 0, + 16, 0x2F7E, 0x8012, 0, + 16, 0x2F7F, 0x8033, 0, + 16, 0x2F80, 0x807F, 0, + 16, 0x2F81, 0x8089, 0, + 16, 0x2F82, 0x81E3, 0, + 16, 0x2F83, 0x81EA, 0, + 16, 0x2F84, 0x81F3, 0, + 16, 0x2F85, 0x81FC, 0, + 16, 0x2F86, 0x820C, 0, + 16, 0x2F87, 0x821B, 0, + 16, 0x2F88, 0x821F, 0, + 16, 0x2F89, 0x826E, 0, + 16, 0x2F8A, 0x8272, 0, + 16, 0x2F8B, 0x8278, 0, + 16, 0x2F8C, 0x864D, 0, + 16, 0x2F8D, 0x866B, 0, + 16, 0x2F8E, 0x8840, 0, + 16, 0x2F8F, 0x884C, 0, + 16, 0x2F90, 0x8863, 0, + 16, 0x2F91, 0x897E, 0, + 16, 0x2F92, 0x898B, 0, + 16, 0x2F93, 0x89D2, 0, + 16, 0x2F94, 0x8A00, 0, + 16, 0x2F95, 0x8C37, 0, + 16, 0x2F96, 0x8C46, 0, + 16, 0x2F97, 0x8C55, 0, + 16, 0x2F98, 0x8C78, 0, + 16, 0x2F99, 0x8C9D, 0, + 16, 0x2F9A, 0x8D64, 0, + 16, 0x2F9B, 0x8D70, 0, + 16, 0x2F9C, 0x8DB3, 0, + 16, 0x2F9D, 0x8EAB, 0, + 16, 0x2F9E, 0x8ECA, 0, + 16, 0x2F9F, 0x8F9B, 0, + 16, 0x2FA0, 0x8FB0, 0, + 16, 0x2FA1, 0x8FB5, 0, + 16, 0x2FA2, 0x9091, 0, + 16, 0x2FA3, 0x9149, 0, + 16, 0x2FA4, 0x91C6, 0, + 16, 0x2FA5, 0x91CC, 0, + 16, 0x2FA6, 0x91D1, 0, + 16, 0x2FA7, 0x9577, 0, + 16, 0x2FA8, 0x9580, 0, + 16, 0x2FA9, 0x961C, 0, + 16, 0x2FAA, 0x96B6, 0, + 16, 0x2FAB, 0x96B9, 0, + 16, 0x2FAC, 0x96E8, 0, + 16, 0x2FAD, 0x9751, 0, + 16, 0x2FAE, 0x975E, 0, + 16, 0x2FAF, 0x9762, 0, + 16, 0x2FB0, 0x9769, 0, + 16, 0x2FB1, 0x97CB, 0, + 16, 0x2FB2, 0x97ED, 0, + 16, 0x2FB3, 0x97F3, 0, + 16, 0x2FB4, 0x9801, 0, + 16, 0x2FB5, 0x98A8, 0, + 16, 0x2FB6, 0x98DB, 0, + 16, 0x2FB7, 0x98DF, 0, + 16, 0x2FB8, 0x9996, 0, + 16, 0x2FB9, 0x9999, 0, + 16, 0x2FBA, 0x99AC, 0, + 16, 0x2FBB, 0x9AA8, 0, + 16, 0x2FBC, 0x9AD8, 0, + 16, 0x2FBD, 0x9ADF, 0, + 16, 0x2FBE, 0x9B25, 0, + 16, 0x2FBF, 0x9B2F, 0, + 16, 0x2FC0, 0x9B32, 0, + 16, 0x2FC1, 0x9B3C, 0, + 16, 0x2FC2, 0x9B5A, 0, + 16, 0x2FC3, 0x9CE5, 0, + 16, 0x2FC4, 0x9E75, 0, + 16, 0x2FC5, 0x9E7F, 0, + 16, 0x2FC6, 0x9EA5, 0, + 16, 0x2FC7, 0x9EBB, 0, + 16, 0x2FC8, 0x9EC3, 0, + 16, 0x2FC9, 0x9ECD, 0, + 16, 0x2FCA, 0x9ED1, 0, + 16, 0x2FCB, 0x9EF9, 0, + 16, 0x2FCC, 0x9EFD, 0, + 16, 0x2FCD, 0x9F0E, 0, + 16, 0x2FCE, 0x9F13, 0, + 16, 0x2FCF, 0x9F20, 0, + 16, 0x2FD0, 0x9F3B, 0, + 16, 0x2FD1, 0x9F4A, 0, + 16, 0x2FD2, 0x9F52, 0, + 16, 0x2FD3, 0x9F8D, 0, + 16, 0x2FD4, 0x9F9C, 0, + 16, 0x2FD5, 0x9FA0, 0, + 12, 0x3000, 0x0020, 0, + 16, 0x3036, 0x3012, 0, + 16, 0x3038, 0x5341, 0, + 16, 0x3039, 0x5344, 0, + 16, 0x303A, 0x5345, 0, + 1, 0x304C, 0x304B, 0x3099, 0, + 1, 0x304E, 0x304D, 0x3099, 0, + 1, 0x3050, 0x304F, 0x3099, 0, + 1, 0x3052, 0x3051, 0x3099, 0, + 1, 0x3054, 0x3053, 0x3099, 0, + 1, 0x3056, 0x3055, 0x3099, 0, + 1, 0x3058, 0x3057, 0x3099, 0, + 1, 0x305A, 0x3059, 0x3099, 0, + 1, 0x305C, 0x305B, 0x3099, 0, + 1, 0x305E, 0x305D, 0x3099, 0, + 1, 0x3060, 0x305F, 0x3099, 0, + 1, 0x3062, 0x3061, 0x3099, 0, + 1, 0x3065, 0x3064, 0x3099, 0, + 1, 0x3067, 0x3066, 0x3099, 0, + 1, 0x3069, 0x3068, 0x3099, 0, + 1, 0x3070, 0x306F, 0x3099, 0, + 1, 0x3071, 0x306F, 0x309A, 0, + 1, 0x3073, 0x3072, 0x3099, 0, + 1, 0x3074, 0x3072, 0x309A, 0, + 1, 0x3076, 0x3075, 0x3099, 0, + 1, 0x3077, 0x3075, 0x309A, 0, + 1, 0x3079, 0x3078, 0x3099, 0, + 1, 0x307A, 0x3078, 0x309A, 0, + 1, 0x307C, 0x307B, 0x3099, 0, + 1, 0x307D, 0x307B, 0x309A, 0, + 1, 0x3094, 0x3046, 0x3099, 0, + 16, 0x309B, 0x0020, 0x3099, 0, + 16, 0x309C, 0x0020, 0x309A, 0, + 1, 0x309E, 0x309D, 0x3099, 0, + 11, 0x309F, 0x3088, 0x308A, 0, + 1, 0x30AC, 0x30AB, 0x3099, 0, + 1, 0x30AE, 0x30AD, 0x3099, 0, + 1, 0x30B0, 0x30AF, 0x3099, 0, + 1, 0x30B2, 0x30B1, 0x3099, 0, + 1, 0x30B4, 0x30B3, 0x3099, 0, + 1, 0x30B6, 0x30B5, 0x3099, 0, + 1, 0x30B8, 0x30B7, 0x3099, 0, + 1, 0x30BA, 0x30B9, 0x3099, 0, + 1, 0x30BC, 0x30BB, 0x3099, 0, + 1, 0x30BE, 0x30BD, 0x3099, 0, + 1, 0x30C0, 0x30BF, 0x3099, 0, + 1, 0x30C2, 0x30C1, 0x3099, 0, + 1, 0x30C5, 0x30C4, 0x3099, 0, + 1, 0x30C7, 0x30C6, 0x3099, 0, + 1, 0x30C9, 0x30C8, 0x3099, 0, + 1, 0x30D0, 0x30CF, 0x3099, 0, + 1, 0x30D1, 0x30CF, 0x309A, 0, + 1, 0x30D3, 0x30D2, 0x3099, 0, + 1, 0x30D4, 0x30D2, 0x309A, 0, + 1, 0x30D6, 0x30D5, 0x3099, 0, + 1, 0x30D7, 0x30D5, 0x309A, 0, + 1, 0x30D9, 0x30D8, 0x3099, 0, + 1, 0x30DA, 0x30D8, 0x309A, 0, + 1, 0x30DC, 0x30DB, 0x3099, 0, + 1, 0x30DD, 0x30DB, 0x309A, 0, + 1, 0x30F4, 0x30A6, 0x3099, 0, + 1, 0x30F7, 0x30EF, 0x3099, 0, + 1, 0x30F8, 0x30F0, 0x3099, 0, + 1, 0x30F9, 0x30F1, 0x3099, 0, + 1, 0x30FA, 0x30F2, 0x3099, 0, + 1, 0x30FE, 0x30FD, 0x3099, 0, + 11, 0x30FF, 0x30B3, 0x30C8, 0, + 16, 0x3131, 0x1100, 0, + 16, 0x3132, 0x1101, 0, + 16, 0x3133, 0x11AA, 0, + 16, 0x3134, 0x1102, 0, + 16, 0x3135, 0x11AC, 0, + 16, 0x3136, 0x11AD, 0, + 16, 0x3137, 0x1103, 0, + 16, 0x3138, 0x1104, 0, + 16, 0x3139, 0x1105, 0, + 16, 0x313A, 0x11B0, 0, + 16, 0x313B, 0x11B1, 0, + 16, 0x313C, 0x11B2, 0, + 16, 0x313D, 0x11B3, 0, + 16, 0x313E, 0x11B4, 0, + 16, 0x313F, 0x11B5, 0, + 16, 0x3140, 0x111A, 0, + 16, 0x3141, 0x1106, 0, + 16, 0x3142, 0x1107, 0, + 16, 0x3143, 0x1108, 0, + 16, 0x3144, 0x1121, 0, + 16, 0x3145, 0x1109, 0, + 16, 0x3146, 0x110A, 0, + 16, 0x3147, 0x110B, 0, + 16, 0x3148, 0x110C, 0, + 16, 0x3149, 0x110D, 0, + 16, 0x314A, 0x110E, 0, + 16, 0x314B, 0x110F, 0, + 16, 0x314C, 0x1110, 0, + 16, 0x314D, 0x1111, 0, + 16, 0x314E, 0x1112, 0, + 16, 0x314F, 0x1161, 0, + 16, 0x3150, 0x1162, 0, + 16, 0x3151, 0x1163, 0, + 16, 0x3152, 0x1164, 0, + 16, 0x3153, 0x1165, 0, + 16, 0x3154, 0x1166, 0, + 16, 0x3155, 0x1167, 0, + 16, 0x3156, 0x1168, 0, + 16, 0x3157, 0x1169, 0, + 16, 0x3158, 0x116A, 0, + 16, 0x3159, 0x116B, 0, + 16, 0x315A, 0x116C, 0, + 16, 0x315B, 0x116D, 0, + 16, 0x315C, 0x116E, 0, + 16, 0x315D, 0x116F, 0, + 16, 0x315E, 0x1170, 0, + 16, 0x315F, 0x1171, 0, + 16, 0x3160, 0x1172, 0, + 16, 0x3161, 0x1173, 0, + 16, 0x3162, 0x1174, 0, + 16, 0x3163, 0x1175, 0, + 16, 0x3164, 0x1160, 0, + 16, 0x3165, 0x1114, 0, + 16, 0x3166, 0x1115, 0, + 16, 0x3167, 0x11C7, 0, + 16, 0x3168, 0x11C8, 0, + 16, 0x3169, 0x11CC, 0, + 16, 0x316A, 0x11CE, 0, + 16, 0x316B, 0x11D3, 0, + 16, 0x316C, 0x11D7, 0, + 16, 0x316D, 0x11D9, 0, + 16, 0x316E, 0x111C, 0, + 16, 0x316F, 0x11DD, 0, + 16, 0x3170, 0x11DF, 0, + 16, 0x3171, 0x111D, 0, + 16, 0x3172, 0x111E, 0, + 16, 0x3173, 0x1120, 0, + 16, 0x3174, 0x1122, 0, + 16, 0x3175, 0x1123, 0, + 16, 0x3176, 0x1127, 0, + 16, 0x3177, 0x1129, 0, + 16, 0x3178, 0x112B, 0, + 16, 0x3179, 0x112C, 0, + 16, 0x317A, 0x112D, 0, + 16, 0x317B, 0x112E, 0, + 16, 0x317C, 0x112F, 0, + 16, 0x317D, 0x1132, 0, + 16, 0x317E, 0x1136, 0, + 16, 0x317F, 0x1140, 0, + 16, 0x3180, 0x1147, 0, + 16, 0x3181, 0x114C, 0, + 16, 0x3182, 0x11F1, 0, + 16, 0x3183, 0x11F2, 0, + 16, 0x3184, 0x1157, 0, + 16, 0x3185, 0x1158, 0, + 16, 0x3186, 0x1159, 0, + 16, 0x3187, 0x1184, 0, + 16, 0x3188, 0x1185, 0, + 16, 0x3189, 0x1188, 0, + 16, 0x318A, 0x1191, 0, + 16, 0x318B, 0x1192, 0, + 16, 0x318C, 0x1194, 0, + 16, 0x318D, 0x119E, 0, + 16, 0x318E, 0x11A1, 0, + 9, 0x3192, 0x4E00, 0, + 9, 0x3193, 0x4E8C, 0, + 9, 0x3194, 0x4E09, 0, + 9, 0x3195, 0x56DB, 0, + 9, 0x3196, 0x4E0A, 0, + 9, 0x3197, 0x4E2D, 0, + 9, 0x3198, 0x4E0B, 0, + 9, 0x3199, 0x7532, 0, + 9, 0x319A, 0x4E59, 0, + 9, 0x319B, 0x4E19, 0, + 9, 0x319C, 0x4E01, 0, + 9, 0x319D, 0x5929, 0, + 9, 0x319E, 0x5730, 0, + 9, 0x319F, 0x4EBA, 0, + 16, 0x3200, 0x0028, 0x1100, 0x0029, 0, + 16, 0x3201, 0x0028, 0x1102, 0x0029, 0, + 16, 0x3202, 0x0028, 0x1103, 0x0029, 0, + 16, 0x3203, 0x0028, 0x1105, 0x0029, 0, + 16, 0x3204, 0x0028, 0x1106, 0x0029, 0, + 16, 0x3205, 0x0028, 0x1107, 0x0029, 0, + 16, 0x3206, 0x0028, 0x1109, 0x0029, 0, + 16, 0x3207, 0x0028, 0x110B, 0x0029, 0, + 16, 0x3208, 0x0028, 0x110C, 0x0029, 0, + 16, 0x3209, 0x0028, 0x110E, 0x0029, 0, + 16, 0x320A, 0x0028, 0x110F, 0x0029, 0, + 16, 0x320B, 0x0028, 0x1110, 0x0029, 0, + 16, 0x320C, 0x0028, 0x1111, 0x0029, 0, + 16, 0x320D, 0x0028, 0x1112, 0x0029, 0, + 16, 0x320E, 0x0028, 0x1100, 0x1161, 0x0029, 0, + 16, 0x320F, 0x0028, 0x1102, 0x1161, 0x0029, 0, + 16, 0x3210, 0x0028, 0x1103, 0x1161, 0x0029, 0, + 16, 0x3211, 0x0028, 0x1105, 0x1161, 0x0029, 0, + 16, 0x3212, 0x0028, 0x1106, 0x1161, 0x0029, 0, + 16, 0x3213, 0x0028, 0x1107, 0x1161, 0x0029, 0, + 16, 0x3214, 0x0028, 0x1109, 0x1161, 0x0029, 0, + 16, 0x3215, 0x0028, 0x110B, 0x1161, 0x0029, 0, + 16, 0x3216, 0x0028, 0x110C, 0x1161, 0x0029, 0, + 16, 0x3217, 0x0028, 0x110E, 0x1161, 0x0029, 0, + 16, 0x3218, 0x0028, 0x110F, 0x1161, 0x0029, 0, + 16, 0x3219, 0x0028, 0x1110, 0x1161, 0x0029, 0, + 16, 0x321A, 0x0028, 0x1111, 0x1161, 0x0029, 0, + 16, 0x321B, 0x0028, 0x1112, 0x1161, 0x0029, 0, + 16, 0x321C, 0x0028, 0x110C, 0x116E, 0x0029, 0, + 16, 0x3220, 0x0028, 0x4E00, 0x0029, 0, + 16, 0x3221, 0x0028, 0x4E8C, 0x0029, 0, + 16, 0x3222, 0x0028, 0x4E09, 0x0029, 0, + 16, 0x3223, 0x0028, 0x56DB, 0x0029, 0, + 16, 0x3224, 0x0028, 0x4E94, 0x0029, 0, + 16, 0x3225, 0x0028, 0x516D, 0x0029, 0, + 16, 0x3226, 0x0028, 0x4E03, 0x0029, 0, + 16, 0x3227, 0x0028, 0x516B, 0x0029, 0, + 16, 0x3228, 0x0028, 0x4E5D, 0x0029, 0, + 16, 0x3229, 0x0028, 0x5341, 0x0029, 0, + 16, 0x322A, 0x0028, 0x6708, 0x0029, 0, + 16, 0x322B, 0x0028, 0x706B, 0x0029, 0, + 16, 0x322C, 0x0028, 0x6C34, 0x0029, 0, + 16, 0x322D, 0x0028, 0x6728, 0x0029, 0, + 16, 0x322E, 0x0028, 0x91D1, 0x0029, 0, + 16, 0x322F, 0x0028, 0x571F, 0x0029, 0, + 16, 0x3230, 0x0028, 0x65E5, 0x0029, 0, + 16, 0x3231, 0x0028, 0x682A, 0x0029, 0, + 16, 0x3232, 0x0028, 0x6709, 0x0029, 0, + 16, 0x3233, 0x0028, 0x793E, 0x0029, 0, + 16, 0x3234, 0x0028, 0x540D, 0x0029, 0, + 16, 0x3235, 0x0028, 0x7279, 0x0029, 0, + 16, 0x3236, 0x0028, 0x8CA1, 0x0029, 0, + 16, 0x3237, 0x0028, 0x795D, 0x0029, 0, + 16, 0x3238, 0x0028, 0x52B4, 0x0029, 0, + 16, 0x3239, 0x0028, 0x4EE3, 0x0029, 0, + 16, 0x323A, 0x0028, 0x547C, 0x0029, 0, + 16, 0x323B, 0x0028, 0x5B66, 0x0029, 0, + 16, 0x323C, 0x0028, 0x76E3, 0x0029, 0, + 16, 0x323D, 0x0028, 0x4F01, 0x0029, 0, + 16, 0x323E, 0x0028, 0x8CC7, 0x0029, 0, + 16, 0x323F, 0x0028, 0x5354, 0x0029, 0, + 16, 0x3240, 0x0028, 0x796D, 0x0029, 0, + 16, 0x3241, 0x0028, 0x4F11, 0x0029, 0, + 16, 0x3242, 0x0028, 0x81EA, 0x0029, 0, + 16, 0x3243, 0x0028, 0x81F3, 0x0029, 0, + 8, 0x3251, 0x0032, 0x0031, 0, + 8, 0x3252, 0x0032, 0x0032, 0, + 8, 0x3253, 0x0032, 0x0033, 0, + 8, 0x3254, 0x0032, 0x0034, 0, + 8, 0x3255, 0x0032, 0x0035, 0, + 8, 0x3256, 0x0032, 0x0036, 0, + 8, 0x3257, 0x0032, 0x0037, 0, + 8, 0x3258, 0x0032, 0x0038, 0, + 8, 0x3259, 0x0032, 0x0039, 0, + 8, 0x325A, 0x0033, 0x0030, 0, + 8, 0x325B, 0x0033, 0x0031, 0, + 8, 0x325C, 0x0033, 0x0032, 0, + 8, 0x325D, 0x0033, 0x0033, 0, + 8, 0x325E, 0x0033, 0x0034, 0, + 8, 0x325F, 0x0033, 0x0035, 0, + 8, 0x3260, 0x1100, 0, + 8, 0x3261, 0x1102, 0, + 8, 0x3262, 0x1103, 0, + 8, 0x3263, 0x1105, 0, + 8, 0x3264, 0x1106, 0, + 8, 0x3265, 0x1107, 0, + 8, 0x3266, 0x1109, 0, + 8, 0x3267, 0x110B, 0, + 8, 0x3268, 0x110C, 0, + 8, 0x3269, 0x110E, 0, + 8, 0x326A, 0x110F, 0, + 8, 0x326B, 0x1110, 0, + 8, 0x326C, 0x1111, 0, + 8, 0x326D, 0x1112, 0, + 8, 0x326E, 0x1100, 0x1161, 0, + 8, 0x326F, 0x1102, 0x1161, 0, + 8, 0x3270, 0x1103, 0x1161, 0, + 8, 0x3271, 0x1105, 0x1161, 0, + 8, 0x3272, 0x1106, 0x1161, 0, + 8, 0x3273, 0x1107, 0x1161, 0, + 8, 0x3274, 0x1109, 0x1161, 0, + 8, 0x3275, 0x110B, 0x1161, 0, + 8, 0x3276, 0x110C, 0x1161, 0, + 8, 0x3277, 0x110E, 0x1161, 0, + 8, 0x3278, 0x110F, 0x1161, 0, + 8, 0x3279, 0x1110, 0x1161, 0, + 8, 0x327A, 0x1111, 0x1161, 0, + 8, 0x327B, 0x1112, 0x1161, 0, + 8, 0x3280, 0x4E00, 0, + 8, 0x3281, 0x4E8C, 0, + 8, 0x3282, 0x4E09, 0, + 8, 0x3283, 0x56DB, 0, + 8, 0x3284, 0x4E94, 0, + 8, 0x3285, 0x516D, 0, + 8, 0x3286, 0x4E03, 0, + 8, 0x3287, 0x516B, 0, + 8, 0x3288, 0x4E5D, 0, + 8, 0x3289, 0x5341, 0, + 8, 0x328A, 0x6708, 0, + 8, 0x328B, 0x706B, 0, + 8, 0x328C, 0x6C34, 0, + 8, 0x328D, 0x6728, 0, + 8, 0x328E, 0x91D1, 0, + 8, 0x328F, 0x571F, 0, + 8, 0x3290, 0x65E5, 0, + 8, 0x3291, 0x682A, 0, + 8, 0x3292, 0x6709, 0, + 8, 0x3293, 0x793E, 0, + 8, 0x3294, 0x540D, 0, + 8, 0x3295, 0x7279, 0, + 8, 0x3296, 0x8CA1, 0, + 8, 0x3297, 0x795D, 0, + 8, 0x3298, 0x52B4, 0, + 8, 0x3299, 0x79D8, 0, + 8, 0x329A, 0x7537, 0, + 8, 0x329B, 0x5973, 0, + 8, 0x329C, 0x9069, 0, + 8, 0x329D, 0x512A, 0, + 8, 0x329E, 0x5370, 0, + 8, 0x329F, 0x6CE8, 0, + 8, 0x32A0, 0x9805, 0, + 8, 0x32A1, 0x4F11, 0, + 8, 0x32A2, 0x5199, 0, + 8, 0x32A3, 0x6B63, 0, + 8, 0x32A4, 0x4E0A, 0, + 8, 0x32A5, 0x4E2D, 0, + 8, 0x32A6, 0x4E0B, 0, + 8, 0x32A7, 0x5DE6, 0, + 8, 0x32A8, 0x53F3, 0, + 8, 0x32A9, 0x533B, 0, + 8, 0x32AA, 0x5B97, 0, + 8, 0x32AB, 0x5B66, 0, + 8, 0x32AC, 0x76E3, 0, + 8, 0x32AD, 0x4F01, 0, + 8, 0x32AE, 0x8CC7, 0, + 8, 0x32AF, 0x5354, 0, + 8, 0x32B0, 0x591C, 0, + 8, 0x32B1, 0x0033, 0x0036, 0, + 8, 0x32B2, 0x0033, 0x0037, 0, + 8, 0x32B3, 0x0033, 0x0038, 0, + 8, 0x32B4, 0x0033, 0x0039, 0, + 8, 0x32B5, 0x0034, 0x0030, 0, + 8, 0x32B6, 0x0034, 0x0031, 0, + 8, 0x32B7, 0x0034, 0x0032, 0, + 8, 0x32B8, 0x0034, 0x0033, 0, + 8, 0x32B9, 0x0034, 0x0034, 0, + 8, 0x32BA, 0x0034, 0x0035, 0, + 8, 0x32BB, 0x0034, 0x0036, 0, + 8, 0x32BC, 0x0034, 0x0037, 0, + 8, 0x32BD, 0x0034, 0x0038, 0, + 8, 0x32BE, 0x0034, 0x0039, 0, + 8, 0x32BF, 0x0035, 0x0030, 0, + 16, 0x32C0, 0x0031, 0x6708, 0, + 16, 0x32C1, 0x0032, 0x6708, 0, + 16, 0x32C2, 0x0033, 0x6708, 0, + 16, 0x32C3, 0x0034, 0x6708, 0, + 16, 0x32C4, 0x0035, 0x6708, 0, + 16, 0x32C5, 0x0036, 0x6708, 0, + 16, 0x32C6, 0x0037, 0x6708, 0, + 16, 0x32C7, 0x0038, 0x6708, 0, + 16, 0x32C8, 0x0039, 0x6708, 0, + 16, 0x32C9, 0x0031, 0x0030, 0x6708, 0, + 16, 0x32CA, 0x0031, 0x0031, 0x6708, 0, + 16, 0x32CB, 0x0031, 0x0032, 0x6708, 0, + 8, 0x32D0, 0x30A2, 0, + 8, 0x32D1, 0x30A4, 0, + 8, 0x32D2, 0x30A6, 0, + 8, 0x32D3, 0x30A8, 0, + 8, 0x32D4, 0x30AA, 0, + 8, 0x32D5, 0x30AB, 0, + 8, 0x32D6, 0x30AD, 0, + 8, 0x32D7, 0x30AF, 0, + 8, 0x32D8, 0x30B1, 0, + 8, 0x32D9, 0x30B3, 0, + 8, 0x32DA, 0x30B5, 0, + 8, 0x32DB, 0x30B7, 0, + 8, 0x32DC, 0x30B9, 0, + 8, 0x32DD, 0x30BB, 0, + 8, 0x32DE, 0x30BD, 0, + 8, 0x32DF, 0x30BF, 0, + 8, 0x32E0, 0x30C1, 0, + 8, 0x32E1, 0x30C4, 0, + 8, 0x32E2, 0x30C6, 0, + 8, 0x32E3, 0x30C8, 0, + 8, 0x32E4, 0x30CA, 0, + 8, 0x32E5, 0x30CB, 0, + 8, 0x32E6, 0x30CC, 0, + 8, 0x32E7, 0x30CD, 0, + 8, 0x32E8, 0x30CE, 0, + 8, 0x32E9, 0x30CF, 0, + 8, 0x32EA, 0x30D2, 0, + 8, 0x32EB, 0x30D5, 0, + 8, 0x32EC, 0x30D8, 0, + 8, 0x32ED, 0x30DB, 0, + 8, 0x32EE, 0x30DE, 0, + 8, 0x32EF, 0x30DF, 0, + 8, 0x32F0, 0x30E0, 0, + 8, 0x32F1, 0x30E1, 0, + 8, 0x32F2, 0x30E2, 0, + 8, 0x32F3, 0x30E4, 0, + 8, 0x32F4, 0x30E6, 0, + 8, 0x32F5, 0x30E8, 0, + 8, 0x32F6, 0x30E9, 0, + 8, 0x32F7, 0x30EA, 0, + 8, 0x32F8, 0x30EB, 0, + 8, 0x32F9, 0x30EC, 0, + 8, 0x32FA, 0x30ED, 0, + 8, 0x32FB, 0x30EF, 0, + 8, 0x32FC, 0x30F0, 0, + 8, 0x32FD, 0x30F1, 0, + 8, 0x32FE, 0x30F2, 0, + 15, 0x3300, 0x30A2, 0x30D1, 0x30FC, 0x30C8, 0, + 15, 0x3301, 0x30A2, 0x30EB, 0x30D5, 0x30A1, 0, + 15, 0x3302, 0x30A2, 0x30F3, 0x30DA, 0x30A2, 0, + 15, 0x3303, 0x30A2, 0x30FC, 0x30EB, 0, + 15, 0x3304, 0x30A4, 0x30CB, 0x30F3, 0x30B0, 0, + 15, 0x3305, 0x30A4, 0x30F3, 0x30C1, 0, + 15, 0x3306, 0x30A6, 0x30A9, 0x30F3, 0, + 15, 0x3307, 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9, 0, + 15, 0x3308, 0x30A8, 0x30FC, 0x30AB, 0x30FC, 0, + 15, 0x3309, 0x30AA, 0x30F3, 0x30B9, 0, + 15, 0x330A, 0x30AA, 0x30FC, 0x30E0, 0, + 15, 0x330B, 0x30AB, 0x30A4, 0x30EA, 0, + 15, 0x330C, 0x30AB, 0x30E9, 0x30C3, 0x30C8, 0, + 15, 0x330D, 0x30AB, 0x30ED, 0x30EA, 0x30FC, 0, + 15, 0x330E, 0x30AC, 0x30ED, 0x30F3, 0, + 15, 0x330F, 0x30AC, 0x30F3, 0x30DE, 0, + 15, 0x3310, 0x30AE, 0x30AC, 0, + 15, 0x3311, 0x30AE, 0x30CB, 0x30FC, 0, + 15, 0x3312, 0x30AD, 0x30E5, 0x30EA, 0x30FC, 0, + 15, 0x3313, 0x30AE, 0x30EB, 0x30C0, 0x30FC, 0, + 15, 0x3314, 0x30AD, 0x30ED, 0, + 15, 0x3315, 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0, 0, + 15, 0x3316, 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, + 15, 0x3317, 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8, 0, + 15, 0x3318, 0x30B0, 0x30E9, 0x30E0, 0, + 15, 0x3319, 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3, 0, + 15, 0x331A, 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED, 0, + 15, 0x331B, 0x30AF, 0x30ED, 0x30FC, 0x30CD, 0, + 15, 0x331C, 0x30B1, 0x30FC, 0x30B9, 0, + 15, 0x331D, 0x30B3, 0x30EB, 0x30CA, 0, + 15, 0x331E, 0x30B3, 0x30FC, 0x30DD, 0, + 15, 0x331F, 0x30B5, 0x30A4, 0x30AF, 0x30EB, 0, + 15, 0x3320, 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0, 0, + 15, 0x3321, 0x30B7, 0x30EA, 0x30F3, 0x30B0, 0, + 15, 0x3322, 0x30BB, 0x30F3, 0x30C1, 0, + 15, 0x3323, 0x30BB, 0x30F3, 0x30C8, 0, + 15, 0x3324, 0x30C0, 0x30FC, 0x30B9, 0, + 15, 0x3325, 0x30C7, 0x30B7, 0, + 15, 0x3326, 0x30C9, 0x30EB, 0, + 15, 0x3327, 0x30C8, 0x30F3, 0, + 15, 0x3328, 0x30CA, 0x30CE, 0, + 15, 0x3329, 0x30CE, 0x30C3, 0x30C8, 0, + 15, 0x332A, 0x30CF, 0x30A4, 0x30C4, 0, + 15, 0x332B, 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8, 0, + 15, 0x332C, 0x30D1, 0x30FC, 0x30C4, 0, + 15, 0x332D, 0x30D0, 0x30FC, 0x30EC, 0x30EB, 0, + 15, 0x332E, 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB, 0, + 15, 0x332F, 0x30D4, 0x30AF, 0x30EB, 0, + 15, 0x3330, 0x30D4, 0x30B3, 0, + 15, 0x3331, 0x30D3, 0x30EB, 0, + 15, 0x3332, 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9, 0, + 15, 0x3333, 0x30D5, 0x30A3, 0x30FC, 0x30C8, 0, + 15, 0x3334, 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB, 0, + 15, 0x3335, 0x30D5, 0x30E9, 0x30F3, 0, + 15, 0x3336, 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB, 0, + 15, 0x3337, 0x30DA, 0x30BD, 0, + 15, 0x3338, 0x30DA, 0x30CB, 0x30D2, 0, + 15, 0x3339, 0x30D8, 0x30EB, 0x30C4, 0, + 15, 0x333A, 0x30DA, 0x30F3, 0x30B9, 0, + 15, 0x333B, 0x30DA, 0x30FC, 0x30B8, 0, + 15, 0x333C, 0x30D9, 0x30FC, 0x30BF, 0, + 15, 0x333D, 0x30DD, 0x30A4, 0x30F3, 0x30C8, 0, + 15, 0x333E, 0x30DC, 0x30EB, 0x30C8, 0, + 15, 0x333F, 0x30DB, 0x30F3, 0, + 15, 0x3340, 0x30DD, 0x30F3, 0x30C9, 0, + 15, 0x3341, 0x30DB, 0x30FC, 0x30EB, 0, + 15, 0x3342, 0x30DB, 0x30FC, 0x30F3, 0, + 15, 0x3343, 0x30DE, 0x30A4, 0x30AF, 0x30ED, 0, + 15, 0x3344, 0x30DE, 0x30A4, 0x30EB, 0, + 15, 0x3345, 0x30DE, 0x30C3, 0x30CF, 0, + 15, 0x3346, 0x30DE, 0x30EB, 0x30AF, 0, + 15, 0x3347, 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3, 0, + 15, 0x3348, 0x30DF, 0x30AF, 0x30ED, 0x30F3, 0, + 15, 0x3349, 0x30DF, 0x30EA, 0, + 15, 0x334A, 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB, 0, + 15, 0x334B, 0x30E1, 0x30AC, 0, + 15, 0x334C, 0x30E1, 0x30AC, 0x30C8, 0x30F3, 0, + 15, 0x334D, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, + 15, 0x334E, 0x30E4, 0x30FC, 0x30C9, 0, + 15, 0x334F, 0x30E4, 0x30FC, 0x30EB, 0, + 15, 0x3350, 0x30E6, 0x30A2, 0x30F3, 0, + 15, 0x3351, 0x30EA, 0x30C3, 0x30C8, 0x30EB, 0, + 15, 0x3352, 0x30EA, 0x30E9, 0, + 15, 0x3353, 0x30EB, 0x30D4, 0x30FC, 0, + 15, 0x3354, 0x30EB, 0x30FC, 0x30D6, 0x30EB, 0, + 15, 0x3355, 0x30EC, 0x30E0, 0, + 15, 0x3356, 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3, 0, + 15, 0x3357, 0x30EF, 0x30C3, 0x30C8, 0, + 16, 0x3358, 0x0030, 0x70B9, 0, + 16, 0x3359, 0x0031, 0x70B9, 0, + 16, 0x335A, 0x0032, 0x70B9, 0, + 16, 0x335B, 0x0033, 0x70B9, 0, + 16, 0x335C, 0x0034, 0x70B9, 0, + 16, 0x335D, 0x0035, 0x70B9, 0, + 16, 0x335E, 0x0036, 0x70B9, 0, + 16, 0x335F, 0x0037, 0x70B9, 0, + 16, 0x3360, 0x0038, 0x70B9, 0, + 16, 0x3361, 0x0039, 0x70B9, 0, + 16, 0x3362, 0x0031, 0x0030, 0x70B9, 0, + 16, 0x3363, 0x0031, 0x0031, 0x70B9, 0, + 16, 0x3364, 0x0031, 0x0032, 0x70B9, 0, + 16, 0x3365, 0x0031, 0x0033, 0x70B9, 0, + 16, 0x3366, 0x0031, 0x0034, 0x70B9, 0, + 16, 0x3367, 0x0031, 0x0035, 0x70B9, 0, + 16, 0x3368, 0x0031, 0x0036, 0x70B9, 0, + 16, 0x3369, 0x0031, 0x0037, 0x70B9, 0, + 16, 0x336A, 0x0031, 0x0038, 0x70B9, 0, + 16, 0x336B, 0x0031, 0x0039, 0x70B9, 0, + 16, 0x336C, 0x0032, 0x0030, 0x70B9, 0, + 16, 0x336D, 0x0032, 0x0031, 0x70B9, 0, + 16, 0x336E, 0x0032, 0x0032, 0x70B9, 0, + 16, 0x336F, 0x0032, 0x0033, 0x70B9, 0, + 16, 0x3370, 0x0032, 0x0034, 0x70B9, 0, + 15, 0x3371, 0x0068, 0x0050, 0x0061, 0, + 15, 0x3372, 0x0064, 0x0061, 0, + 15, 0x3373, 0x0041, 0x0055, 0, + 15, 0x3374, 0x0062, 0x0061, 0x0072, 0, + 15, 0x3375, 0x006F, 0x0056, 0, + 15, 0x3376, 0x0070, 0x0063, 0, + 15, 0x337B, 0x5E73, 0x6210, 0, + 15, 0x337C, 0x662D, 0x548C, 0, + 15, 0x337D, 0x5927, 0x6B63, 0, + 15, 0x337E, 0x660E, 0x6CBB, 0, + 15, 0x337F, 0x682A, 0x5F0F, 0x4F1A, 0x793E, 0, + 15, 0x3380, 0x0070, 0x0041, 0, + 15, 0x3381, 0x006E, 0x0041, 0, + 15, 0x3382, 0x03BC, 0x0041, 0, + 15, 0x3383, 0x006D, 0x0041, 0, + 15, 0x3384, 0x006B, 0x0041, 0, + 15, 0x3385, 0x004B, 0x0042, 0, + 15, 0x3386, 0x004D, 0x0042, 0, + 15, 0x3387, 0x0047, 0x0042, 0, + 15, 0x3388, 0x0063, 0x0061, 0x006C, 0, + 15, 0x3389, 0x006B, 0x0063, 0x0061, 0x006C, 0, + 15, 0x338A, 0x0070, 0x0046, 0, + 15, 0x338B, 0x006E, 0x0046, 0, + 15, 0x338C, 0x03BC, 0x0046, 0, + 15, 0x338D, 0x03BC, 0x0067, 0, + 15, 0x338E, 0x006D, 0x0067, 0, + 15, 0x338F, 0x006B, 0x0067, 0, + 15, 0x3390, 0x0048, 0x007A, 0, + 15, 0x3391, 0x006B, 0x0048, 0x007A, 0, + 15, 0x3392, 0x004D, 0x0048, 0x007A, 0, + 15, 0x3393, 0x0047, 0x0048, 0x007A, 0, + 15, 0x3394, 0x0054, 0x0048, 0x007A, 0, + 15, 0x3395, 0x03BC, 0x2113, 0, + 15, 0x3396, 0x006D, 0x2113, 0, + 15, 0x3397, 0x0064, 0x2113, 0, + 15, 0x3398, 0x006B, 0x2113, 0, + 15, 0x3399, 0x0066, 0x006D, 0, + 15, 0x339A, 0x006E, 0x006D, 0, + 15, 0x339B, 0x03BC, 0x006D, 0, + 15, 0x339C, 0x006D, 0x006D, 0, + 15, 0x339D, 0x0063, 0x006D, 0, + 15, 0x339E, 0x006B, 0x006D, 0, + 15, 0x339F, 0x006D, 0x006D, 0x00B2, 0, + 15, 0x33A0, 0x0063, 0x006D, 0x00B2, 0, + 15, 0x33A1, 0x006D, 0x00B2, 0, + 15, 0x33A2, 0x006B, 0x006D, 0x00B2, 0, + 15, 0x33A3, 0x006D, 0x006D, 0x00B3, 0, + 15, 0x33A4, 0x0063, 0x006D, 0x00B3, 0, + 15, 0x33A5, 0x006D, 0x00B3, 0, + 15, 0x33A6, 0x006B, 0x006D, 0x00B3, 0, + 15, 0x33A7, 0x006D, 0x2215, 0x0073, 0, + 15, 0x33A8, 0x006D, 0x2215, 0x0073, 0x00B2, 0, + 15, 0x33A9, 0x0050, 0x0061, 0, + 15, 0x33AA, 0x006B, 0x0050, 0x0061, 0, + 15, 0x33AB, 0x004D, 0x0050, 0x0061, 0, + 15, 0x33AC, 0x0047, 0x0050, 0x0061, 0, + 15, 0x33AD, 0x0072, 0x0061, 0x0064, 0, + 15, 0x33AE, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0, + 15, 0x33AF, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2, 0, + 15, 0x33B0, 0x0070, 0x0073, 0, + 15, 0x33B1, 0x006E, 0x0073, 0, + 15, 0x33B2, 0x03BC, 0x0073, 0, + 15, 0x33B3, 0x006D, 0x0073, 0, + 15, 0x33B4, 0x0070, 0x0056, 0, + 15, 0x33B5, 0x006E, 0x0056, 0, + 15, 0x33B6, 0x03BC, 0x0056, 0, + 15, 0x33B7, 0x006D, 0x0056, 0, + 15, 0x33B8, 0x006B, 0x0056, 0, + 15, 0x33B9, 0x004D, 0x0056, 0, + 15, 0x33BA, 0x0070, 0x0057, 0, + 15, 0x33BB, 0x006E, 0x0057, 0, + 15, 0x33BC, 0x03BC, 0x0057, 0, + 15, 0x33BD, 0x006D, 0x0057, 0, + 15, 0x33BE, 0x006B, 0x0057, 0, + 15, 0x33BF, 0x004D, 0x0057, 0, + 15, 0x33C0, 0x006B, 0x03A9, 0, + 15, 0x33C1, 0x004D, 0x03A9, 0, + 15, 0x33C2, 0x0061, 0x002E, 0x006D, 0x002E, 0, + 15, 0x33C3, 0x0042, 0x0071, 0, + 15, 0x33C4, 0x0063, 0x0063, 0, + 15, 0x33C5, 0x0063, 0x0064, 0, + 15, 0x33C6, 0x0043, 0x2215, 0x006B, 0x0067, 0, + 15, 0x33C7, 0x0043, 0x006F, 0x002E, 0, + 15, 0x33C8, 0x0064, 0x0042, 0, + 15, 0x33C9, 0x0047, 0x0079, 0, + 15, 0x33CA, 0x0068, 0x0061, 0, + 15, 0x33CB, 0x0048, 0x0050, 0, + 15, 0x33CC, 0x0069, 0x006E, 0, + 15, 0x33CD, 0x004B, 0x004B, 0, + 15, 0x33CE, 0x004B, 0x004D, 0, + 15, 0x33CF, 0x006B, 0x0074, 0, + 15, 0x33D0, 0x006C, 0x006D, 0, + 15, 0x33D1, 0x006C, 0x006E, 0, + 15, 0x33D2, 0x006C, 0x006F, 0x0067, 0, + 15, 0x33D3, 0x006C, 0x0078, 0, + 15, 0x33D4, 0x006D, 0x0062, 0, + 15, 0x33D5, 0x006D, 0x0069, 0x006C, 0, + 15, 0x33D6, 0x006D, 0x006F, 0x006C, 0, + 15, 0x33D7, 0x0050, 0x0048, 0, + 15, 0x33D8, 0x0070, 0x002E, 0x006D, 0x002E, 0, + 15, 0x33D9, 0x0050, 0x0050, 0x004D, 0, + 15, 0x33DA, 0x0050, 0x0052, 0, + 15, 0x33DB, 0x0073, 0x0072, 0, + 15, 0x33DC, 0x0053, 0x0076, 0, + 15, 0x33DD, 0x0057, 0x0062, 0, + 16, 0x33E0, 0x0031, 0x65E5, 0, + 16, 0x33E1, 0x0032, 0x65E5, 0, + 16, 0x33E2, 0x0033, 0x65E5, 0, + 16, 0x33E3, 0x0034, 0x65E5, 0, + 16, 0x33E4, 0x0035, 0x65E5, 0, + 16, 0x33E5, 0x0036, 0x65E5, 0, + 16, 0x33E6, 0x0037, 0x65E5, 0, + 16, 0x33E7, 0x0038, 0x65E5, 0, + 16, 0x33E8, 0x0039, 0x65E5, 0, + 16, 0x33E9, 0x0031, 0x0030, 0x65E5, 0, + 16, 0x33EA, 0x0031, 0x0031, 0x65E5, 0, + 16, 0x33EB, 0x0031, 0x0032, 0x65E5, 0, + 16, 0x33EC, 0x0031, 0x0033, 0x65E5, 0, + 16, 0x33ED, 0x0031, 0x0034, 0x65E5, 0, + 16, 0x33EE, 0x0031, 0x0035, 0x65E5, 0, + 16, 0x33EF, 0x0031, 0x0036, 0x65E5, 0, + 16, 0x33F0, 0x0031, 0x0037, 0x65E5, 0, + 16, 0x33F1, 0x0031, 0x0038, 0x65E5, 0, + 16, 0x33F2, 0x0031, 0x0039, 0x65E5, 0, + 16, 0x33F3, 0x0032, 0x0030, 0x65E5, 0, + 16, 0x33F4, 0x0032, 0x0031, 0x65E5, 0, + 16, 0x33F5, 0x0032, 0x0032, 0x65E5, 0, + 16, 0x33F6, 0x0032, 0x0033, 0x65E5, 0, + 16, 0x33F7, 0x0032, 0x0034, 0x65E5, 0, + 16, 0x33F8, 0x0032, 0x0035, 0x65E5, 0, + 16, 0x33F9, 0x0032, 0x0036, 0x65E5, 0, + 16, 0x33FA, 0x0032, 0x0037, 0x65E5, 0, + 16, 0x33FB, 0x0032, 0x0038, 0x65E5, 0, + 16, 0x33FC, 0x0032, 0x0039, 0x65E5, 0, + 16, 0x33FD, 0x0033, 0x0030, 0x65E5, 0, + 16, 0x33FE, 0x0033, 0x0031, 0x65E5, 0, + 1, 0xF900, 0x8C48, 0, + 1, 0xF901, 0x66F4, 0, + 1, 0xF902, 0x8ECA, 0, + 1, 0xF903, 0x8CC8, 0, + 1, 0xF904, 0x6ED1, 0, + 1, 0xF905, 0x4E32, 0, + 1, 0xF906, 0x53E5, 0, + 1, 0xF907, 0x9F9C, 0, + 1, 0xF908, 0x9F9C, 0, + 1, 0xF909, 0x5951, 0, + 1, 0xF90A, 0x91D1, 0, + 1, 0xF90B, 0x5587, 0, + 1, 0xF90C, 0x5948, 0, + 1, 0xF90D, 0x61F6, 0, + 1, 0xF90E, 0x7669, 0, + 1, 0xF90F, 0x7F85, 0, + 1, 0xF910, 0x863F, 0, + 1, 0xF911, 0x87BA, 0, + 1, 0xF912, 0x88F8, 0, + 1, 0xF913, 0x908F, 0, + 1, 0xF914, 0x6A02, 0, + 1, 0xF915, 0x6D1B, 0, + 1, 0xF916, 0x70D9, 0, + 1, 0xF917, 0x73DE, 0, + 1, 0xF918, 0x843D, 0, + 1, 0xF919, 0x916A, 0, + 1, 0xF91A, 0x99F1, 0, + 1, 0xF91B, 0x4E82, 0, + 1, 0xF91C, 0x5375, 0, + 1, 0xF91D, 0x6B04, 0, + 1, 0xF91E, 0x721B, 0, + 1, 0xF91F, 0x862D, 0, + 1, 0xF920, 0x9E1E, 0, + 1, 0xF921, 0x5D50, 0, + 1, 0xF922, 0x6FEB, 0, + 1, 0xF923, 0x85CD, 0, + 1, 0xF924, 0x8964, 0, + 1, 0xF925, 0x62C9, 0, + 1, 0xF926, 0x81D8, 0, + 1, 0xF927, 0x881F, 0, + 1, 0xF928, 0x5ECA, 0, + 1, 0xF929, 0x6717, 0, + 1, 0xF92A, 0x6D6A, 0, + 1, 0xF92B, 0x72FC, 0, + 1, 0xF92C, 0x90CE, 0, + 1, 0xF92D, 0x4F86, 0, + 1, 0xF92E, 0x51B7, 0, + 1, 0xF92F, 0x52DE, 0, + 1, 0xF930, 0x64C4, 0, + 1, 0xF931, 0x6AD3, 0, + 1, 0xF932, 0x7210, 0, + 1, 0xF933, 0x76E7, 0, + 1, 0xF934, 0x8001, 0, + 1, 0xF935, 0x8606, 0, + 1, 0xF936, 0x865C, 0, + 1, 0xF937, 0x8DEF, 0, + 1, 0xF938, 0x9732, 0, + 1, 0xF939, 0x9B6F, 0, + 1, 0xF93A, 0x9DFA, 0, + 1, 0xF93B, 0x788C, 0, + 1, 0xF93C, 0x797F, 0, + 1, 0xF93D, 0x7DA0, 0, + 1, 0xF93E, 0x83C9, 0, + 1, 0xF93F, 0x9304, 0, + 1, 0xF940, 0x9E7F, 0, + 1, 0xF941, 0x8AD6, 0, + 1, 0xF942, 0x58DF, 0, + 1, 0xF943, 0x5F04, 0, + 1, 0xF944, 0x7C60, 0, + 1, 0xF945, 0x807E, 0, + 1, 0xF946, 0x7262, 0, + 1, 0xF947, 0x78CA, 0, + 1, 0xF948, 0x8CC2, 0, + 1, 0xF949, 0x96F7, 0, + 1, 0xF94A, 0x58D8, 0, + 1, 0xF94B, 0x5C62, 0, + 1, 0xF94C, 0x6A13, 0, + 1, 0xF94D, 0x6DDA, 0, + 1, 0xF94E, 0x6F0F, 0, + 1, 0xF94F, 0x7D2F, 0, + 1, 0xF950, 0x7E37, 0, + 1, 0xF951, 0x964B, 0, + 1, 0xF952, 0x52D2, 0, + 1, 0xF953, 0x808B, 0, + 1, 0xF954, 0x51DC, 0, + 1, 0xF955, 0x51CC, 0, + 1, 0xF956, 0x7A1C, 0, + 1, 0xF957, 0x7DBE, 0, + 1, 0xF958, 0x83F1, 0, + 1, 0xF959, 0x9675, 0, + 1, 0xF95A, 0x8B80, 0, + 1, 0xF95B, 0x62CF, 0, + 1, 0xF95C, 0x6A02, 0, + 1, 0xF95D, 0x8AFE, 0, + 1, 0xF95E, 0x4E39, 0, + 1, 0xF95F, 0x5BE7, 0, + 1, 0xF960, 0x6012, 0, + 1, 0xF961, 0x7387, 0, + 1, 0xF962, 0x7570, 0, + 1, 0xF963, 0x5317, 0, + 1, 0xF964, 0x78FB, 0, + 1, 0xF965, 0x4FBF, 0, + 1, 0xF966, 0x5FA9, 0, + 1, 0xF967, 0x4E0D, 0, + 1, 0xF968, 0x6CCC, 0, + 1, 0xF969, 0x6578, 0, + 1, 0xF96A, 0x7D22, 0, + 1, 0xF96B, 0x53C3, 0, + 1, 0xF96C, 0x585E, 0, + 1, 0xF96D, 0x7701, 0, + 1, 0xF96E, 0x8449, 0, + 1, 0xF96F, 0x8AAA, 0, + 1, 0xF970, 0x6BBA, 0, + 1, 0xF971, 0x8FB0, 0, + 1, 0xF972, 0x6C88, 0, + 1, 0xF973, 0x62FE, 0, + 1, 0xF974, 0x82E5, 0, + 1, 0xF975, 0x63A0, 0, + 1, 0xF976, 0x7565, 0, + 1, 0xF977, 0x4EAE, 0, + 1, 0xF978, 0x5169, 0, + 1, 0xF979, 0x51C9, 0, + 1, 0xF97A, 0x6881, 0, + 1, 0xF97B, 0x7CE7, 0, + 1, 0xF97C, 0x826F, 0, + 1, 0xF97D, 0x8AD2, 0, + 1, 0xF97E, 0x91CF, 0, + 1, 0xF97F, 0x52F5, 0, + 1, 0xF980, 0x5442, 0, + 1, 0xF981, 0x5973, 0, + 1, 0xF982, 0x5EEC, 0, + 1, 0xF983, 0x65C5, 0, + 1, 0xF984, 0x6FFE, 0, + 1, 0xF985, 0x792A, 0, + 1, 0xF986, 0x95AD, 0, + 1, 0xF987, 0x9A6A, 0, + 1, 0xF988, 0x9E97, 0, + 1, 0xF989, 0x9ECE, 0, + 1, 0xF98A, 0x529B, 0, + 1, 0xF98B, 0x66C6, 0, + 1, 0xF98C, 0x6B77, 0, + 1, 0xF98D, 0x8F62, 0, + 1, 0xF98E, 0x5E74, 0, + 1, 0xF98F, 0x6190, 0, + 1, 0xF990, 0x6200, 0, + 1, 0xF991, 0x649A, 0, + 1, 0xF992, 0x6F23, 0, + 1, 0xF993, 0x7149, 0, + 1, 0xF994, 0x7489, 0, + 1, 0xF995, 0x79CA, 0, + 1, 0xF996, 0x7DF4, 0, + 1, 0xF997, 0x806F, 0, + 1, 0xF998, 0x8F26, 0, + 1, 0xF999, 0x84EE, 0, + 1, 0xF99A, 0x9023, 0, + 1, 0xF99B, 0x934A, 0, + 1, 0xF99C, 0x5217, 0, + 1, 0xF99D, 0x52A3, 0, + 1, 0xF99E, 0x54BD, 0, + 1, 0xF99F, 0x70C8, 0, + 1, 0xF9A0, 0x88C2, 0, + 1, 0xF9A1, 0x8AAA, 0, + 1, 0xF9A2, 0x5EC9, 0, + 1, 0xF9A3, 0x5FF5, 0, + 1, 0xF9A4, 0x637B, 0, + 1, 0xF9A5, 0x6BAE, 0, + 1, 0xF9A6, 0x7C3E, 0, + 1, 0xF9A7, 0x7375, 0, + 1, 0xF9A8, 0x4EE4, 0, + 1, 0xF9A9, 0x56F9, 0, + 1, 0xF9AA, 0x5BE7, 0, + 1, 0xF9AB, 0x5DBA, 0, + 1, 0xF9AC, 0x601C, 0, + 1, 0xF9AD, 0x73B2, 0, + 1, 0xF9AE, 0x7469, 0, + 1, 0xF9AF, 0x7F9A, 0, + 1, 0xF9B0, 0x8046, 0, + 1, 0xF9B1, 0x9234, 0, + 1, 0xF9B2, 0x96F6, 0, + 1, 0xF9B3, 0x9748, 0, + 1, 0xF9B4, 0x9818, 0, + 1, 0xF9B5, 0x4F8B, 0, + 1, 0xF9B6, 0x79AE, 0, + 1, 0xF9B7, 0x91B4, 0, + 1, 0xF9B8, 0x96B8, 0, + 1, 0xF9B9, 0x60E1, 0, + 1, 0xF9BA, 0x4E86, 0, + 1, 0xF9BB, 0x50DA, 0, + 1, 0xF9BC, 0x5BEE, 0, + 1, 0xF9BD, 0x5C3F, 0, + 1, 0xF9BE, 0x6599, 0, + 1, 0xF9BF, 0x6A02, 0, + 1, 0xF9C0, 0x71CE, 0, + 1, 0xF9C1, 0x7642, 0, + 1, 0xF9C2, 0x84FC, 0, + 1, 0xF9C3, 0x907C, 0, + 1, 0xF9C4, 0x9F8D, 0, + 1, 0xF9C5, 0x6688, 0, + 1, 0xF9C6, 0x962E, 0, + 1, 0xF9C7, 0x5289, 0, + 1, 0xF9C8, 0x677B, 0, + 1, 0xF9C9, 0x67F3, 0, + 1, 0xF9CA, 0x6D41, 0, + 1, 0xF9CB, 0x6E9C, 0, + 1, 0xF9CC, 0x7409, 0, + 1, 0xF9CD, 0x7559, 0, + 1, 0xF9CE, 0x786B, 0, + 1, 0xF9CF, 0x7D10, 0, + 1, 0xF9D0, 0x985E, 0, + 1, 0xF9D1, 0x516D, 0, + 1, 0xF9D2, 0x622E, 0, + 1, 0xF9D3, 0x9678, 0, + 1, 0xF9D4, 0x502B, 0, + 1, 0xF9D5, 0x5D19, 0, + 1, 0xF9D6, 0x6DEA, 0, + 1, 0xF9D7, 0x8F2A, 0, + 1, 0xF9D8, 0x5F8B, 0, + 1, 0xF9D9, 0x6144, 0, + 1, 0xF9DA, 0x6817, 0, + 1, 0xF9DB, 0x7387, 0, + 1, 0xF9DC, 0x9686, 0, + 1, 0xF9DD, 0x5229, 0, + 1, 0xF9DE, 0x540F, 0, + 1, 0xF9DF, 0x5C65, 0, + 1, 0xF9E0, 0x6613, 0, + 1, 0xF9E1, 0x674E, 0, + 1, 0xF9E2, 0x68A8, 0, + 1, 0xF9E3, 0x6CE5, 0, + 1, 0xF9E4, 0x7406, 0, + 1, 0xF9E5, 0x75E2, 0, + 1, 0xF9E6, 0x7F79, 0, + 1, 0xF9E7, 0x88CF, 0, + 1, 0xF9E8, 0x88E1, 0, + 1, 0xF9E9, 0x91CC, 0, + 1, 0xF9EA, 0x96E2, 0, + 1, 0xF9EB, 0x533F, 0, + 1, 0xF9EC, 0x6EBA, 0, + 1, 0xF9ED, 0x541D, 0, + 1, 0xF9EE, 0x71D0, 0, + 1, 0xF9EF, 0x7498, 0, + 1, 0xF9F0, 0x85FA, 0, + 1, 0xF9F1, 0x96A3, 0, + 1, 0xF9F2, 0x9C57, 0, + 1, 0xF9F3, 0x9E9F, 0, + 1, 0xF9F4, 0x6797, 0, + 1, 0xF9F5, 0x6DCB, 0, + 1, 0xF9F6, 0x81E8, 0, + 1, 0xF9F7, 0x7ACB, 0, + 1, 0xF9F8, 0x7B20, 0, + 1, 0xF9F9, 0x7C92, 0, + 1, 0xF9FA, 0x72C0, 0, + 1, 0xF9FB, 0x7099, 0, + 1, 0xF9FC, 0x8B58, 0, + 1, 0xF9FD, 0x4EC0, 0, + 1, 0xF9FE, 0x8336, 0, + 1, 0xF9FF, 0x523A, 0, + 1, 0xFA00, 0x5207, 0, + 1, 0xFA01, 0x5EA6, 0, + 1, 0xFA02, 0x62D3, 0, + 1, 0xFA03, 0x7CD6, 0, + 1, 0xFA04, 0x5B85, 0, + 1, 0xFA05, 0x6D1E, 0, + 1, 0xFA06, 0x66B4, 0, + 1, 0xFA07, 0x8F3B, 0, + 1, 0xFA08, 0x884C, 0, + 1, 0xFA09, 0x964D, 0, + 1, 0xFA0A, 0x898B, 0, + 1, 0xFA0B, 0x5ED3, 0, + 1, 0xFA0C, 0x5140, 0, + 1, 0xFA0D, 0x55C0, 0, + 1, 0xFA10, 0x585A, 0, + 1, 0xFA12, 0x6674, 0, + 1, 0xFA15, 0x51DE, 0, + 1, 0xFA16, 0x732A, 0, + 1, 0xFA17, 0x76CA, 0, + 1, 0xFA18, 0x793C, 0, + 1, 0xFA19, 0x795E, 0, + 1, 0xFA1A, 0x7965, 0, + 1, 0xFA1B, 0x798F, 0, + 1, 0xFA1C, 0x9756, 0, + 1, 0xFA1D, 0x7CBE, 0, + 1, 0xFA1E, 0x7FBD, 0, + 1, 0xFA20, 0x8612, 0, + 1, 0xFA22, 0x8AF8, 0, + 1, 0xFA25, 0x9038, 0, + 1, 0xFA26, 0x90FD, 0, + 1, 0xFA2A, 0x98EF, 0, + 1, 0xFA2B, 0x98FC, 0, + 1, 0xFA2C, 0x9928, 0, + 1, 0xFA2D, 0x9DB4, 0, + 1, 0xFA30, 0x4FAE, 0, + 1, 0xFA31, 0x50E7, 0, + 1, 0xFA32, 0x514D, 0, + 1, 0xFA33, 0x52C9, 0, + 1, 0xFA34, 0x52E4, 0, + 1, 0xFA35, 0x5351, 0, + 1, 0xFA36, 0x559D, 0, + 1, 0xFA37, 0x5606, 0, + 1, 0xFA38, 0x5668, 0, + 1, 0xFA39, 0x5840, 0, + 1, 0xFA3A, 0x58A8, 0, + 1, 0xFA3B, 0x5C64, 0, + 1, 0xFA3C, 0x5C6E, 0, + 1, 0xFA3D, 0x6094, 0, + 1, 0xFA3E, 0x6168, 0, + 1, 0xFA3F, 0x618E, 0, + 1, 0xFA40, 0x61F2, 0, + 1, 0xFA41, 0x654F, 0, + 1, 0xFA42, 0x65E2, 0, + 1, 0xFA43, 0x6691, 0, + 1, 0xFA44, 0x6885, 0, + 1, 0xFA45, 0x6D77, 0, + 1, 0xFA46, 0x6E1A, 0, + 1, 0xFA47, 0x6F22, 0, + 1, 0xFA48, 0x716E, 0, + 1, 0xFA49, 0x722B, 0, + 1, 0xFA4A, 0x7422, 0, + 1, 0xFA4B, 0x7891, 0, + 1, 0xFA4C, 0x793E, 0, + 1, 0xFA4D, 0x7949, 0, + 1, 0xFA4E, 0x7948, 0, + 1, 0xFA4F, 0x7950, 0, + 1, 0xFA50, 0x7956, 0, + 1, 0xFA51, 0x795D, 0, + 1, 0xFA52, 0x798D, 0, + 1, 0xFA53, 0x798E, 0, + 1, 0xFA54, 0x7A40, 0, + 1, 0xFA55, 0x7A81, 0, + 1, 0xFA56, 0x7BC0, 0, + 1, 0xFA57, 0x7DF4, 0, + 1, 0xFA58, 0x7E09, 0, + 1, 0xFA59, 0x7E41, 0, + 1, 0xFA5A, 0x7F72, 0, + 1, 0xFA5B, 0x8005, 0, + 1, 0xFA5C, 0x81ED, 0, + 1, 0xFA5D, 0x8279, 0, + 1, 0xFA5E, 0x8279, 0, + 1, 0xFA5F, 0x8457, 0, + 1, 0xFA60, 0x8910, 0, + 1, 0xFA61, 0x8996, 0, + 1, 0xFA62, 0x8B01, 0, + 1, 0xFA63, 0x8B39, 0, + 1, 0xFA64, 0x8CD3, 0, + 1, 0xFA65, 0x8D08, 0, + 1, 0xFA66, 0x8FB6, 0, + 1, 0xFA67, 0x9038, 0, + 1, 0xFA68, 0x96E3, 0, + 1, 0xFA69, 0x97FF, 0, + 1, 0xFA6A, 0x983B, 0, + 16, 0xFB00, 0x0066, 0x0066, 0, + 16, 0xFB01, 0x0066, 0x0069, 0, + 16, 0xFB02, 0x0066, 0x006C, 0, + 16, 0xFB03, 0x0066, 0x0066, 0x0069, 0, + 16, 0xFB04, 0x0066, 0x0066, 0x006C, 0, + 16, 0xFB05, 0x017F, 0x0074, 0, + 16, 0xFB06, 0x0073, 0x0074, 0, + 16, 0xFB13, 0x0574, 0x0576, 0, + 16, 0xFB14, 0x0574, 0x0565, 0, + 16, 0xFB15, 0x0574, 0x056B, 0, + 16, 0xFB16, 0x057E, 0x0576, 0, + 16, 0xFB17, 0x0574, 0x056D, 0, + 1, 0xFB1D, 0x05D9, 0x05B4, 0, + 1, 0xFB1F, 0x05F2, 0x05B7, 0, + 2, 0xFB20, 0x05E2, 0, + 2, 0xFB21, 0x05D0, 0, + 2, 0xFB22, 0x05D3, 0, + 2, 0xFB23, 0x05D4, 0, + 2, 0xFB24, 0x05DB, 0, + 2, 0xFB25, 0x05DC, 0, + 2, 0xFB26, 0x05DD, 0, + 2, 0xFB27, 0x05E8, 0, + 2, 0xFB28, 0x05EA, 0, + 2, 0xFB29, 0x002B, 0, + 1, 0xFB2A, 0x05E9, 0x05C1, 0, + 1, 0xFB2B, 0x05E9, 0x05C2, 0, + 1, 0xFB2C, 0xFB49, 0x05C1, 0, + 1, 0xFB2D, 0xFB49, 0x05C2, 0, + 1, 0xFB2E, 0x05D0, 0x05B7, 0, + 1, 0xFB2F, 0x05D0, 0x05B8, 0, + 1, 0xFB30, 0x05D0, 0x05BC, 0, + 1, 0xFB31, 0x05D1, 0x05BC, 0, + 1, 0xFB32, 0x05D2, 0x05BC, 0, + 1, 0xFB33, 0x05D3, 0x05BC, 0, + 1, 0xFB34, 0x05D4, 0x05BC, 0, + 1, 0xFB35, 0x05D5, 0x05BC, 0, + 1, 0xFB36, 0x05D6, 0x05BC, 0, + 1, 0xFB38, 0x05D8, 0x05BC, 0, + 1, 0xFB39, 0x05D9, 0x05BC, 0, + 1, 0xFB3A, 0x05DA, 0x05BC, 0, + 1, 0xFB3B, 0x05DB, 0x05BC, 0, + 1, 0xFB3C, 0x05DC, 0x05BC, 0, + 1, 0xFB3E, 0x05DE, 0x05BC, 0, + 1, 0xFB40, 0x05E0, 0x05BC, 0, + 1, 0xFB41, 0x05E1, 0x05BC, 0, + 1, 0xFB43, 0x05E3, 0x05BC, 0, + 1, 0xFB44, 0x05E4, 0x05BC, 0, + 1, 0xFB46, 0x05E6, 0x05BC, 0, + 1, 0xFB47, 0x05E7, 0x05BC, 0, + 1, 0xFB48, 0x05E8, 0x05BC, 0, + 1, 0xFB49, 0x05E9, 0x05BC, 0, + 1, 0xFB4A, 0x05EA, 0x05BC, 0, + 1, 0xFB4B, 0x05D5, 0x05B9, 0, + 1, 0xFB4C, 0x05D1, 0x05BF, 0, + 1, 0xFB4D, 0x05DB, 0x05BF, 0, + 1, 0xFB4E, 0x05E4, 0x05BF, 0, + 16, 0xFB4F, 0x05D0, 0x05DC, 0, + 7, 0xFB50, 0x0671, 0, + 6, 0xFB51, 0x0671, 0, + 7, 0xFB52, 0x067B, 0, + 6, 0xFB53, 0x067B, 0, + 4, 0xFB54, 0x067B, 0, + 5, 0xFB55, 0x067B, 0, + 7, 0xFB56, 0x067E, 0, + 6, 0xFB57, 0x067E, 0, + 4, 0xFB58, 0x067E, 0, + 5, 0xFB59, 0x067E, 0, + 7, 0xFB5A, 0x0680, 0, + 6, 0xFB5B, 0x0680, 0, + 4, 0xFB5C, 0x0680, 0, + 5, 0xFB5D, 0x0680, 0, + 7, 0xFB5E, 0x067A, 0, + 6, 0xFB5F, 0x067A, 0, + 4, 0xFB60, 0x067A, 0, + 5, 0xFB61, 0x067A, 0, + 7, 0xFB62, 0x067F, 0, + 6, 0xFB63, 0x067F, 0, + 4, 0xFB64, 0x067F, 0, + 5, 0xFB65, 0x067F, 0, + 7, 0xFB66, 0x0679, 0, + 6, 0xFB67, 0x0679, 0, + 4, 0xFB68, 0x0679, 0, + 5, 0xFB69, 0x0679, 0, + 7, 0xFB6A, 0x06A4, 0, + 6, 0xFB6B, 0x06A4, 0, + 4, 0xFB6C, 0x06A4, 0, + 5, 0xFB6D, 0x06A4, 0, + 7, 0xFB6E, 0x06A6, 0, + 6, 0xFB6F, 0x06A6, 0, + 4, 0xFB70, 0x06A6, 0, + 5, 0xFB71, 0x06A6, 0, + 7, 0xFB72, 0x0684, 0, + 6, 0xFB73, 0x0684, 0, + 4, 0xFB74, 0x0684, 0, + 5, 0xFB75, 0x0684, 0, + 7, 0xFB76, 0x0683, 0, + 6, 0xFB77, 0x0683, 0, + 4, 0xFB78, 0x0683, 0, + 5, 0xFB79, 0x0683, 0, + 7, 0xFB7A, 0x0686, 0, + 6, 0xFB7B, 0x0686, 0, + 4, 0xFB7C, 0x0686, 0, + 5, 0xFB7D, 0x0686, 0, + 7, 0xFB7E, 0x0687, 0, + 6, 0xFB7F, 0x0687, 0, + 4, 0xFB80, 0x0687, 0, + 5, 0xFB81, 0x0687, 0, + 7, 0xFB82, 0x068D, 0, + 6, 0xFB83, 0x068D, 0, + 7, 0xFB84, 0x068C, 0, + 6, 0xFB85, 0x068C, 0, + 7, 0xFB86, 0x068E, 0, + 6, 0xFB87, 0x068E, 0, + 7, 0xFB88, 0x0688, 0, + 6, 0xFB89, 0x0688, 0, + 7, 0xFB8A, 0x0698, 0, + 6, 0xFB8B, 0x0698, 0, + 7, 0xFB8C, 0x0691, 0, + 6, 0xFB8D, 0x0691, 0, + 7, 0xFB8E, 0x06A9, 0, + 6, 0xFB8F, 0x06A9, 0, + 4, 0xFB90, 0x06A9, 0, + 5, 0xFB91, 0x06A9, 0, + 7, 0xFB92, 0x06AF, 0, + 6, 0xFB93, 0x06AF, 0, + 4, 0xFB94, 0x06AF, 0, + 5, 0xFB95, 0x06AF, 0, + 7, 0xFB96, 0x06B3, 0, + 6, 0xFB97, 0x06B3, 0, + 4, 0xFB98, 0x06B3, 0, + 5, 0xFB99, 0x06B3, 0, + 7, 0xFB9A, 0x06B1, 0, + 6, 0xFB9B, 0x06B1, 0, + 4, 0xFB9C, 0x06B1, 0, + 5, 0xFB9D, 0x06B1, 0, + 7, 0xFB9E, 0x06BA, 0, + 6, 0xFB9F, 0x06BA, 0, + 7, 0xFBA0, 0x06BB, 0, + 6, 0xFBA1, 0x06BB, 0, + 4, 0xFBA2, 0x06BB, 0, + 5, 0xFBA3, 0x06BB, 0, + 7, 0xFBA4, 0x06C0, 0, + 6, 0xFBA5, 0x06C0, 0, + 7, 0xFBA6, 0x06C1, 0, + 6, 0xFBA7, 0x06C1, 0, + 4, 0xFBA8, 0x06C1, 0, + 5, 0xFBA9, 0x06C1, 0, + 7, 0xFBAA, 0x06BE, 0, + 6, 0xFBAB, 0x06BE, 0, + 4, 0xFBAC, 0x06BE, 0, + 5, 0xFBAD, 0x06BE, 0, + 7, 0xFBAE, 0x06D2, 0, + 6, 0xFBAF, 0x06D2, 0, + 7, 0xFBB0, 0x06D3, 0, + 6, 0xFBB1, 0x06D3, 0, + 7, 0xFBD3, 0x06AD, 0, + 6, 0xFBD4, 0x06AD, 0, + 4, 0xFBD5, 0x06AD, 0, + 5, 0xFBD6, 0x06AD, 0, + 7, 0xFBD7, 0x06C7, 0, + 6, 0xFBD8, 0x06C7, 0, + 7, 0xFBD9, 0x06C6, 0, + 6, 0xFBDA, 0x06C6, 0, + 7, 0xFBDB, 0x06C8, 0, + 6, 0xFBDC, 0x06C8, 0, + 7, 0xFBDD, 0x0677, 0, + 7, 0xFBDE, 0x06CB, 0, + 6, 0xFBDF, 0x06CB, 0, + 7, 0xFBE0, 0x06C5, 0, + 6, 0xFBE1, 0x06C5, 0, + 7, 0xFBE2, 0x06C9, 0, + 6, 0xFBE3, 0x06C9, 0, + 7, 0xFBE4, 0x06D0, 0, + 6, 0xFBE5, 0x06D0, 0, + 4, 0xFBE6, 0x06D0, 0, + 5, 0xFBE7, 0x06D0, 0, + 4, 0xFBE8, 0x0649, 0, + 5, 0xFBE9, 0x0649, 0, + 7, 0xFBEA, 0x0626, 0x0627, 0, + 6, 0xFBEB, 0x0626, 0x0627, 0, + 7, 0xFBEC, 0x0626, 0x06D5, 0, + 6, 0xFBED, 0x0626, 0x06D5, 0, + 7, 0xFBEE, 0x0626, 0x0648, 0, + 6, 0xFBEF, 0x0626, 0x0648, 0, + 7, 0xFBF0, 0x0626, 0x06C7, 0, + 6, 0xFBF1, 0x0626, 0x06C7, 0, + 7, 0xFBF2, 0x0626, 0x06C6, 0, + 6, 0xFBF3, 0x0626, 0x06C6, 0, + 7, 0xFBF4, 0x0626, 0x06C8, 0, + 6, 0xFBF5, 0x0626, 0x06C8, 0, + 7, 0xFBF6, 0x0626, 0x06D0, 0, + 6, 0xFBF7, 0x0626, 0x06D0, 0, + 4, 0xFBF8, 0x0626, 0x06D0, 0, + 7, 0xFBF9, 0x0626, 0x0649, 0, + 6, 0xFBFA, 0x0626, 0x0649, 0, + 4, 0xFBFB, 0x0626, 0x0649, 0, + 7, 0xFBFC, 0x06CC, 0, + 6, 0xFBFD, 0x06CC, 0, + 4, 0xFBFE, 0x06CC, 0, + 5, 0xFBFF, 0x06CC, 0, + 7, 0xFC00, 0x0626, 0x062C, 0, + 7, 0xFC01, 0x0626, 0x062D, 0, + 7, 0xFC02, 0x0626, 0x0645, 0, + 7, 0xFC03, 0x0626, 0x0649, 0, + 7, 0xFC04, 0x0626, 0x064A, 0, + 7, 0xFC05, 0x0628, 0x062C, 0, + 7, 0xFC06, 0x0628, 0x062D, 0, + 7, 0xFC07, 0x0628, 0x062E, 0, + 7, 0xFC08, 0x0628, 0x0645, 0, + 7, 0xFC09, 0x0628, 0x0649, 0, + 7, 0xFC0A, 0x0628, 0x064A, 0, + 7, 0xFC0B, 0x062A, 0x062C, 0, + 7, 0xFC0C, 0x062A, 0x062D, 0, + 7, 0xFC0D, 0x062A, 0x062E, 0, + 7, 0xFC0E, 0x062A, 0x0645, 0, + 7, 0xFC0F, 0x062A, 0x0649, 0, + 7, 0xFC10, 0x062A, 0x064A, 0, + 7, 0xFC11, 0x062B, 0x062C, 0, + 7, 0xFC12, 0x062B, 0x0645, 0, + 7, 0xFC13, 0x062B, 0x0649, 0, + 7, 0xFC14, 0x062B, 0x064A, 0, + 7, 0xFC15, 0x062C, 0x062D, 0, + 7, 0xFC16, 0x062C, 0x0645, 0, + 7, 0xFC17, 0x062D, 0x062C, 0, + 7, 0xFC18, 0x062D, 0x0645, 0, + 7, 0xFC19, 0x062E, 0x062C, 0, + 7, 0xFC1A, 0x062E, 0x062D, 0, + 7, 0xFC1B, 0x062E, 0x0645, 0, + 7, 0xFC1C, 0x0633, 0x062C, 0, + 7, 0xFC1D, 0x0633, 0x062D, 0, + 7, 0xFC1E, 0x0633, 0x062E, 0, + 7, 0xFC1F, 0x0633, 0x0645, 0, + 7, 0xFC20, 0x0635, 0x062D, 0, + 7, 0xFC21, 0x0635, 0x0645, 0, + 7, 0xFC22, 0x0636, 0x062C, 0, + 7, 0xFC23, 0x0636, 0x062D, 0, + 7, 0xFC24, 0x0636, 0x062E, 0, + 7, 0xFC25, 0x0636, 0x0645, 0, + 7, 0xFC26, 0x0637, 0x062D, 0, + 7, 0xFC27, 0x0637, 0x0645, 0, + 7, 0xFC28, 0x0638, 0x0645, 0, + 7, 0xFC29, 0x0639, 0x062C, 0, + 7, 0xFC2A, 0x0639, 0x0645, 0, + 7, 0xFC2B, 0x063A, 0x062C, 0, + 7, 0xFC2C, 0x063A, 0x0645, 0, + 7, 0xFC2D, 0x0641, 0x062C, 0, + 7, 0xFC2E, 0x0641, 0x062D, 0, + 7, 0xFC2F, 0x0641, 0x062E, 0, + 7, 0xFC30, 0x0641, 0x0645, 0, + 7, 0xFC31, 0x0641, 0x0649, 0, + 7, 0xFC32, 0x0641, 0x064A, 0, + 7, 0xFC33, 0x0642, 0x062D, 0, + 7, 0xFC34, 0x0642, 0x0645, 0, + 7, 0xFC35, 0x0642, 0x0649, 0, + 7, 0xFC36, 0x0642, 0x064A, 0, + 7, 0xFC37, 0x0643, 0x0627, 0, + 7, 0xFC38, 0x0643, 0x062C, 0, + 7, 0xFC39, 0x0643, 0x062D, 0, + 7, 0xFC3A, 0x0643, 0x062E, 0, + 7, 0xFC3B, 0x0643, 0x0644, 0, + 7, 0xFC3C, 0x0643, 0x0645, 0, + 7, 0xFC3D, 0x0643, 0x0649, 0, + 7, 0xFC3E, 0x0643, 0x064A, 0, + 7, 0xFC3F, 0x0644, 0x062C, 0, + 7, 0xFC40, 0x0644, 0x062D, 0, + 7, 0xFC41, 0x0644, 0x062E, 0, + 7, 0xFC42, 0x0644, 0x0645, 0, + 7, 0xFC43, 0x0644, 0x0649, 0, + 7, 0xFC44, 0x0644, 0x064A, 0, + 7, 0xFC45, 0x0645, 0x062C, 0, + 7, 0xFC46, 0x0645, 0x062D, 0, + 7, 0xFC47, 0x0645, 0x062E, 0, + 7, 0xFC48, 0x0645, 0x0645, 0, + 7, 0xFC49, 0x0645, 0x0649, 0, + 7, 0xFC4A, 0x0645, 0x064A, 0, + 7, 0xFC4B, 0x0646, 0x062C, 0, + 7, 0xFC4C, 0x0646, 0x062D, 0, + 7, 0xFC4D, 0x0646, 0x062E, 0, + 7, 0xFC4E, 0x0646, 0x0645, 0, + 7, 0xFC4F, 0x0646, 0x0649, 0, + 7, 0xFC50, 0x0646, 0x064A, 0, + 7, 0xFC51, 0x0647, 0x062C, 0, + 7, 0xFC52, 0x0647, 0x0645, 0, + 7, 0xFC53, 0x0647, 0x0649, 0, + 7, 0xFC54, 0x0647, 0x064A, 0, + 7, 0xFC55, 0x064A, 0x062C, 0, + 7, 0xFC56, 0x064A, 0x062D, 0, + 7, 0xFC57, 0x064A, 0x062E, 0, + 7, 0xFC58, 0x064A, 0x0645, 0, + 7, 0xFC59, 0x064A, 0x0649, 0, + 7, 0xFC5A, 0x064A, 0x064A, 0, + 7, 0xFC5B, 0x0630, 0x0670, 0, + 7, 0xFC5C, 0x0631, 0x0670, 0, + 7, 0xFC5D, 0x0649, 0x0670, 0, + 7, 0xFC5E, 0x0020, 0x064C, 0x0651, 0, + 7, 0xFC5F, 0x0020, 0x064D, 0x0651, 0, + 7, 0xFC60, 0x0020, 0x064E, 0x0651, 0, + 7, 0xFC61, 0x0020, 0x064F, 0x0651, 0, + 7, 0xFC62, 0x0020, 0x0650, 0x0651, 0, + 7, 0xFC63, 0x0020, 0x0651, 0x0670, 0, + 6, 0xFC64, 0x0626, 0x0631, 0, + 6, 0xFC65, 0x0626, 0x0632, 0, + 6, 0xFC66, 0x0626, 0x0645, 0, + 6, 0xFC67, 0x0626, 0x0646, 0, + 6, 0xFC68, 0x0626, 0x0649, 0, + 6, 0xFC69, 0x0626, 0x064A, 0, + 6, 0xFC6A, 0x0628, 0x0631, 0, + 6, 0xFC6B, 0x0628, 0x0632, 0, + 6, 0xFC6C, 0x0628, 0x0645, 0, + 6, 0xFC6D, 0x0628, 0x0646, 0, + 6, 0xFC6E, 0x0628, 0x0649, 0, + 6, 0xFC6F, 0x0628, 0x064A, 0, + 6, 0xFC70, 0x062A, 0x0631, 0, + 6, 0xFC71, 0x062A, 0x0632, 0, + 6, 0xFC72, 0x062A, 0x0645, 0, + 6, 0xFC73, 0x062A, 0x0646, 0, + 6, 0xFC74, 0x062A, 0x0649, 0, + 6, 0xFC75, 0x062A, 0x064A, 0, + 6, 0xFC76, 0x062B, 0x0631, 0, + 6, 0xFC77, 0x062B, 0x0632, 0, + 6, 0xFC78, 0x062B, 0x0645, 0, + 6, 0xFC79, 0x062B, 0x0646, 0, + 6, 0xFC7A, 0x062B, 0x0649, 0, + 6, 0xFC7B, 0x062B, 0x064A, 0, + 6, 0xFC7C, 0x0641, 0x0649, 0, + 6, 0xFC7D, 0x0641, 0x064A, 0, + 6, 0xFC7E, 0x0642, 0x0649, 0, + 6, 0xFC7F, 0x0642, 0x064A, 0, + 6, 0xFC80, 0x0643, 0x0627, 0, + 6, 0xFC81, 0x0643, 0x0644, 0, + 6, 0xFC82, 0x0643, 0x0645, 0, + 6, 0xFC83, 0x0643, 0x0649, 0, + 6, 0xFC84, 0x0643, 0x064A, 0, + 6, 0xFC85, 0x0644, 0x0645, 0, + 6, 0xFC86, 0x0644, 0x0649, 0, + 6, 0xFC87, 0x0644, 0x064A, 0, + 6, 0xFC88, 0x0645, 0x0627, 0, + 6, 0xFC89, 0x0645, 0x0645, 0, + 6, 0xFC8A, 0x0646, 0x0631, 0, + 6, 0xFC8B, 0x0646, 0x0632, 0, + 6, 0xFC8C, 0x0646, 0x0645, 0, + 6, 0xFC8D, 0x0646, 0x0646, 0, + 6, 0xFC8E, 0x0646, 0x0649, 0, + 6, 0xFC8F, 0x0646, 0x064A, 0, + 6, 0xFC90, 0x0649, 0x0670, 0, + 6, 0xFC91, 0x064A, 0x0631, 0, + 6, 0xFC92, 0x064A, 0x0632, 0, + 6, 0xFC93, 0x064A, 0x0645, 0, + 6, 0xFC94, 0x064A, 0x0646, 0, + 6, 0xFC95, 0x064A, 0x0649, 0, + 6, 0xFC96, 0x064A, 0x064A, 0, + 4, 0xFC97, 0x0626, 0x062C, 0, + 4, 0xFC98, 0x0626, 0x062D, 0, + 4, 0xFC99, 0x0626, 0x062E, 0, + 4, 0xFC9A, 0x0626, 0x0645, 0, + 4, 0xFC9B, 0x0626, 0x0647, 0, + 4, 0xFC9C, 0x0628, 0x062C, 0, + 4, 0xFC9D, 0x0628, 0x062D, 0, + 4, 0xFC9E, 0x0628, 0x062E, 0, + 4, 0xFC9F, 0x0628, 0x0645, 0, + 4, 0xFCA0, 0x0628, 0x0647, 0, + 4, 0xFCA1, 0x062A, 0x062C, 0, + 4, 0xFCA2, 0x062A, 0x062D, 0, + 4, 0xFCA3, 0x062A, 0x062E, 0, + 4, 0xFCA4, 0x062A, 0x0645, 0, + 4, 0xFCA5, 0x062A, 0x0647, 0, + 4, 0xFCA6, 0x062B, 0x0645, 0, + 4, 0xFCA7, 0x062C, 0x062D, 0, + 4, 0xFCA8, 0x062C, 0x0645, 0, + 4, 0xFCA9, 0x062D, 0x062C, 0, + 4, 0xFCAA, 0x062D, 0x0645, 0, + 4, 0xFCAB, 0x062E, 0x062C, 0, + 4, 0xFCAC, 0x062E, 0x0645, 0, + 4, 0xFCAD, 0x0633, 0x062C, 0, + 4, 0xFCAE, 0x0633, 0x062D, 0, + 4, 0xFCAF, 0x0633, 0x062E, 0, + 4, 0xFCB0, 0x0633, 0x0645, 0, + 4, 0xFCB1, 0x0635, 0x062D, 0, + 4, 0xFCB2, 0x0635, 0x062E, 0, + 4, 0xFCB3, 0x0635, 0x0645, 0, + 4, 0xFCB4, 0x0636, 0x062C, 0, + 4, 0xFCB5, 0x0636, 0x062D, 0, + 4, 0xFCB6, 0x0636, 0x062E, 0, + 4, 0xFCB7, 0x0636, 0x0645, 0, + 4, 0xFCB8, 0x0637, 0x062D, 0, + 4, 0xFCB9, 0x0638, 0x0645, 0, + 4, 0xFCBA, 0x0639, 0x062C, 0, + 4, 0xFCBB, 0x0639, 0x0645, 0, + 4, 0xFCBC, 0x063A, 0x062C, 0, + 4, 0xFCBD, 0x063A, 0x0645, 0, + 4, 0xFCBE, 0x0641, 0x062C, 0, + 4, 0xFCBF, 0x0641, 0x062D, 0, + 4, 0xFCC0, 0x0641, 0x062E, 0, + 4, 0xFCC1, 0x0641, 0x0645, 0, + 4, 0xFCC2, 0x0642, 0x062D, 0, + 4, 0xFCC3, 0x0642, 0x0645, 0, + 4, 0xFCC4, 0x0643, 0x062C, 0, + 4, 0xFCC5, 0x0643, 0x062D, 0, + 4, 0xFCC6, 0x0643, 0x062E, 0, + 4, 0xFCC7, 0x0643, 0x0644, 0, + 4, 0xFCC8, 0x0643, 0x0645, 0, + 4, 0xFCC9, 0x0644, 0x062C, 0, + 4, 0xFCCA, 0x0644, 0x062D, 0, + 4, 0xFCCB, 0x0644, 0x062E, 0, + 4, 0xFCCC, 0x0644, 0x0645, 0, + 4, 0xFCCD, 0x0644, 0x0647, 0, + 4, 0xFCCE, 0x0645, 0x062C, 0, + 4, 0xFCCF, 0x0645, 0x062D, 0, + 4, 0xFCD0, 0x0645, 0x062E, 0, + 4, 0xFCD1, 0x0645, 0x0645, 0, + 4, 0xFCD2, 0x0646, 0x062C, 0, + 4, 0xFCD3, 0x0646, 0x062D, 0, + 4, 0xFCD4, 0x0646, 0x062E, 0, + 4, 0xFCD5, 0x0646, 0x0645, 0, + 4, 0xFCD6, 0x0646, 0x0647, 0, + 4, 0xFCD7, 0x0647, 0x062C, 0, + 4, 0xFCD8, 0x0647, 0x0645, 0, + 4, 0xFCD9, 0x0647, 0x0670, 0, + 4, 0xFCDA, 0x064A, 0x062C, 0, + 4, 0xFCDB, 0x064A, 0x062D, 0, + 4, 0xFCDC, 0x064A, 0x062E, 0, + 4, 0xFCDD, 0x064A, 0x0645, 0, + 4, 0xFCDE, 0x064A, 0x0647, 0, + 5, 0xFCDF, 0x0626, 0x0645, 0, + 5, 0xFCE0, 0x0626, 0x0647, 0, + 5, 0xFCE1, 0x0628, 0x0645, 0, + 5, 0xFCE2, 0x0628, 0x0647, 0, + 5, 0xFCE3, 0x062A, 0x0645, 0, + 5, 0xFCE4, 0x062A, 0x0647, 0, + 5, 0xFCE5, 0x062B, 0x0645, 0, + 5, 0xFCE6, 0x062B, 0x0647, 0, + 5, 0xFCE7, 0x0633, 0x0645, 0, + 5, 0xFCE8, 0x0633, 0x0647, 0, + 5, 0xFCE9, 0x0634, 0x0645, 0, + 5, 0xFCEA, 0x0634, 0x0647, 0, + 5, 0xFCEB, 0x0643, 0x0644, 0, + 5, 0xFCEC, 0x0643, 0x0645, 0, + 5, 0xFCED, 0x0644, 0x0645, 0, + 5, 0xFCEE, 0x0646, 0x0645, 0, + 5, 0xFCEF, 0x0646, 0x0647, 0, + 5, 0xFCF0, 0x064A, 0x0645, 0, + 5, 0xFCF1, 0x064A, 0x0647, 0, + 5, 0xFCF2, 0x0640, 0x064E, 0x0651, 0, + 5, 0xFCF3, 0x0640, 0x064F, 0x0651, 0, + 5, 0xFCF4, 0x0640, 0x0650, 0x0651, 0, + 7, 0xFCF5, 0x0637, 0x0649, 0, + 7, 0xFCF6, 0x0637, 0x064A, 0, + 7, 0xFCF7, 0x0639, 0x0649, 0, + 7, 0xFCF8, 0x0639, 0x064A, 0, + 7, 0xFCF9, 0x063A, 0x0649, 0, + 7, 0xFCFA, 0x063A, 0x064A, 0, + 7, 0xFCFB, 0x0633, 0x0649, 0, + 7, 0xFCFC, 0x0633, 0x064A, 0, + 7, 0xFCFD, 0x0634, 0x0649, 0, + 7, 0xFCFE, 0x0634, 0x064A, 0, + 7, 0xFCFF, 0x062D, 0x0649, 0, + 7, 0xFD00, 0x062D, 0x064A, 0, + 7, 0xFD01, 0x062C, 0x0649, 0, + 7, 0xFD02, 0x062C, 0x064A, 0, + 7, 0xFD03, 0x062E, 0x0649, 0, + 7, 0xFD04, 0x062E, 0x064A, 0, + 7, 0xFD05, 0x0635, 0x0649, 0, + 7, 0xFD06, 0x0635, 0x064A, 0, + 7, 0xFD07, 0x0636, 0x0649, 0, + 7, 0xFD08, 0x0636, 0x064A, 0, + 7, 0xFD09, 0x0634, 0x062C, 0, + 7, 0xFD0A, 0x0634, 0x062D, 0, + 7, 0xFD0B, 0x0634, 0x062E, 0, + 7, 0xFD0C, 0x0634, 0x0645, 0, + 7, 0xFD0D, 0x0634, 0x0631, 0, + 7, 0xFD0E, 0x0633, 0x0631, 0, + 7, 0xFD0F, 0x0635, 0x0631, 0, + 7, 0xFD10, 0x0636, 0x0631, 0, + 6, 0xFD11, 0x0637, 0x0649, 0, + 6, 0xFD12, 0x0637, 0x064A, 0, + 6, 0xFD13, 0x0639, 0x0649, 0, + 6, 0xFD14, 0x0639, 0x064A, 0, + 6, 0xFD15, 0x063A, 0x0649, 0, + 6, 0xFD16, 0x063A, 0x064A, 0, + 6, 0xFD17, 0x0633, 0x0649, 0, + 6, 0xFD18, 0x0633, 0x064A, 0, + 6, 0xFD19, 0x0634, 0x0649, 0, + 6, 0xFD1A, 0x0634, 0x064A, 0, + 6, 0xFD1B, 0x062D, 0x0649, 0, + 6, 0xFD1C, 0x062D, 0x064A, 0, + 6, 0xFD1D, 0x062C, 0x0649, 0, + 6, 0xFD1E, 0x062C, 0x064A, 0, + 6, 0xFD1F, 0x062E, 0x0649, 0, + 6, 0xFD20, 0x062E, 0x064A, 0, + 6, 0xFD21, 0x0635, 0x0649, 0, + 6, 0xFD22, 0x0635, 0x064A, 0, + 6, 0xFD23, 0x0636, 0x0649, 0, + 6, 0xFD24, 0x0636, 0x064A, 0, + 6, 0xFD25, 0x0634, 0x062C, 0, + 6, 0xFD26, 0x0634, 0x062D, 0, + 6, 0xFD27, 0x0634, 0x062E, 0, + 6, 0xFD28, 0x0634, 0x0645, 0, + 6, 0xFD29, 0x0634, 0x0631, 0, + 6, 0xFD2A, 0x0633, 0x0631, 0, + 6, 0xFD2B, 0x0635, 0x0631, 0, + 6, 0xFD2C, 0x0636, 0x0631, 0, + 4, 0xFD2D, 0x0634, 0x062C, 0, + 4, 0xFD2E, 0x0634, 0x062D, 0, + 4, 0xFD2F, 0x0634, 0x062E, 0, + 4, 0xFD30, 0x0634, 0x0645, 0, + 4, 0xFD31, 0x0633, 0x0647, 0, + 4, 0xFD32, 0x0634, 0x0647, 0, + 4, 0xFD33, 0x0637, 0x0645, 0, + 5, 0xFD34, 0x0633, 0x062C, 0, + 5, 0xFD35, 0x0633, 0x062D, 0, + 5, 0xFD36, 0x0633, 0x062E, 0, + 5, 0xFD37, 0x0634, 0x062C, 0, + 5, 0xFD38, 0x0634, 0x062D, 0, + 5, 0xFD39, 0x0634, 0x062E, 0, + 5, 0xFD3A, 0x0637, 0x0645, 0, + 5, 0xFD3B, 0x0638, 0x0645, 0, + 6, 0xFD3C, 0x0627, 0x064B, 0, + 7, 0xFD3D, 0x0627, 0x064B, 0, + 4, 0xFD50, 0x062A, 0x062C, 0x0645, 0, + 6, 0xFD51, 0x062A, 0x062D, 0x062C, 0, + 4, 0xFD52, 0x062A, 0x062D, 0x062C, 0, + 4, 0xFD53, 0x062A, 0x062D, 0x0645, 0, + 4, 0xFD54, 0x062A, 0x062E, 0x0645, 0, + 4, 0xFD55, 0x062A, 0x0645, 0x062C, 0, + 4, 0xFD56, 0x062A, 0x0645, 0x062D, 0, + 4, 0xFD57, 0x062A, 0x0645, 0x062E, 0, + 6, 0xFD58, 0x062C, 0x0645, 0x062D, 0, + 4, 0xFD59, 0x062C, 0x0645, 0x062D, 0, + 6, 0xFD5A, 0x062D, 0x0645, 0x064A, 0, + 6, 0xFD5B, 0x062D, 0x0645, 0x0649, 0, + 4, 0xFD5C, 0x0633, 0x062D, 0x062C, 0, + 4, 0xFD5D, 0x0633, 0x062C, 0x062D, 0, + 6, 0xFD5E, 0x0633, 0x062C, 0x0649, 0, + 6, 0xFD5F, 0x0633, 0x0645, 0x062D, 0, + 4, 0xFD60, 0x0633, 0x0645, 0x062D, 0, + 4, 0xFD61, 0x0633, 0x0645, 0x062C, 0, + 6, 0xFD62, 0x0633, 0x0645, 0x0645, 0, + 4, 0xFD63, 0x0633, 0x0645, 0x0645, 0, + 6, 0xFD64, 0x0635, 0x062D, 0x062D, 0, + 4, 0xFD65, 0x0635, 0x062D, 0x062D, 0, + 6, 0xFD66, 0x0635, 0x0645, 0x0645, 0, + 6, 0xFD67, 0x0634, 0x062D, 0x0645, 0, + 4, 0xFD68, 0x0634, 0x062D, 0x0645, 0, + 6, 0xFD69, 0x0634, 0x062C, 0x064A, 0, + 6, 0xFD6A, 0x0634, 0x0645, 0x062E, 0, + 4, 0xFD6B, 0x0634, 0x0645, 0x062E, 0, + 6, 0xFD6C, 0x0634, 0x0645, 0x0645, 0, + 4, 0xFD6D, 0x0634, 0x0645, 0x0645, 0, + 6, 0xFD6E, 0x0636, 0x062D, 0x0649, 0, + 6, 0xFD6F, 0x0636, 0x062E, 0x0645, 0, + 4, 0xFD70, 0x0636, 0x062E, 0x0645, 0, + 6, 0xFD71, 0x0637, 0x0645, 0x062D, 0, + 4, 0xFD72, 0x0637, 0x0645, 0x062D, 0, + 4, 0xFD73, 0x0637, 0x0645, 0x0645, 0, + 6, 0xFD74, 0x0637, 0x0645, 0x064A, 0, + 6, 0xFD75, 0x0639, 0x062C, 0x0645, 0, + 6, 0xFD76, 0x0639, 0x0645, 0x0645, 0, + 4, 0xFD77, 0x0639, 0x0645, 0x0645, 0, + 6, 0xFD78, 0x0639, 0x0645, 0x0649, 0, + 6, 0xFD79, 0x063A, 0x0645, 0x0645, 0, + 6, 0xFD7A, 0x063A, 0x0645, 0x064A, 0, + 6, 0xFD7B, 0x063A, 0x0645, 0x0649, 0, + 6, 0xFD7C, 0x0641, 0x062E, 0x0645, 0, + 4, 0xFD7D, 0x0641, 0x062E, 0x0645, 0, + 6, 0xFD7E, 0x0642, 0x0645, 0x062D, 0, + 6, 0xFD7F, 0x0642, 0x0645, 0x0645, 0, + 6, 0xFD80, 0x0644, 0x062D, 0x0645, 0, + 6, 0xFD81, 0x0644, 0x062D, 0x064A, 0, + 6, 0xFD82, 0x0644, 0x062D, 0x0649, 0, + 4, 0xFD83, 0x0644, 0x062C, 0x062C, 0, + 6, 0xFD84, 0x0644, 0x062C, 0x062C, 0, + 6, 0xFD85, 0x0644, 0x062E, 0x0645, 0, + 4, 0xFD86, 0x0644, 0x062E, 0x0645, 0, + 6, 0xFD87, 0x0644, 0x0645, 0x062D, 0, + 4, 0xFD88, 0x0644, 0x0645, 0x062D, 0, + 4, 0xFD89, 0x0645, 0x062D, 0x062C, 0, + 4, 0xFD8A, 0x0645, 0x062D, 0x0645, 0, + 6, 0xFD8B, 0x0645, 0x062D, 0x064A, 0, + 4, 0xFD8C, 0x0645, 0x062C, 0x062D, 0, + 4, 0xFD8D, 0x0645, 0x062C, 0x0645, 0, + 4, 0xFD8E, 0x0645, 0x062E, 0x062C, 0, + 4, 0xFD8F, 0x0645, 0x062E, 0x0645, 0, + 4, 0xFD92, 0x0645, 0x062C, 0x062E, 0, + 4, 0xFD93, 0x0647, 0x0645, 0x062C, 0, + 4, 0xFD94, 0x0647, 0x0645, 0x0645, 0, + 4, 0xFD95, 0x0646, 0x062D, 0x0645, 0, + 6, 0xFD96, 0x0646, 0x062D, 0x0649, 0, + 6, 0xFD97, 0x0646, 0x062C, 0x0645, 0, + 4, 0xFD98, 0x0646, 0x062C, 0x0645, 0, + 6, 0xFD99, 0x0646, 0x062C, 0x0649, 0, + 6, 0xFD9A, 0x0646, 0x0645, 0x064A, 0, + 6, 0xFD9B, 0x0646, 0x0645, 0x0649, 0, + 6, 0xFD9C, 0x064A, 0x0645, 0x0645, 0, + 4, 0xFD9D, 0x064A, 0x0645, 0x0645, 0, + 6, 0xFD9E, 0x0628, 0x062E, 0x064A, 0, + 6, 0xFD9F, 0x062A, 0x062C, 0x064A, 0, + 6, 0xFDA0, 0x062A, 0x062C, 0x0649, 0, + 6, 0xFDA1, 0x062A, 0x062E, 0x064A, 0, + 6, 0xFDA2, 0x062A, 0x062E, 0x0649, 0, + 6, 0xFDA3, 0x062A, 0x0645, 0x064A, 0, + 6, 0xFDA4, 0x062A, 0x0645, 0x0649, 0, + 6, 0xFDA5, 0x062C, 0x0645, 0x064A, 0, + 6, 0xFDA6, 0x062C, 0x062D, 0x0649, 0, + 6, 0xFDA7, 0x062C, 0x0645, 0x0649, 0, + 6, 0xFDA8, 0x0633, 0x062E, 0x0649, 0, + 6, 0xFDA9, 0x0635, 0x062D, 0x064A, 0, + 6, 0xFDAA, 0x0634, 0x062D, 0x064A, 0, + 6, 0xFDAB, 0x0636, 0x062D, 0x064A, 0, + 6, 0xFDAC, 0x0644, 0x062C, 0x064A, 0, + 6, 0xFDAD, 0x0644, 0x0645, 0x064A, 0, + 6, 0xFDAE, 0x064A, 0x062D, 0x064A, 0, + 6, 0xFDAF, 0x064A, 0x062C, 0x064A, 0, + 6, 0xFDB0, 0x064A, 0x0645, 0x064A, 0, + 6, 0xFDB1, 0x0645, 0x0645, 0x064A, 0, + 6, 0xFDB2, 0x0642, 0x0645, 0x064A, 0, + 6, 0xFDB3, 0x0646, 0x062D, 0x064A, 0, + 4, 0xFDB4, 0x0642, 0x0645, 0x062D, 0, + 4, 0xFDB5, 0x0644, 0x062D, 0x0645, 0, + 6, 0xFDB6, 0x0639, 0x0645, 0x064A, 0, + 6, 0xFDB7, 0x0643, 0x0645, 0x064A, 0, + 4, 0xFDB8, 0x0646, 0x062C, 0x062D, 0, + 6, 0xFDB9, 0x0645, 0x062E, 0x064A, 0, + 4, 0xFDBA, 0x0644, 0x062C, 0x0645, 0, + 6, 0xFDBB, 0x0643, 0x0645, 0x0645, 0, + 6, 0xFDBC, 0x0644, 0x062C, 0x0645, 0, + 6, 0xFDBD, 0x0646, 0x062C, 0x062D, 0, + 6, 0xFDBE, 0x062C, 0x062D, 0x064A, 0, + 6, 0xFDBF, 0x062D, 0x062C, 0x064A, 0, + 6, 0xFDC0, 0x0645, 0x062C, 0x064A, 0, + 6, 0xFDC1, 0x0641, 0x0645, 0x064A, 0, + 6, 0xFDC2, 0x0628, 0x062D, 0x064A, 0, + 4, 0xFDC3, 0x0643, 0x0645, 0x0645, 0, + 4, 0xFDC4, 0x0639, 0x062C, 0x0645, 0, + 4, 0xFDC5, 0x0635, 0x0645, 0x0645, 0, + 6, 0xFDC6, 0x0633, 0x062E, 0x064A, 0, + 6, 0xFDC7, 0x0646, 0x062C, 0x064A, 0, + 7, 0xFDF0, 0x0635, 0x0644, 0x06D2, 0, + 7, 0xFDF1, 0x0642, 0x0644, 0x06D2, 0, + 7, 0xFDF2, 0x0627, 0x0644, 0x0644, 0x0647, 0, + 7, 0xFDF3, 0x0627, 0x0643, 0x0628, 0x0631, 0, + 7, 0xFDF4, 0x0645, 0x062D, 0x0645, 0x062F, 0, + 7, 0xFDF5, 0x0635, 0x0644, 0x0639, 0x0645, 0, + 7, 0xFDF6, 0x0631, 0x0633, 0x0648, 0x0644, 0, + 7, 0xFDF7, 0x0639, 0x0644, 0x064A, 0x0647, 0, + 7, 0xFDF8, 0x0648, 0x0633, 0x0644, 0x0645, 0, + 7, 0xFDF9, 0x0635, 0x0644, 0x0649, 0, + 7, 0xFDFA, 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645, 0, + 7, 0xFDFB, 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647, 0, + 7, 0xFDFC, 0x0631, 0x06CC, 0x0627, 0x0644, 0, + 11, 0xFE30, 0x2025, 0, + 11, 0xFE31, 0x2014, 0, + 11, 0xFE32, 0x2013, 0, + 11, 0xFE33, 0x005F, 0, + 11, 0xFE34, 0x005F, 0, + 11, 0xFE35, 0x0028, 0, + 11, 0xFE36, 0x0029, 0, + 11, 0xFE37, 0x007B, 0, + 11, 0xFE38, 0x007D, 0, + 11, 0xFE39, 0x3014, 0, + 11, 0xFE3A, 0x3015, 0, + 11, 0xFE3B, 0x3010, 0, + 11, 0xFE3C, 0x3011, 0, + 11, 0xFE3D, 0x300A, 0, + 11, 0xFE3E, 0x300B, 0, + 11, 0xFE3F, 0x3008, 0, + 11, 0xFE40, 0x3009, 0, + 11, 0xFE41, 0x300C, 0, + 11, 0xFE42, 0x300D, 0, + 11, 0xFE43, 0x300E, 0, + 11, 0xFE44, 0x300F, 0, + 16, 0xFE49, 0x203E, 0, + 16, 0xFE4A, 0x203E, 0, + 16, 0xFE4B, 0x203E, 0, + 16, 0xFE4C, 0x203E, 0, + 16, 0xFE4D, 0x005F, 0, + 16, 0xFE4E, 0x005F, 0, + 16, 0xFE4F, 0x005F, 0, + 14, 0xFE50, 0x002C, 0, + 14, 0xFE51, 0x3001, 0, + 14, 0xFE52, 0x002E, 0, + 14, 0xFE54, 0x003B, 0, + 14, 0xFE55, 0x003A, 0, + 14, 0xFE56, 0x003F, 0, + 14, 0xFE57, 0x0021, 0, + 14, 0xFE58, 0x2014, 0, + 14, 0xFE59, 0x0028, 0, + 14, 0xFE5A, 0x0029, 0, + 14, 0xFE5B, 0x007B, 0, + 14, 0xFE5C, 0x007D, 0, + 14, 0xFE5D, 0x3014, 0, + 14, 0xFE5E, 0x3015, 0, + 14, 0xFE5F, 0x0023, 0, + 14, 0xFE60, 0x0026, 0, + 14, 0xFE61, 0x002A, 0, + 14, 0xFE62, 0x002B, 0, + 14, 0xFE63, 0x002D, 0, + 14, 0xFE64, 0x003C, 0, + 14, 0xFE65, 0x003E, 0, + 14, 0xFE66, 0x003D, 0, + 14, 0xFE68, 0x005C, 0, + 14, 0xFE69, 0x0024, 0, + 14, 0xFE6A, 0x0025, 0, + 14, 0xFE6B, 0x0040, 0, + 7, 0xFE70, 0x0020, 0x064B, 0, + 5, 0xFE71, 0x0640, 0x064B, 0, + 7, 0xFE72, 0x0020, 0x064C, 0, + 7, 0xFE74, 0x0020, 0x064D, 0, + 7, 0xFE76, 0x0020, 0x064E, 0, + 5, 0xFE77, 0x0640, 0x064E, 0, + 7, 0xFE78, 0x0020, 0x064F, 0, + 5, 0xFE79, 0x0640, 0x064F, 0, + 7, 0xFE7A, 0x0020, 0x0650, 0, + 5, 0xFE7B, 0x0640, 0x0650, 0, + 7, 0xFE7C, 0x0020, 0x0651, 0, + 5, 0xFE7D, 0x0640, 0x0651, 0, + 7, 0xFE7E, 0x0020, 0x0652, 0, + 5, 0xFE7F, 0x0640, 0x0652, 0, + 7, 0xFE80, 0x0621, 0, + 7, 0xFE81, 0x0622, 0, + 6, 0xFE82, 0x0622, 0, + 7, 0xFE83, 0x0623, 0, + 6, 0xFE84, 0x0623, 0, + 7, 0xFE85, 0x0624, 0, + 6, 0xFE86, 0x0624, 0, + 7, 0xFE87, 0x0625, 0, + 6, 0xFE88, 0x0625, 0, + 7, 0xFE89, 0x0626, 0, + 6, 0xFE8A, 0x0626, 0, + 4, 0xFE8B, 0x0626, 0, + 5, 0xFE8C, 0x0626, 0, + 7, 0xFE8D, 0x0627, 0, + 6, 0xFE8E, 0x0627, 0, + 7, 0xFE8F, 0x0628, 0, + 6, 0xFE90, 0x0628, 0, + 4, 0xFE91, 0x0628, 0, + 5, 0xFE92, 0x0628, 0, + 7, 0xFE93, 0x0629, 0, + 6, 0xFE94, 0x0629, 0, + 7, 0xFE95, 0x062A, 0, + 6, 0xFE96, 0x062A, 0, + 4, 0xFE97, 0x062A, 0, + 5, 0xFE98, 0x062A, 0, + 7, 0xFE99, 0x062B, 0, + 6, 0xFE9A, 0x062B, 0, + 4, 0xFE9B, 0x062B, 0, + 5, 0xFE9C, 0x062B, 0, + 7, 0xFE9D, 0x062C, 0, + 6, 0xFE9E, 0x062C, 0, + 4, 0xFE9F, 0x062C, 0, + 5, 0xFEA0, 0x062C, 0, + 7, 0xFEA1, 0x062D, 0, + 6, 0xFEA2, 0x062D, 0, + 4, 0xFEA3, 0x062D, 0, + 5, 0xFEA4, 0x062D, 0, + 7, 0xFEA5, 0x062E, 0, + 6, 0xFEA6, 0x062E, 0, + 4, 0xFEA7, 0x062E, 0, + 5, 0xFEA8, 0x062E, 0, + 7, 0xFEA9, 0x062F, 0, + 6, 0xFEAA, 0x062F, 0, + 7, 0xFEAB, 0x0630, 0, + 6, 0xFEAC, 0x0630, 0, + 7, 0xFEAD, 0x0631, 0, + 6, 0xFEAE, 0x0631, 0, + 7, 0xFEAF, 0x0632, 0, + 6, 0xFEB0, 0x0632, 0, + 7, 0xFEB1, 0x0633, 0, + 6, 0xFEB2, 0x0633, 0, + 4, 0xFEB3, 0x0633, 0, + 5, 0xFEB4, 0x0633, 0, + 7, 0xFEB5, 0x0634, 0, + 6, 0xFEB6, 0x0634, 0, + 4, 0xFEB7, 0x0634, 0, + 5, 0xFEB8, 0x0634, 0, + 7, 0xFEB9, 0x0635, 0, + 6, 0xFEBA, 0x0635, 0, + 4, 0xFEBB, 0x0635, 0, + 5, 0xFEBC, 0x0635, 0, + 7, 0xFEBD, 0x0636, 0, + 6, 0xFEBE, 0x0636, 0, + 4, 0xFEBF, 0x0636, 0, + 5, 0xFEC0, 0x0636, 0, + 7, 0xFEC1, 0x0637, 0, + 6, 0xFEC2, 0x0637, 0, + 4, 0xFEC3, 0x0637, 0, + 5, 0xFEC4, 0x0637, 0, + 7, 0xFEC5, 0x0638, 0, + 6, 0xFEC6, 0x0638, 0, + 4, 0xFEC7, 0x0638, 0, + 5, 0xFEC8, 0x0638, 0, + 7, 0xFEC9, 0x0639, 0, + 6, 0xFECA, 0x0639, 0, + 4, 0xFECB, 0x0639, 0, + 5, 0xFECC, 0x0639, 0, + 7, 0xFECD, 0x063A, 0, + 6, 0xFECE, 0x063A, 0, + 4, 0xFECF, 0x063A, 0, + 5, 0xFED0, 0x063A, 0, + 7, 0xFED1, 0x0641, 0, + 6, 0xFED2, 0x0641, 0, + 4, 0xFED3, 0x0641, 0, + 5, 0xFED4, 0x0641, 0, + 7, 0xFED5, 0x0642, 0, + 6, 0xFED6, 0x0642, 0, + 4, 0xFED7, 0x0642, 0, + 5, 0xFED8, 0x0642, 0, + 7, 0xFED9, 0x0643, 0, + 6, 0xFEDA, 0x0643, 0, + 4, 0xFEDB, 0x0643, 0, + 5, 0xFEDC, 0x0643, 0, + 7, 0xFEDD, 0x0644, 0, + 6, 0xFEDE, 0x0644, 0, + 4, 0xFEDF, 0x0644, 0, + 5, 0xFEE0, 0x0644, 0, + 7, 0xFEE1, 0x0645, 0, + 6, 0xFEE2, 0x0645, 0, + 4, 0xFEE3, 0x0645, 0, + 5, 0xFEE4, 0x0645, 0, + 7, 0xFEE5, 0x0646, 0, + 6, 0xFEE6, 0x0646, 0, + 4, 0xFEE7, 0x0646, 0, + 5, 0xFEE8, 0x0646, 0, + 7, 0xFEE9, 0x0647, 0, + 6, 0xFEEA, 0x0647, 0, + 4, 0xFEEB, 0x0647, 0, + 5, 0xFEEC, 0x0647, 0, + 7, 0xFEED, 0x0648, 0, + 6, 0xFEEE, 0x0648, 0, + 7, 0xFEEF, 0x0649, 0, + 6, 0xFEF0, 0x0649, 0, + 7, 0xFEF1, 0x064A, 0, + 6, 0xFEF2, 0x064A, 0, + 4, 0xFEF3, 0x064A, 0, + 5, 0xFEF4, 0x064A, 0, + 7, 0xFEF5, 0x0644, 0x0622, 0, + 6, 0xFEF6, 0x0644, 0x0622, 0, + 7, 0xFEF7, 0x0644, 0x0623, 0, + 6, 0xFEF8, 0x0644, 0x0623, 0, + 7, 0xFEF9, 0x0644, 0x0625, 0, + 6, 0xFEFA, 0x0644, 0x0625, 0, + 7, 0xFEFB, 0x0644, 0x0627, 0, + 6, 0xFEFC, 0x0644, 0x0627, 0, + 12, 0xFF01, 0x0021, 0, + 12, 0xFF02, 0x0022, 0, + 12, 0xFF03, 0x0023, 0, + 12, 0xFF04, 0x0024, 0, + 12, 0xFF05, 0x0025, 0, + 12, 0xFF06, 0x0026, 0, + 12, 0xFF07, 0x0027, 0, + 12, 0xFF08, 0x0028, 0, + 12, 0xFF09, 0x0029, 0, + 12, 0xFF0A, 0x002A, 0, + 12, 0xFF0B, 0x002B, 0, + 12, 0xFF0C, 0x002C, 0, + 12, 0xFF0D, 0x002D, 0, + 12, 0xFF0E, 0x002E, 0, + 12, 0xFF0F, 0x002F, 0, + 12, 0xFF10, 0x0030, 0, + 12, 0xFF11, 0x0031, 0, + 12, 0xFF12, 0x0032, 0, + 12, 0xFF13, 0x0033, 0, + 12, 0xFF14, 0x0034, 0, + 12, 0xFF15, 0x0035, 0, + 12, 0xFF16, 0x0036, 0, + 12, 0xFF17, 0x0037, 0, + 12, 0xFF18, 0x0038, 0, + 12, 0xFF19, 0x0039, 0, + 12, 0xFF1A, 0x003A, 0, + 12, 0xFF1B, 0x003B, 0, + 12, 0xFF1C, 0x003C, 0, + 12, 0xFF1D, 0x003D, 0, + 12, 0xFF1E, 0x003E, 0, + 12, 0xFF1F, 0x003F, 0, + 12, 0xFF20, 0x0040, 0, + 12, 0xFF21, 0x0041, 0, + 12, 0xFF22, 0x0042, 0, + 12, 0xFF23, 0x0043, 0, + 12, 0xFF24, 0x0044, 0, + 12, 0xFF25, 0x0045, 0, + 12, 0xFF26, 0x0046, 0, + 12, 0xFF27, 0x0047, 0, + 12, 0xFF28, 0x0048, 0, + 12, 0xFF29, 0x0049, 0, + 12, 0xFF2A, 0x004A, 0, + 12, 0xFF2B, 0x004B, 0, + 12, 0xFF2C, 0x004C, 0, + 12, 0xFF2D, 0x004D, 0, + 12, 0xFF2E, 0x004E, 0, + 12, 0xFF2F, 0x004F, 0, + 12, 0xFF30, 0x0050, 0, + 12, 0xFF31, 0x0051, 0, + 12, 0xFF32, 0x0052, 0, + 12, 0xFF33, 0x0053, 0, + 12, 0xFF34, 0x0054, 0, + 12, 0xFF35, 0x0055, 0, + 12, 0xFF36, 0x0056, 0, + 12, 0xFF37, 0x0057, 0, + 12, 0xFF38, 0x0058, 0, + 12, 0xFF39, 0x0059, 0, + 12, 0xFF3A, 0x005A, 0, + 12, 0xFF3B, 0x005B, 0, + 12, 0xFF3C, 0x005C, 0, + 12, 0xFF3D, 0x005D, 0, + 12, 0xFF3E, 0x005E, 0, + 12, 0xFF3F, 0x005F, 0, + 12, 0xFF40, 0x0060, 0, + 12, 0xFF41, 0x0061, 0, + 12, 0xFF42, 0x0062, 0, + 12, 0xFF43, 0x0063, 0, + 12, 0xFF44, 0x0064, 0, + 12, 0xFF45, 0x0065, 0, + 12, 0xFF46, 0x0066, 0, + 12, 0xFF47, 0x0067, 0, + 12, 0xFF48, 0x0068, 0, + 12, 0xFF49, 0x0069, 0, + 12, 0xFF4A, 0x006A, 0, + 12, 0xFF4B, 0x006B, 0, + 12, 0xFF4C, 0x006C, 0, + 12, 0xFF4D, 0x006D, 0, + 12, 0xFF4E, 0x006E, 0, + 12, 0xFF4F, 0x006F, 0, + 12, 0xFF50, 0x0070, 0, + 12, 0xFF51, 0x0071, 0, + 12, 0xFF52, 0x0072, 0, + 12, 0xFF53, 0x0073, 0, + 12, 0xFF54, 0x0074, 0, + 12, 0xFF55, 0x0075, 0, + 12, 0xFF56, 0x0076, 0, + 12, 0xFF57, 0x0077, 0, + 12, 0xFF58, 0x0078, 0, + 12, 0xFF59, 0x0079, 0, + 12, 0xFF5A, 0x007A, 0, + 12, 0xFF5B, 0x007B, 0, + 12, 0xFF5C, 0x007C, 0, + 12, 0xFF5D, 0x007D, 0, + 12, 0xFF5E, 0x007E, 0, + 12, 0xFF5F, 0x2985, 0, + 12, 0xFF60, 0x2986, 0, + 13, 0xFF61, 0x3002, 0, + 13, 0xFF62, 0x300C, 0, + 13, 0xFF63, 0x300D, 0, + 13, 0xFF64, 0x3001, 0, + 13, 0xFF65, 0x30FB, 0, + 13, 0xFF66, 0x30F2, 0, + 13, 0xFF67, 0x30A1, 0, + 13, 0xFF68, 0x30A3, 0, + 13, 0xFF69, 0x30A5, 0, + 13, 0xFF6A, 0x30A7, 0, + 13, 0xFF6B, 0x30A9, 0, + 13, 0xFF6C, 0x30E3, 0, + 13, 0xFF6D, 0x30E5, 0, + 13, 0xFF6E, 0x30E7, 0, + 13, 0xFF6F, 0x30C3, 0, + 13, 0xFF70, 0x30FC, 0, + 13, 0xFF71, 0x30A2, 0, + 13, 0xFF72, 0x30A4, 0, + 13, 0xFF73, 0x30A6, 0, + 13, 0xFF74, 0x30A8, 0, + 13, 0xFF75, 0x30AA, 0, + 13, 0xFF76, 0x30AB, 0, + 13, 0xFF77, 0x30AD, 0, + 13, 0xFF78, 0x30AF, 0, + 13, 0xFF79, 0x30B1, 0, + 13, 0xFF7A, 0x30B3, 0, + 13, 0xFF7B, 0x30B5, 0, + 13, 0xFF7C, 0x30B7, 0, + 13, 0xFF7D, 0x30B9, 0, + 13, 0xFF7E, 0x30BB, 0, + 13, 0xFF7F, 0x30BD, 0, + 13, 0xFF80, 0x30BF, 0, + 13, 0xFF81, 0x30C1, 0, + 13, 0xFF82, 0x30C4, 0, + 13, 0xFF83, 0x30C6, 0, + 13, 0xFF84, 0x30C8, 0, + 13, 0xFF85, 0x30CA, 0, + 13, 0xFF86, 0x30CB, 0, + 13, 0xFF87, 0x30CC, 0, + 13, 0xFF88, 0x30CD, 0, + 13, 0xFF89, 0x30CE, 0, + 13, 0xFF8A, 0x30CF, 0, + 13, 0xFF8B, 0x30D2, 0, + 13, 0xFF8C, 0x30D5, 0, + 13, 0xFF8D, 0x30D8, 0, + 13, 0xFF8E, 0x30DB, 0, + 13, 0xFF8F, 0x30DE, 0, + 13, 0xFF90, 0x30DF, 0, + 13, 0xFF91, 0x30E0, 0, + 13, 0xFF92, 0x30E1, 0, + 13, 0xFF93, 0x30E2, 0, + 13, 0xFF94, 0x30E4, 0, + 13, 0xFF95, 0x30E6, 0, + 13, 0xFF96, 0x30E8, 0, + 13, 0xFF97, 0x30E9, 0, + 13, 0xFF98, 0x30EA, 0, + 13, 0xFF99, 0x30EB, 0, + 13, 0xFF9A, 0x30EC, 0, + 13, 0xFF9B, 0x30ED, 0, + 13, 0xFF9C, 0x30EF, 0, + 13, 0xFF9D, 0x30F3, 0, + 13, 0xFF9E, 0x3099, 0, + 13, 0xFF9F, 0x309A, 0, + 13, 0xFFA0, 0x3164, 0, + 13, 0xFFA1, 0x3131, 0, + 13, 0xFFA2, 0x3132, 0, + 13, 0xFFA3, 0x3133, 0, + 13, 0xFFA4, 0x3134, 0, + 13, 0xFFA5, 0x3135, 0, + 13, 0xFFA6, 0x3136, 0, + 13, 0xFFA7, 0x3137, 0, + 13, 0xFFA8, 0x3138, 0, + 13, 0xFFA9, 0x3139, 0, + 13, 0xFFAA, 0x313A, 0, + 13, 0xFFAB, 0x313B, 0, + 13, 0xFFAC, 0x313C, 0, + 13, 0xFFAD, 0x313D, 0, + 13, 0xFFAE, 0x313E, 0, + 13, 0xFFAF, 0x313F, 0, + 13, 0xFFB0, 0x3140, 0, + 13, 0xFFB1, 0x3141, 0, + 13, 0xFFB2, 0x3142, 0, + 13, 0xFFB3, 0x3143, 0, + 13, 0xFFB4, 0x3144, 0, + 13, 0xFFB5, 0x3145, 0, + 13, 0xFFB6, 0x3146, 0, + 13, 0xFFB7, 0x3147, 0, + 13, 0xFFB8, 0x3148, 0, + 13, 0xFFB9, 0x3149, 0, + 13, 0xFFBA, 0x314A, 0, + 13, 0xFFBB, 0x314B, 0, + 13, 0xFFBC, 0x314C, 0, + 13, 0xFFBD, 0x314D, 0, + 13, 0xFFBE, 0x314E, 0, + 13, 0xFFC2, 0x314F, 0, + 13, 0xFFC3, 0x3150, 0, + 13, 0xFFC4, 0x3151, 0, + 13, 0xFFC5, 0x3152, 0, + 13, 0xFFC6, 0x3153, 0, + 13, 0xFFC7, 0x3154, 0, + 13, 0xFFCA, 0x3155, 0, + 13, 0xFFCB, 0x3156, 0, + 13, 0xFFCC, 0x3157, 0, + 13, 0xFFCD, 0x3158, 0, + 13, 0xFFCE, 0x3159, 0, + 13, 0xFFCF, 0x315A, 0, + 13, 0xFFD2, 0x315B, 0, + 13, 0xFFD3, 0x315C, 0, + 13, 0xFFD4, 0x315D, 0, + 13, 0xFFD5, 0x315E, 0, + 13, 0xFFD6, 0x315F, 0, + 13, 0xFFD7, 0x3160, 0, + 13, 0xFFDA, 0x3161, 0, + 13, 0xFFDB, 0x3162, 0, + 13, 0xFFDC, 0x3163, 0, + 12, 0xFFE0, 0x00A2, 0, + 12, 0xFFE1, 0x00A3, 0, + 12, 0xFFE2, 0x00AC, 0, + 12, 0xFFE3, 0x00AF, 0, + 12, 0xFFE4, 0x00A6, 0, + 12, 0xFFE5, 0x00A5, 0, + 12, 0xFFE6, 0x20A9, 0, + 13, 0xFFE8, 0x2502, 0, + 13, 0xFFE9, 0x2190, 0, + 13, 0xFFEA, 0x2191, 0, + 13, 0xFFEB, 0x2192, 0, + 13, 0xFFEC, 0x2193, 0, + 13, 0xFFED, 0x25A0, 0, + 13, 0xFFEE, 0x25CB, 0, + +}; + +static const Q_UINT16 di_00[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 10, 0, 0, 0, 0, 14, + 0, 0, 19, 23, 27, 32, 0, 0, + 36, 41, 45, 0, 49, 55, 61, 0, + 67, 72, 77, 82, 87, 92, 0, 97, + 102, 107, 112, 117, 122, 127, 132, 137, + 0, 142, 147, 152, 157, 162, 167, 0, + 0, 172, 177, 182, 187, 192, 0, 0, + 197, 202, 207, 212, 217, 222, 0, 227, + 232, 237, 242, 247, 252, 257, 262, 267, + 0, 272, 277, 282, 287, 292, 297, 0, + 0, 302, 307, 312, 317, 322, 0, 327, +}; + +static const Q_UINT16 di_01[] = { + 332, 337, 342, 347, 352, 357, 362, 367, + 372, 377, 382, 387, 392, 397, 402, 407, + 0, 0, 412, 417, 422, 427, 432, 437, + 442, 447, 452, 457, 462, 467, 472, 477, + 482, 487, 492, 497, 502, 507, 0, 0, + 512, 517, 522, 527, 532, 537, 542, 547, + 552, 0, 557, 562, 567, 572, 577, 582, + 0, 587, 592, 597, 602, 607, 612, 617, + 622, 0, 0, 627, 632, 637, 642, 647, + 652, 657, 0, 0, 662, 667, 672, 677, + 682, 687, 0, 0, 692, 697, 702, 707, + 712, 717, 722, 727, 732, 737, 742, 747, + 752, 757, 762, 767, 772, 777, 0, 0, + 782, 787, 792, 797, 802, 807, 812, 817, + 822, 827, 832, 837, 842, 847, 852, 857, + 862, 867, 872, 877, 882, 887, 892, 897, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 901, 906, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 911, + 916, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 921, 926, 931, 936, + 941, 946, 951, 956, 961, 966, 971, 976, + 981, 986, 991, 996, 1001, 1006, 1011, 1016, + 1021, 1026, 1031, 1036, 1041, 0, 1046, 1051, + 1056, 1061, 1066, 1071, 0, 0, 1076, 1081, + 1086, 1091, 1096, 1101, 1106, 1111, 1116, 1121, + 1126, 1131, 1136, 1141, 1146, 1151, 0, 0, + 1156, 1161, 1166, 1171, 1176, 1181, 1186, 1191, +}; + +static const Q_UINT16 di_02[] = { + 1196, 1201, 1206, 1211, 1216, 1221, 1226, 1231, + 1236, 1241, 1246, 1251, 1256, 1261, 1266, 1271, + 1276, 1281, 1286, 1291, 1296, 1301, 1306, 1311, + 1316, 1321, 1326, 1331, 0, 0, 1336, 1341, + 0, 0, 0, 0, 0, 0, 1346, 1351, + 1356, 1361, 1366, 1371, 1376, 1381, 1386, 1391, + 1396, 1401, 1406, 1411, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1416, 1420, 1424, 1428, 1432, 1436, 1440, 1444, + 1448, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1452, 1457, 1462, 1467, 1472, 1477, 0, 0, + 1482, 1486, 1490, 1494, 1498, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_03[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1502, 1506, 0, 1510, 1514, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1519, 0, 0, 0, + 0, 0, 1523, 0, 0, 0, 1528, 0, + 0, 0, 0, 0, 1532, 1537, 1542, 1547, + 1551, 1556, 1561, 0, 1566, 0, 1571, 1576, + 1581, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1586, 1591, 1596, 1601, 1606, 1611, + 1616, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1621, 1626, 1631, 1636, 1641, 0, + 1646, 1650, 1654, 1658, 1663, 1668, 1672, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1676, 1680, 1684, 0, 1688, 1692, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_04[] = { + 1696, 1701, 0, 1706, 0, 0, 0, 1711, + 0, 0, 0, 0, 1716, 1721, 1726, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1731, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1736, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1741, 1746, 0, 1751, 0, 0, 0, 1756, + 0, 0, 0, 0, 1761, 1766, 1771, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1776, 1781, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1786, 1791, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1796, 1801, 1806, 1811, 0, 0, 1816, 1821, + 0, 0, 1826, 1831, 1836, 1841, 1846, 1851, + 0, 0, 1856, 1861, 1866, 1871, 1876, 1881, + 0, 0, 1886, 1891, 1896, 1901, 1906, 1911, + 1916, 1921, 1926, 1931, 1936, 1941, 0, 0, + 1946, 1951, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_05[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1956, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_06[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1961, 1966, 1971, 1976, 1981, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1986, 1991, 1996, + 2001, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2006, 0, 2011, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2016, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_07[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_09[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2021, 0, 0, 0, 0, 0, 0, + 0, 2026, 0, 0, 2031, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2036, 2041, 2046, 2051, 2056, 2061, 2066, 2071, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2076, 2081, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2086, 2091, 0, 2096, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0A[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2101, 0, 0, 2106, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2111, 2116, 2121, 0, 0, 2126, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0B[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2131, 0, 0, 2136, 2141, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2146, 2151, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2156, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2161, 2166, 2171, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0C[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2176, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2181, 0, 0, 0, 0, 0, 0, 2186, + 2191, 0, 2196, 2201, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0D[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2206, 2211, 2216, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2221, 0, 2226, 2231, 2236, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2241, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2246, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2251, 2256, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_0F[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2261, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2265, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2270, 0, 0, + 0, 0, 2275, 0, 0, 0, 0, 2280, + 0, 0, 0, 0, 2285, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2290, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2295, 0, 2300, 2305, 2310, + 2315, 2320, 0, 0, 0, 0, 0, 0, + 0, 2325, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2330, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2335, 0, 0, + 0, 0, 2340, 0, 0, 0, 0, 2345, + 0, 0, 0, 0, 2350, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2355, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_10[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2360, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_1E[] = { + 2365, 2370, 2375, 2380, 2385, 2390, 2395, 2400, + 2405, 2410, 2415, 2420, 2425, 2430, 2435, 2440, + 2445, 2450, 2455, 2460, 2465, 2470, 2475, 2480, + 2485, 2490, 2495, 2500, 2505, 2510, 2515, 2520, + 2525, 2530, 2535, 2540, 2545, 2550, 2555, 2560, + 2565, 2570, 2575, 2580, 2585, 2590, 2595, 2600, + 2605, 2610, 2615, 2620, 2625, 2630, 2635, 2640, + 2645, 2650, 2655, 2660, 2665, 2670, 2675, 2680, + 2685, 2690, 2695, 2700, 2705, 2710, 2715, 2720, + 2725, 2730, 2735, 2740, 2745, 2750, 2755, 2760, + 2765, 2770, 2775, 2780, 2785, 2790, 2795, 2800, + 2805, 2810, 2815, 2820, 2825, 2830, 2835, 2840, + 2845, 2850, 2855, 2860, 2865, 2870, 2875, 2880, + 2885, 2890, 2895, 2900, 2905, 2910, 2915, 2920, + 2925, 2930, 2935, 2940, 2945, 2950, 2955, 2960, + 2965, 2970, 2975, 2980, 2985, 2990, 2995, 3000, + 3005, 3010, 3015, 3020, 3025, 3030, 3035, 3040, + 3045, 3050, 3055, 3060, 3065, 3070, 3075, 3080, + 3085, 3090, 3095, 3100, 3105, 3110, 3115, 3120, + 3125, 3130, 3135, 3140, 0, 0, 0, 0, + 3145, 3150, 3155, 3160, 3165, 3170, 3175, 3180, + 3185, 3190, 3195, 3200, 3205, 3210, 3215, 3220, + 3225, 3230, 3235, 3240, 3245, 3250, 3255, 3260, + 3265, 3270, 3275, 3280, 3285, 3290, 3295, 3300, + 3305, 3310, 3315, 3320, 3325, 3330, 3335, 3340, + 3345, 3350, 3355, 3360, 3365, 3370, 3375, 3380, + 3385, 3390, 3395, 3400, 3405, 3410, 3415, 3420, + 3425, 3430, 3435, 3440, 3445, 3450, 3455, 3460, + 3465, 3470, 3475, 3480, 3485, 3490, 3495, 3500, + 3505, 3510, 3515, 3520, 3525, 3530, 3535, 3540, + 3545, 3550, 3555, 3560, 3565, 3570, 3575, 3580, + 3585, 3590, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_1F[] = { + 3595, 3600, 3605, 3610, 3615, 3620, 3625, 3630, + 3635, 3640, 3645, 3650, 3655, 3660, 3665, 3670, + 3675, 3680, 3685, 3690, 3695, 3700, 0, 0, + 3705, 3710, 3715, 3720, 3725, 3730, 0, 0, + 3735, 3740, 3745, 3750, 3755, 3760, 3765, 3770, + 3775, 3780, 3785, 3790, 3795, 3800, 3805, 3810, + 3815, 3820, 3825, 3830, 3835, 3840, 3845, 3850, + 3855, 3860, 3865, 3870, 3875, 3880, 3885, 3890, + 3895, 3900, 3905, 3910, 3915, 3920, 0, 0, + 3925, 3930, 3935, 3940, 3945, 3950, 0, 0, + 3955, 3960, 3965, 3970, 3975, 3980, 3985, 3990, + 0, 3995, 0, 4000, 0, 4005, 0, 4010, + 4015, 4020, 4025, 4030, 4035, 4040, 4045, 4050, + 4055, 4060, 4065, 4070, 4075, 4080, 4085, 4090, + 4095, 4100, 4104, 4109, 4113, 4118, 4122, 4127, + 4131, 4136, 4140, 4145, 4149, 4154, 0, 0, + 4158, 4163, 4168, 4173, 4178, 4183, 4188, 4193, + 4198, 4203, 4208, 4213, 4218, 4223, 4228, 4233, + 4238, 4243, 4248, 4253, 4258, 4263, 4268, 4273, + 4278, 4283, 4288, 4293, 4298, 4303, 4308, 4313, + 4318, 4323, 4328, 4333, 4338, 4343, 4348, 4353, + 4358, 4363, 4368, 4373, 4378, 4383, 4388, 4393, + 4398, 4403, 4408, 4413, 4418, 0, 4423, 4428, + 4433, 4438, 4443, 4448, 4452, 4457, 4462, 4466, + 4471, 4476, 4481, 4486, 4491, 0, 4496, 4501, + 4506, 4511, 4515, 4520, 4524, 4529, 4534, 4539, + 4544, 4549, 4554, 4559, 0, 0, 4563, 4568, + 4573, 4578, 4583, 4588, 0, 4592, 4597, 4602, + 4607, 4612, 4617, 4622, 4626, 4631, 4636, 4641, + 4646, 4651, 4656, 4661, 4665, 4670, 4675, 4679, + 0, 0, 4683, 4688, 4693, 0, 4698, 4703, + 4708, 4713, 4717, 4722, 4726, 4731, 4735, 0, +}; + +static const Q_UINT16 di_20[] = { + 4740, 4744, 4748, 4752, 4756, 4760, 4764, 4768, + 4772, 4776, 4780, 0, 0, 0, 0, 0, + 0, 4784, 0, 0, 0, 0, 0, 4788, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4793, 4797, 4802, 0, + 0, 0, 0, 0, 0, 0, 0, 4808, + 0, 0, 0, 4812, 4817, 0, 4823, 4828, + 0, 0, 0, 0, 4834, 0, 4839, 0, + 0, 0, 0, 0, 0, 0, 0, 4844, + 4849, 4854, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4859, + 0, 0, 0, 0, 0, 0, 0, 4866, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4870, 4874, 0, 0, 4878, 4882, 4886, 4890, + 4894, 4898, 4902, 4906, 4910, 4914, 4918, 4922, + 4926, 4930, 4934, 4938, 4942, 4946, 4950, 4954, + 4958, 4962, 4966, 4970, 4974, 4978, 4982, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4986, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_21[] = { + 4991, 4997, 5003, 5007, 0, 5012, 5018, 5024, + 0, 5028, 5033, 5037, 5041, 5045, 5049, 5053, + 5057, 5061, 5065, 5069, 0, 5073, 5077, 0, + 0, 5082, 5086, 5090, 5094, 5098, 0, 0, + 5102, 5107, 5113, 0, 5118, 0, 5122, 0, + 5126, 0, 5130, 5134, 5138, 5142, 0, 5146, + 5150, 5154, 0, 5158, 5162, 5166, 5170, 5174, + 5178, 5182, 0, 0, 0, 5186, 5190, 5194, + 5198, 0, 0, 0, 0, 5202, 5206, 5210, + 5214, 5218, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5222, 5228, 5234, 5240, 5246, + 5252, 5258, 5264, 5270, 5276, 5282, 5288, 5294, + 5299, 5303, 5308, 5314, 5319, 5323, 5328, 5334, + 5341, 5346, 5350, 5355, 5361, 5365, 5369, 5373, + 5377, 5381, 5386, 5392, 5397, 5401, 5406, 5412, + 5419, 5424, 5428, 5433, 5439, 5443, 5447, 5451, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5455, 5460, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5465, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5470, 5475, 5480, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_22[] = { + 0, 0, 0, 0, 5485, 0, 0, 0, + 0, 5490, 0, 0, 5495, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5500, 0, 5505, 0, + 0, 0, 0, 0, 5510, 5515, 0, 5521, + 5526, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5532, 0, 0, 5537, 0, 0, 5542, + 0, 5547, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5552, 0, 5557, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5562, 5567, 5572, + 5577, 5582, 0, 0, 5587, 5592, 0, 0, + 5597, 5602, 0, 0, 0, 0, 0, 0, + 5607, 5612, 0, 0, 5617, 5622, 0, 0, + 5627, 5632, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5637, 5642, 5647, 5652, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5657, 5662, 5667, 5672, 0, 0, 0, 0, + 0, 0, 5677, 5682, 5687, 5692, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_23[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5697, 5701, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_24[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5705, 5709, 5713, 5717, 5721, 5725, 5729, 5733, + 5737, 5741, 5746, 5751, 5756, 5761, 5766, 5771, + 5776, 5781, 5786, 5791, 5796, 5802, 5808, 5814, + 5820, 5826, 5832, 5838, 5844, 5850, 5857, 5864, + 5871, 5878, 5885, 5892, 5899, 5906, 5913, 5920, + 5927, 5932, 5937, 5942, 5947, 5952, 5957, 5962, + 5967, 5972, 5978, 5984, 5990, 5996, 6002, 6008, + 6014, 6020, 6026, 6032, 6038, 6044, 6050, 6056, + 6062, 6068, 6074, 6080, 6086, 6092, 6098, 6104, + 6110, 6116, 6122, 6128, 6134, 6140, 6146, 6152, + 6158, 6164, 6170, 6176, 6182, 6188, 6194, 6198, + 6202, 6206, 6210, 6214, 6218, 6222, 6226, 6230, + 6234, 6238, 6242, 6246, 6250, 6254, 6258, 6262, + 6266, 6270, 6274, 6278, 6282, 6286, 6290, 6294, + 6298, 6302, 6306, 6310, 6314, 6318, 6322, 6326, + 6330, 6334, 6338, 6342, 6346, 6350, 6354, 6358, + 6362, 6366, 6370, 6374, 6378, 6382, 6386, 6390, + 6394, 6398, 6402, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_2A[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6406, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6413, 6419, 6424, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6430, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_2E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6435, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6439, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_2F[] = { + 6443, 6447, 6451, 6455, 6459, 6463, 6467, 6471, + 6475, 6479, 6483, 6487, 6491, 6495, 6499, 6503, + 6507, 6511, 6515, 6519, 6523, 6527, 6531, 6535, + 6539, 6543, 6547, 6551, 6555, 6559, 6563, 6567, + 6571, 6575, 6579, 6583, 6587, 6591, 6595, 6599, + 6603, 6607, 6611, 6615, 6619, 6623, 6627, 6631, + 6635, 6639, 6643, 6647, 6651, 6655, 6659, 6663, + 6667, 6671, 6675, 6679, 6683, 6687, 6691, 6695, + 6699, 6703, 6707, 6711, 6715, 6719, 6723, 6727, + 6731, 6735, 6739, 6743, 6747, 6751, 6755, 6759, + 6763, 6767, 6771, 6775, 6779, 6783, 6787, 6791, + 6795, 6799, 6803, 6807, 6811, 6815, 6819, 6823, + 6827, 6831, 6835, 6839, 6843, 6847, 6851, 6855, + 6859, 6863, 6867, 6871, 6875, 6879, 6883, 6887, + 6891, 6895, 6899, 6903, 6907, 6911, 6915, 6919, + 6923, 6927, 6931, 6935, 6939, 6943, 6947, 6951, + 6955, 6959, 6963, 6967, 6971, 6975, 6979, 6983, + 6987, 6991, 6995, 6999, 7003, 7007, 7011, 7015, + 7019, 7023, 7027, 7031, 7035, 7039, 7043, 7047, + 7051, 7055, 7059, 7063, 7067, 7071, 7075, 7079, + 7083, 7087, 7091, 7095, 7099, 7103, 7107, 7111, + 7115, 7119, 7123, 7127, 7131, 7135, 7139, 7143, + 7147, 7151, 7155, 7159, 7163, 7167, 7171, 7175, + 7179, 7183, 7187, 7191, 7195, 7199, 7203, 7207, + 7211, 7215, 7219, 7223, 7227, 7231, 7235, 7239, + 7243, 7247, 7251, 7255, 7259, 7263, 7267, 7271, + 7275, 7279, 7283, 7287, 7291, 7295, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_30[] = { + 7299, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7303, 0, + 7307, 7311, 7315, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7319, 0, 7324, 0, + 7329, 0, 7334, 0, 7339, 0, 7344, 0, + 7349, 0, 7354, 0, 7359, 0, 7364, 0, + 7369, 0, 7374, 0, 0, 7379, 0, 7384, + 0, 7389, 0, 0, 0, 0, 0, 0, + 7394, 7399, 0, 7404, 7409, 0, 7414, 7419, + 0, 7424, 7429, 0, 7434, 7439, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7444, 0, 0, 0, + 0, 0, 0, 7449, 7454, 0, 7459, 7464, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7469, 0, 7474, 0, + 7479, 0, 7484, 0, 7489, 0, 7494, 0, + 7499, 0, 7504, 0, 7509, 0, 7514, 0, + 7519, 0, 7524, 0, 0, 7529, 0, 7534, + 0, 7539, 0, 0, 0, 0, 0, 0, + 7544, 7549, 0, 7554, 7559, 0, 7564, 7569, + 0, 7574, 7579, 0, 7584, 7589, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7594, 0, 0, 7599, + 7604, 7609, 7614, 0, 0, 0, 7619, 7624, +}; + +static const Q_UINT16 di_31[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7629, 7633, 7637, 7641, 7645, 7649, 7653, + 7657, 7661, 7665, 7669, 7673, 7677, 7681, 7685, + 7689, 7693, 7697, 7701, 7705, 7709, 7713, 7717, + 7721, 7725, 7729, 7733, 7737, 7741, 7745, 7749, + 7753, 7757, 7761, 7765, 7769, 7773, 7777, 7781, + 7785, 7789, 7793, 7797, 7801, 7805, 7809, 7813, + 7817, 7821, 7825, 7829, 7833, 7837, 7841, 7845, + 7849, 7853, 7857, 7861, 7865, 7869, 7873, 7877, + 7881, 7885, 7889, 7893, 7897, 7901, 7905, 7909, + 7913, 7917, 7921, 7925, 7929, 7933, 7937, 7941, + 7945, 7949, 7953, 7957, 7961, 7965, 7969, 7973, + 7977, 7981, 7985, 7989, 7993, 7997, 8001, 0, + 0, 0, 8005, 8009, 8013, 8017, 8021, 8025, + 8029, 8033, 8037, 8041, 8045, 8049, 8053, 8057, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_32[] = { + 8061, 8067, 8073, 8079, 8085, 8091, 8097, 8103, + 8109, 8115, 8121, 8127, 8133, 8139, 8145, 8152, + 8159, 8166, 8173, 8180, 8187, 8194, 8201, 8208, + 8215, 8222, 8229, 8236, 8243, 0, 0, 0, + 8250, 8256, 8262, 8268, 8274, 8280, 8286, 8292, + 8298, 8304, 8310, 8316, 8322, 8328, 8334, 8340, + 8346, 8352, 8358, 8364, 8370, 8376, 8382, 8388, + 8394, 8400, 8406, 8412, 8418, 8424, 8430, 8436, + 8442, 8448, 8454, 8460, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8466, 8471, 8476, 8481, 8486, 8491, 8496, + 8501, 8506, 8511, 8516, 8521, 8526, 8531, 8536, + 8541, 8545, 8549, 8553, 8557, 8561, 8565, 8569, + 8573, 8577, 8581, 8585, 8589, 8593, 8597, 8602, + 8607, 8612, 8617, 8622, 8627, 8632, 8637, 8642, + 8647, 8652, 8657, 8662, 0, 0, 0, 0, + 8667, 8671, 8675, 8679, 8683, 8687, 8691, 8695, + 8699, 8703, 8707, 8711, 8715, 8719, 8723, 8727, + 8731, 8735, 8739, 8743, 8747, 8751, 8755, 8759, + 8763, 8767, 8771, 8775, 8779, 8783, 8787, 8791, + 8795, 8799, 8803, 8807, 8811, 8815, 8819, 8823, + 8827, 8831, 8835, 8839, 8843, 8847, 8851, 8855, + 8859, 8863, 8868, 8873, 8878, 8883, 8888, 8893, + 8898, 8903, 8908, 8913, 8918, 8923, 8928, 8933, + 8938, 8943, 8948, 8953, 8958, 8963, 8968, 8973, + 8978, 8983, 8989, 8995, 0, 0, 0, 0, + 9001, 9005, 9009, 9013, 9017, 9021, 9025, 9029, + 9033, 9037, 9041, 9045, 9049, 9053, 9057, 9061, + 9065, 9069, 9073, 9077, 9081, 9085, 9089, 9093, + 9097, 9101, 9105, 9109, 9113, 9117, 9121, 9125, + 9129, 9133, 9137, 9141, 9145, 9149, 9153, 9157, + 9161, 9165, 9169, 9173, 9177, 9181, 9185, 0, +}; + +static const Q_UINT16 di_33[] = { + 9189, 9196, 9203, 9210, 9216, 9223, 9229, 9235, + 9243, 9250, 9256, 9262, 9268, 9275, 9282, 9288, + 9294, 9299, 9305, 9312, 9319, 9324, 9332, 9341, + 9349, 9355, 9363, 9371, 9378, 9384, 9390, 9396, + 9403, 9411, 9418, 9424, 9430, 9436, 9441, 9446, + 9451, 9456, 9462, 9468, 9476, 9482, 9489, 9497, + 9503, 9508, 9513, 9521, 9528, 9536, 9542, 9550, + 9555, 9561, 9567, 9573, 9579, 9585, 9592, 9598, + 9603, 9609, 9615, 9621, 9628, 9634, 9640, 9646, + 9654, 9661, 9666, 9674, 9679, 9686, 9693, 9699, + 9705, 9711, 9718, 9723, 9729, 9736, 9741, 9749, + 9755, 9760, 9765, 9770, 9775, 9780, 9785, 9790, + 9795, 9800, 9805, 9811, 9817, 9823, 9829, 9835, + 9841, 9847, 9853, 9859, 9865, 9871, 9877, 9883, + 9889, 9895, 9901, 9906, 9911, 9917, 9922, 0, + 0, 0, 0, 9927, 9932, 9937, 9942, 9947, + 9954, 9959, 9964, 9969, 9974, 9979, 9984, 9989, + 9994, 10000, 10007, 10012, 10017, 10022, 10027, 10032, + 10037, 10042, 10048, 10054, 10060, 10066, 10071, 10076, + 10081, 10086, 10091, 10096, 10101, 10106, 10111, 10116, + 10122, 10128, 10133, 10139, 10145, 10151, 10156, 10162, + 10168, 10175, 10180, 10186, 10192, 10198, 10204, 10212, + 10221, 10226, 10231, 10236, 10241, 10246, 10251, 10256, + 10261, 10266, 10271, 10276, 10281, 10286, 10291, 10296, + 10301, 10306, 10311, 10318, 10323, 10328, 10333, 10340, + 10346, 10351, 10356, 10361, 10366, 10371, 10376, 10381, + 10386, 10391, 10396, 10402, 10407, 10412, 10418, 10424, + 10429, 10436, 10442, 10447, 10452, 10457, 0, 0, + 10462, 10467, 10472, 10477, 10482, 10487, 10492, 10497, + 10502, 10507, 10513, 10519, 10525, 10531, 10537, 10543, + 10549, 10555, 10561, 10567, 10573, 10579, 10585, 10591, + 10597, 10603, 10609, 10615, 10621, 10627, 10633, 0, +}; + +static const Q_UINT16 di_F9[] = { + 10639, 10643, 10647, 10651, 10655, 10659, 10663, 10667, + 10671, 10675, 10679, 10683, 10687, 10691, 10695, 10699, + 10703, 10707, 10711, 10715, 10719, 10723, 10727, 10731, + 10735, 10739, 10743, 10747, 10751, 10755, 10759, 10763, + 10767, 10771, 10775, 10779, 10783, 10787, 10791, 10795, + 10799, 10803, 10807, 10811, 10815, 10819, 10823, 10827, + 10831, 10835, 10839, 10843, 10847, 10851, 10855, 10859, + 10863, 10867, 10871, 10875, 10879, 10883, 10887, 10891, + 10895, 10899, 10903, 10907, 10911, 10915, 10919, 10923, + 10927, 10931, 10935, 10939, 10943, 10947, 10951, 10955, + 10959, 10963, 10967, 10971, 10975, 10979, 10983, 10987, + 10991, 10995, 10999, 11003, 11007, 11011, 11015, 11019, + 11023, 11027, 11031, 11035, 11039, 11043, 11047, 11051, + 11055, 11059, 11063, 11067, 11071, 11075, 11079, 11083, + 11087, 11091, 11095, 11099, 11103, 11107, 11111, 11115, + 11119, 11123, 11127, 11131, 11135, 11139, 11143, 11147, + 11151, 11155, 11159, 11163, 11167, 11171, 11175, 11179, + 11183, 11187, 11191, 11195, 11199, 11203, 11207, 11211, + 11215, 11219, 11223, 11227, 11231, 11235, 11239, 11243, + 11247, 11251, 11255, 11259, 11263, 11267, 11271, 11275, + 11279, 11283, 11287, 11291, 11295, 11299, 11303, 11307, + 11311, 11315, 11319, 11323, 11327, 11331, 11335, 11339, + 11343, 11347, 11351, 11355, 11359, 11363, 11367, 11371, + 11375, 11379, 11383, 11387, 11391, 11395, 11399, 11403, + 11407, 11411, 11415, 11419, 11423, 11427, 11431, 11435, + 11439, 11443, 11447, 11451, 11455, 11459, 11463, 11467, + 11471, 11475, 11479, 11483, 11487, 11491, 11495, 11499, + 11503, 11507, 11511, 11515, 11519, 11523, 11527, 11531, + 11535, 11539, 11543, 11547, 11551, 11555, 11559, 11563, + 11567, 11571, 11575, 11579, 11583, 11587, 11591, 11595, + 11599, 11603, 11607, 11611, 11615, 11619, 11623, 11627, + 11631, 11635, 11639, 11643, 11647, 11651, 11655, 11659, +}; + +static const Q_UINT16 di_FA[] = { + 11663, 11667, 11671, 11675, 11679, 11683, 11687, 11691, + 11695, 11699, 11703, 11707, 11711, 11715, 0, 0, + 11719, 0, 11723, 0, 0, 11727, 11731, 11735, + 11739, 11743, 11747, 11751, 11755, 11759, 11763, 0, + 11767, 0, 11771, 0, 0, 11775, 11779, 0, + 0, 0, 11783, 11787, 11791, 11795, 0, 0, + 11799, 11803, 11807, 11811, 11815, 11819, 11823, 11827, + 11831, 11835, 11839, 11843, 11847, 11851, 11855, 11859, + 11863, 11867, 11871, 11875, 11879, 11883, 11887, 11891, + 11895, 11899, 11903, 11907, 11911, 11915, 11919, 11923, + 11927, 11931, 11935, 11939, 11943, 11947, 11951, 11955, + 11959, 11963, 11967, 11971, 11975, 11979, 11983, 11987, + 11991, 11995, 11999, 12003, 12007, 12011, 12015, 12019, + 12023, 12027, 12031, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_FB[] = { + 12035, 12040, 12045, 12050, 12056, 12062, 12067, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12072, 12077, 12082, 12087, 12092, + 0, 0, 0, 0, 0, 12097, 0, 12102, + 12107, 12111, 12115, 12119, 12123, 12127, 12131, 12135, + 12139, 12143, 12147, 12152, 12157, 12162, 12167, 12172, + 12177, 12182, 12187, 12192, 12197, 12202, 12207, 0, + 12212, 12217, 12222, 12227, 12232, 0, 12237, 0, + 12242, 12247, 0, 12252, 12257, 0, 12262, 12267, + 12272, 12277, 12282, 12287, 12292, 12297, 12302, 12307, + 12312, 12316, 12320, 12324, 12328, 12332, 12336, 12340, + 12344, 12348, 12352, 12356, 12360, 12364, 12368, 12372, + 12376, 12380, 12384, 12388, 12392, 12396, 12400, 12404, + 12408, 12412, 12416, 12420, 12424, 12428, 12432, 12436, + 12440, 12444, 12448, 12452, 12456, 12460, 12464, 12468, + 12472, 12476, 12480, 12484, 12488, 12492, 12496, 12500, + 12504, 12508, 12512, 12516, 12520, 12524, 12528, 12532, + 12536, 12540, 12544, 12548, 12552, 12556, 12560, 12564, + 12568, 12572, 12576, 12580, 12584, 12588, 12592, 12596, + 12600, 12604, 12608, 12612, 12616, 12620, 12624, 12628, + 12632, 12636, 12640, 12644, 12648, 12652, 12656, 12660, + 12664, 12668, 12672, 12676, 12680, 12684, 12688, 12692, + 12696, 12700, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12704, 12708, 12712, 12716, 12720, + 12724, 12728, 12732, 12736, 12740, 12744, 12748, 12752, + 12756, 12760, 12764, 12768, 12772, 12776, 12780, 12784, + 12788, 12792, 12796, 12801, 12806, 12811, 12816, 12821, + 12826, 12831, 12836, 12841, 12846, 12851, 12856, 12861, + 12866, 12871, 12876, 12881, 12886, 12890, 12894, 12898, +}; + +static const Q_UINT16 di_FC[] = { + 12902, 12907, 12912, 12917, 12922, 12927, 12932, 12937, + 12942, 12947, 12952, 12957, 12962, 12967, 12972, 12977, + 12982, 12987, 12992, 12997, 13002, 13007, 13012, 13017, + 13022, 13027, 13032, 13037, 13042, 13047, 13052, 13057, + 13062, 13067, 13072, 13077, 13082, 13087, 13092, 13097, + 13102, 13107, 13112, 13117, 13122, 13127, 13132, 13137, + 13142, 13147, 13152, 13157, 13162, 13167, 13172, 13177, + 13182, 13187, 13192, 13197, 13202, 13207, 13212, 13217, + 13222, 13227, 13232, 13237, 13242, 13247, 13252, 13257, + 13262, 13267, 13272, 13277, 13282, 13287, 13292, 13297, + 13302, 13307, 13312, 13317, 13322, 13327, 13332, 13337, + 13342, 13347, 13352, 13357, 13362, 13367, 13372, 13378, + 13384, 13390, 13396, 13402, 13408, 13413, 13418, 13423, + 13428, 13433, 13438, 13443, 13448, 13453, 13458, 13463, + 13468, 13473, 13478, 13483, 13488, 13493, 13498, 13503, + 13508, 13513, 13518, 13523, 13528, 13533, 13538, 13543, + 13548, 13553, 13558, 13563, 13568, 13573, 13578, 13583, + 13588, 13593, 13598, 13603, 13608, 13613, 13618, 13623, + 13628, 13633, 13638, 13643, 13648, 13653, 13658, 13663, + 13668, 13673, 13678, 13683, 13688, 13693, 13698, 13703, + 13708, 13713, 13718, 13723, 13728, 13733, 13738, 13743, + 13748, 13753, 13758, 13763, 13768, 13773, 13778, 13783, + 13788, 13793, 13798, 13803, 13808, 13813, 13818, 13823, + 13828, 13833, 13838, 13843, 13848, 13853, 13858, 13863, + 13868, 13873, 13878, 13883, 13888, 13893, 13898, 13903, + 13908, 13913, 13918, 13923, 13928, 13933, 13938, 13943, + 13948, 13953, 13958, 13963, 13968, 13973, 13978, 13983, + 13988, 13993, 13998, 14003, 14008, 14013, 14018, 14023, + 14028, 14033, 14038, 14043, 14048, 14053, 14058, 14063, + 14068, 14073, 14078, 14083, 14088, 14093, 14098, 14103, + 14108, 14113, 14118, 14124, 14130, 14136, 14141, 14146, + 14151, 14156, 14161, 14166, 14171, 14176, 14181, 14186, +}; + +static const Q_UINT16 di_FD[] = { + 14191, 14196, 14201, 14206, 14211, 14216, 14221, 14226, + 14231, 14236, 14241, 14246, 14251, 14256, 14261, 14266, + 14271, 14276, 14281, 14286, 14291, 14296, 14301, 14306, + 14311, 14316, 14321, 14326, 14331, 14336, 14341, 14346, + 14351, 14356, 14361, 14366, 14371, 14376, 14381, 14386, + 14391, 14396, 14401, 14406, 14411, 14416, 14421, 14426, + 14431, 14436, 14441, 14446, 14451, 14456, 14461, 14466, + 14471, 14476, 14481, 14486, 14491, 14496, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14501, 14507, 14513, 14519, 14525, 14531, 14537, 14543, + 14549, 14555, 14561, 14567, 14573, 14579, 14585, 14591, + 14597, 14603, 14609, 14615, 14621, 14627, 14633, 14639, + 14645, 14651, 14657, 14663, 14669, 14675, 14681, 14687, + 14693, 14699, 14705, 14711, 14717, 14723, 14729, 14735, + 14741, 14747, 14753, 14759, 14765, 14771, 14777, 14783, + 14789, 14795, 14801, 14807, 14813, 14819, 14825, 14831, + 14837, 14843, 14849, 14855, 14861, 14867, 14873, 14879, + 0, 0, 14885, 14891, 14897, 14903, 14909, 14915, + 14921, 14927, 14933, 14939, 14945, 14951, 14957, 14963, + 14969, 14975, 14981, 14987, 14993, 14999, 15005, 15011, + 15017, 15023, 15029, 15035, 15041, 15047, 15053, 15059, + 15065, 15071, 15077, 15083, 15089, 15095, 15101, 15107, + 15113, 15119, 15125, 15131, 15137, 15143, 15149, 15155, + 15161, 15167, 15173, 15179, 15185, 15191, 15197, 15203, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15209, 15215, 15221, 15228, 15235, 15242, 15249, 15256, + 15263, 15270, 15276, 15297, 15308, 0, 0, 0, +}; + +static const Q_UINT16 di_FE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15315, 15319, 15323, 15327, 15331, 15335, 15339, 15343, + 15347, 15351, 15355, 15359, 15363, 15367, 15371, 15375, + 15379, 15383, 15387, 15391, 15395, 0, 0, 0, + 0, 15399, 15403, 15407, 15411, 15415, 15419, 15423, + 15427, 15431, 15435, 0, 15439, 15443, 15447, 15451, + 15455, 15459, 15463, 15467, 15471, 15475, 15479, 15483, + 15487, 15491, 15495, 15499, 15503, 15507, 15511, 0, + 15515, 15519, 15523, 15527, 0, 0, 0, 0, + 15531, 15536, 15541, 0, 15546, 0, 15551, 15556, + 15561, 15566, 15571, 15576, 15581, 15586, 15591, 15596, + 15601, 15605, 15609, 15613, 15617, 15621, 15625, 15629, + 15633, 15637, 15641, 15645, 15649, 15653, 15657, 15661, + 15665, 15669, 15673, 15677, 15681, 15685, 15689, 15693, + 15697, 15701, 15705, 15709, 15713, 15717, 15721, 15725, + 15729, 15733, 15737, 15741, 15745, 15749, 15753, 15757, + 15761, 15765, 15769, 15773, 15777, 15781, 15785, 15789, + 15793, 15797, 15801, 15805, 15809, 15813, 15817, 15821, + 15825, 15829, 15833, 15837, 15841, 15845, 15849, 15853, + 15857, 15861, 15865, 15869, 15873, 15877, 15881, 15885, + 15889, 15893, 15897, 15901, 15905, 15909, 15913, 15917, + 15921, 15925, 15929, 15933, 15937, 15941, 15945, 15949, + 15953, 15957, 15961, 15965, 15969, 15973, 15977, 15981, + 15985, 15989, 15993, 15997, 16001, 16005, 16009, 16013, + 16017, 16021, 16025, 16029, 16033, 16037, 16041, 16045, + 16049, 16053, 16057, 16061, 16065, 16069, 16074, 16079, + 16084, 16089, 16094, 16099, 16104, 0, 0, 0, +}; + +static const Q_UINT16 di_FF[] = { + 0, 16109, 16113, 16117, 16121, 16125, 16129, 16133, + 16137, 16141, 16145, 16149, 16153, 16157, 16161, 16165, + 16169, 16173, 16177, 16181, 16185, 16189, 16193, 16197, + 16201, 16205, 16209, 16213, 16217, 16221, 16225, 16229, + 16233, 16237, 16241, 16245, 16249, 16253, 16257, 16261, + 16265, 16269, 16273, 16277, 16281, 16285, 16289, 16293, + 16297, 16301, 16305, 16309, 16313, 16317, 16321, 16325, + 16329, 16333, 16337, 16341, 16345, 16349, 16353, 16357, + 16361, 16365, 16369, 16373, 16377, 16381, 16385, 16389, + 16393, 16397, 16401, 16405, 16409, 16413, 16417, 16421, + 16425, 16429, 16433, 16437, 16441, 16445, 16449, 16453, + 16457, 16461, 16465, 16469, 16473, 16477, 16481, 16485, + 16489, 16493, 16497, 16501, 16505, 16509, 16513, 16517, + 16521, 16525, 16529, 16533, 16537, 16541, 16545, 16549, + 16553, 16557, 16561, 16565, 16569, 16573, 16577, 16581, + 16585, 16589, 16593, 16597, 16601, 16605, 16609, 16613, + 16617, 16621, 16625, 16629, 16633, 16637, 16641, 16645, + 16649, 16653, 16657, 16661, 16665, 16669, 16673, 16677, + 16681, 16685, 16689, 16693, 16697, 16701, 16705, 16709, + 16713, 16717, 16721, 16725, 16729, 16733, 16737, 16741, + 16745, 16749, 16753, 16757, 16761, 16765, 16769, 16773, + 16777, 16781, 16785, 16789, 16793, 16797, 16801, 16805, + 16809, 16813, 16817, 16821, 16825, 16829, 16833, 16837, + 16841, 16845, 16849, 16853, 16857, 16861, 16865, 0, + 0, 0, 16869, 16873, 16877, 16881, 16885, 16889, + 0, 0, 16893, 16897, 16901, 16905, 16909, 16913, + 0, 0, 16917, 16921, 16925, 16929, 16933, 16937, + 0, 0, 16941, 16945, 16949, 0, 0, 0, + 16953, 16957, 16961, 16965, 16969, 16973, 16977, 0, + 16981, 16985, 16989, 16993, 16997, 17001, 17005, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 * const decomposition_info[256] = { + di_00, di_01, di_02, di_03, di_04, di_05, di_06, di_07, + di_07, di_09, di_0A, di_0B, di_0C, di_0D, di_0E, di_0F, + di_10, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_1E, di_1F, + di_20, di_21, di_22, di_23, di_24, di_07, di_07, di_07, + di_07, di_07, di_2A, di_07, di_07, di_07, di_2E, di_2F, + di_30, di_31, di_32, di_33, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_07, di_07, di_07, di_07, di_07, di_07, di_07, + di_07, di_F9, di_FA, di_FB, di_FC, di_FD, di_FE, di_FF, +}; +// 68832 bytes + +static const Q_UINT16 ligature_map[] = { + 0, + 5567, 0, + 5552, 0, + 5572, 0, + 67, 72, 77, 82, 87, 92, 332, 342, 352, 966, 1196, 1206, 1346, 2365, 3145, 3155, 0, + 2375, 2385, 2395, 0, + 97, 362, 372, 382, 392, 0, + 402, 2415, 2425, 2435, 2445, 2455, 0, + 102, 107, 112, 117, 412, 422, 432, 442, 452, 1216, 1226, 1356, 2485, 2495, 3265, 3275, 3285, 0, + 2515, 0, + 462, 472, 482, 492, 1076, 1146, 2525, 0, + 502, 1336, 2535, 2545, 2555, 2565, 2575, 0, + 122, 127, 132, 137, 512, 522, 532, 542, 552, 976, 1236, 1246, 2585, 3345, 3355, 0, + 567, 0, + 577, 1086, 2605, 2615, 2625, 0, + 587, 597, 607, 2635, 2655, 2665, 0, + 2675, 2685, 2695, 0, + 142, 627, 637, 647, 1156, 2705, 2715, 2725, 2735, 0, + 147, 152, 157, 162, 167, 662, 672, 682, 901, 986, 1096, 1256, 1266, 1386, 3365, 3375, 0, + 2785, 2795, 0, + 692, 702, 712, 1276, 1286, 2805, 2815, 2835, 0, + 722, 732, 742, 752, 1316, 2845, 2855, 0, + 762, 772, 1326, 2895, 2905, 2915, 2925, 0, + 172, 177, 182, 187, 782, 792, 802, 812, 822, 832, 911, 996, 1296, 1306, 2935, 2945, 2955, 3485, 3495, 0, + 2985, 2995, 0, + 842, 3005, 3015, 3025, 3035, 3045, 0, + 3055, 3065, 0, + 192, 852, 862, 1406, 3075, 3555, 3565, 3575, 3585, 0, + 867, 877, 887, 3085, 3095, 3105, 0, + 197, 202, 207, 212, 217, 222, 337, 347, 357, 971, 1201, 1211, 1351, 2370, 3150, 3160, 0, + 2380, 2390, 2400, 0, + 227, 367, 377, 387, 397, 0, + 407, 2420, 2430, 2440, 2450, 2460, 0, + 232, 237, 242, 247, 417, 427, 437, 447, 457, 1221, 1231, 1361, 2490, 2500, 3270, 3280, 3290, 0, + 2520, 0, + 467, 477, 487, 497, 1081, 1151, 2530, 0, + 507, 1341, 2540, 2550, 2560, 2570, 2580, 3115, 0, + 252, 257, 262, 267, 517, 527, 537, 547, 981, 1241, 1251, 2590, 3350, 3360, 0, + 572, 1126, 0, + 582, 1091, 2610, 2620, 2630, 0, + 592, 602, 612, 2640, 2660, 2670, 0, + 2680, 2690, 2700, 0, + 272, 632, 642, 652, 1161, 2710, 2720, 2730, 2740, 0, + 277, 282, 287, 292, 297, 667, 677, 687, 906, 991, 1101, 1261, 1271, 1391, 3370, 3380, 0, + 2790, 2800, 0, + 697, 707, 717, 1281, 1291, 2810, 2820, 2840, 0, + 727, 737, 747, 757, 1321, 2850, 2860, 0, + 767, 777, 1331, 2900, 2910, 2920, 2930, 3120, 0, + 302, 307, 312, 317, 787, 797, 807, 817, 827, 837, 916, 1001, 1301, 1311, 2940, 2950, 2960, 3490, 3500, 0, + 2990, 3000, 0, + 847, 3010, 3020, 3030, 3040, 3050, 3125, 0, + 3060, 3070, 0, + 322, 327, 857, 1411, 3080, 3130, 3560, 3570, 3580, 3590, 0, + 872, 882, 892, 3090, 3100, 3110, 0, + 1537, 4476, 4670, 0, + 3165, 3175, 3185, 3195, 0, + 1046, 0, + 1166, 0, + 1066, 1176, 0, + 2405, 0, + 3295, 3305, 3315, 3325, 0, + 2595, 0, + 3385, 3395, 3405, 3415, 0, + 1376, 2745, 2755, 0, + 1366, 0, + 1186, 0, + 1006, 1016, 1026, 1036, 0, + 3170, 3180, 3190, 3200, 0, + 1051, 0, + 1171, 0, + 1071, 1181, 0, + 2410, 0, + 3300, 3310, 3320, 3330, 0, + 2600, 0, + 3390, 3400, 3410, 3420, 0, + 1381, 2750, 2760, 0, + 1371, 0, + 1191, 0, + 1011, 1021, 1031, 1041, 0, + 3215, 3225, 3235, 3245, 0, + 3220, 3230, 3240, 3250, 0, + 2465, 2475, 0, + 2470, 2480, 0, + 2765, 2775, 0, + 2770, 2780, 0, + 2865, 0, + 2870, 0, + 2875, 0, + 2880, 0, + 2965, 0, + 2970, 0, + 2975, 0, + 2980, 0, + 3140, 0, + 3435, 3445, 3455, 3465, 3475, 0, + 3440, 3450, 3460, 3470, 3480, 0, + 3505, 3515, 3525, 3535, 3545, 0, + 3510, 3520, 3530, 3540, 3550, 0, + 1116, 0, + 1106, 0, + 1111, 0, + 1056, 0, + 1061, 0, + 2505, 0, + 2510, 0, + 1396, 0, + 1401, 0, + 1121, 0, + 1514, 0, + 1542, 3635, 3640, 4433, 4438, 4443, 4452, 0, + 1551, 3705, 3710, 4506, 0, + 1556, 3775, 3780, 4515, 4524, 0, + 1561, 1586, 3855, 3860, 4573, 4578, 4583, 0, + 1566, 3925, 3930, 4708, 0, + 4665, 0, + 1571, 1591, 3995, 4646, 4651, 4656, 0, + 1576, 4055, 4060, 4717, 4726, 0, + 4418, 0, + 4491, 0, + 1596, 3595, 3600, 4095, 4398, 4403, 4413, 4423, 0, + 1601, 3675, 3680, 4104, 0, + 1606, 3735, 3740, 4113, 4486, 4496, 0, + 1611, 1621, 3815, 3820, 4122, 4544, 4549, 4563, 0, + 1631, 3895, 3900, 4131, 0, + 4626, 4631, 0, + 1626, 1636, 3955, 3960, 4140, 4607, 4612, 4636, 0, + 1641, 4015, 4020, 4149, 4688, 4698, 0, + 1581, 4554, 4568, 0, + 1616, 4617, 4641, 0, + 4693, 0, + 1658, 1663, 0, + 1711, 0, + 1796, 1806, 0, + 1706, 0, + 1696, 1701, 1816, 0, + 1786, 1836, 0, + 1846, 0, + 1721, 1731, 1856, 1866, 0, + 1716, 0, + 1876, 0, + 1726, 1906, 1916, 1926, 0, + 1936, 0, + 1946, 0, + 1896, 0, + 1801, 1811, 0, + 1751, 0, + 1741, 1746, 1821, 0, + 1791, 1841, 0, + 1851, 0, + 1736, 1766, 1861, 1871, 0, + 1761, 0, + 1881, 0, + 1771, 1911, 1921, 1931, 0, + 1941, 0, + 1951, 0, + 1901, 0, + 1756, 0, + 1776, 0, + 1781, 0, + 1826, 0, + 1831, 0, + 1886, 0, + 1891, 0, + 12167, 12172, 12177, 0, + 12182, 12292, 0, + 12187, 0, + 12192, 0, + 12197, 0, + 12202, 12287, 0, + 12207, 0, + 12212, 0, + 12097, 12217, 0, + 12222, 0, + 12227, 12297, 0, + 12232, 0, + 12237, 0, + 12242, 0, + 12247, 0, + 12252, 0, + 12257, 12302, 0, + 12262, 0, + 12267, 0, + 12272, 0, + 12147, 12152, 12277, 0, + 12282, 0, + 12102, 0, + 1961, 1966, 1976, 0, + 1971, 0, + 1981, 0, + 2011, 0, + 2016, 0, + 2006, 0, + 2036, 0, + 2041, 0, + 2046, 0, + 2051, 0, + 2056, 0, + 2061, 0, + 2021, 0, + 2066, 0, + 2071, 0, + 2026, 0, + 2031, 0, + 2086, 0, + 2091, 0, + 2096, 0, + 2076, 2081, 0, + 2111, 0, + 2116, 0, + 2121, 0, + 2126, 0, + 2101, 0, + 2106, 0, + 2146, 0, + 2151, 0, + 2131, 2136, 2141, 0, + 2156, 0, + 2161, 2171, 0, + 2166, 0, + 2176, 0, + 2181, 0, + 2186, 2191, 2196, 0, + 2201, 0, + 2206, 2216, 0, + 2211, 0, + 2221, 2226, 2236, 0, + 2231, 0, + 2290, 0, + 2265, 0, + 2270, 0, + 2275, 0, + 2280, 0, + 2285, 0, + 2295, 2300, 2325, 0, + 2355, 0, + 2330, 0, + 2335, 0, + 2340, 0, + 2345, 0, + 2350, 0, + 2305, 0, + 2315, 0, + 2360, 0, + 2645, 0, + 2650, 0, + 2825, 0, + 2830, 0, + 2885, 0, + 2890, 0, + 3205, 3255, 0, + 3210, 3260, 0, + 3335, 0, + 3340, 0, + 3425, 0, + 3430, 0, + 3605, 3615, 3625, 4158, 0, + 3610, 3620, 3630, 4163, 0, + 4168, 0, + 4173, 0, + 4178, 0, + 4183, 0, + 4188, 0, + 4193, 0, + 3645, 3655, 3665, 4198, 0, + 3650, 3660, 3670, 4203, 0, + 4208, 0, + 4213, 0, + 4218, 0, + 4223, 0, + 4228, 0, + 4233, 0, + 3685, 3695, 0, + 3690, 3700, 0, + 3715, 3725, 0, + 3720, 3730, 0, + 3745, 3755, 3765, 4238, 0, + 3750, 3760, 3770, 4243, 0, + 4248, 0, + 4253, 0, + 4258, 0, + 4263, 0, + 4268, 0, + 4273, 0, + 3785, 3795, 3805, 4278, 0, + 3790, 3800, 3810, 4283, 0, + 4288, 0, + 4293, 0, + 4298, 0, + 4303, 0, + 4308, 0, + 4313, 0, + 3825, 3835, 3845, 0, + 3830, 3840, 3850, 0, + 3865, 3875, 3885, 0, + 3870, 3880, 3890, 0, + 3905, 3915, 0, + 3910, 3920, 0, + 3935, 3945, 0, + 3940, 3950, 0, + 3965, 3975, 3985, 0, + 3970, 3980, 3990, 0, + 4000, 4005, 4010, 0, + 4025, 4035, 4045, 4318, 0, + 4030, 4040, 4050, 4323, 0, + 4328, 0, + 4333, 0, + 4338, 0, + 4343, 0, + 4348, 0, + 4353, 0, + 4065, 4075, 4085, 4358, 0, + 4070, 4080, 4090, 4363, 0, + 4368, 0, + 4373, 0, + 4378, 0, + 4383, 0, + 4388, 0, + 4393, 0, + 4408, 0, + 4481, 0, + 4683, 0, + 4428, 0, + 4529, 4534, 4539, 0, + 4501, 0, + 4703, 0, + 4592, 4597, 4602, 0, + 5455, 0, + 5460, 0, + 5465, 0, + 5470, 0, + 5480, 0, + 5475, 0, + 5485, 0, + 5490, 0, + 5495, 0, + 5500, 0, + 5505, 0, + 5532, 0, + 5537, 0, + 5542, 0, + 5547, 0, + 5562, 0, + 5557, 0, + 5577, 0, + 5582, 0, + 5587, 0, + 5592, 0, + 5597, 0, + 5602, 0, + 5607, 0, + 5612, 0, + 5657, 0, + 5662, 0, + 5617, 0, + 5622, 0, + 5627, 0, + 5632, 0, + 5667, 0, + 5672, 0, + 5637, 0, + 5642, 0, + 5647, 0, + 5652, 0, + 5677, 0, + 5682, 0, + 5687, 0, + 5692, 0, + 6430, 0, + 7444, 0, + 7319, 0, + 7324, 0, + 7329, 0, + 7334, 0, + 7339, 0, + 7344, 0, + 7349, 0, + 7354, 0, + 7359, 0, + 7364, 0, + 7369, 0, + 7374, 0, + 7379, 0, + 7384, 0, + 7389, 0, + 7394, 7399, 0, + 7404, 7409, 0, + 7414, 7419, 0, + 7424, 7429, 0, + 7434, 7439, 0, + 7459, 0, + 7594, 0, + 7469, 0, + 7474, 0, + 7479, 0, + 7484, 0, + 7489, 0, + 7494, 0, + 7499, 0, + 7504, 0, + 7509, 0, + 7514, 0, + 7519, 0, + 7524, 0, + 7529, 0, + 7534, 0, + 7539, 0, + 7544, 7549, 0, + 7554, 7559, 0, + 7564, 7569, 0, + 7574, 7579, 0, + 7584, 7589, 0, + 7599, 0, + 7604, 0, + 7609, 0, + 7614, 0, + 7619, 0, + 12157, 12162, 0, + +}; + +static const Q_UINT16 li_00[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 3, 5, 0, + 0, 7, 24, 28, 34, 41, 59, 61, + 69, 77, 93, 95, 101, 108, 112, 122, + 139, 0, 142, 151, 159, 167, 187, 190, + 197, 200, 210, 0, 0, 0, 0, 0, + 0, 217, 234, 238, 244, 251, 269, 271, + 279, 288, 303, 306, 312, 319, 323, 333, + 350, 0, 353, 362, 370, 379, 399, 402, + 410, 413, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 431, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 435, 0, 440, 442, 444, 447, + 0, 0, 449, 0, 0, 0, 0, 454, + 0, 0, 0, 0, 456, 461, 465, 0, + 467, 0, 0, 0, 469, 0, 0, 0, + 0, 0, 474, 0, 479, 481, 483, 486, + 0, 0, 488, 0, 0, 0, 0, 493, + 0, 0, 0, 0, 495, 500, 504, 0, + 506, 0, 0, 0, 508, 0, 0, 0, +}; + +static const Q_UINT16 li_01[] = { + 0, 0, 513, 518, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 523, 526, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 529, 532, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 535, 537, 0, 0, 0, 0, + 539, 541, 0, 0, 0, 0, 0, 0, + 543, 545, 547, 549, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 553, 559, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 565, + 571, 0, 0, 0, 0, 0, 0, 577, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 579, 581, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_02[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 583, 585, + 587, 589, 0, 0, 0, 0, 591, 593, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 595, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_03[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 597, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 599, 0, 0, 0, 607, 0, 612, + 0, 618, 0, 0, 0, 0, 0, 626, + 0, 631, 0, 0, 0, 633, 0, 0, + 0, 640, 0, 0, 646, 0, 648, 0, + 0, 650, 0, 0, 0, 659, 0, 664, + 0, 671, 0, 0, 0, 0, 0, 680, + 0, 685, 0, 0, 0, 688, 0, 0, + 0, 697, 704, 708, 0, 0, 712, 0, + 0, 0, 714, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_04[] = { + 0, 0, 0, 0, 0, 0, 717, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 719, 0, 0, 722, 0, 724, 728, 731, + 733, 0, 738, 0, 0, 0, 740, 0, + 0, 0, 0, 742, 0, 0, 0, 747, + 0, 0, 0, 749, 0, 751, 0, 0, + 753, 0, 0, 756, 0, 758, 762, 765, + 767, 0, 772, 0, 0, 0, 774, 0, + 0, 0, 0, 776, 0, 0, 0, 781, + 0, 0, 0, 783, 0, 785, 0, 0, + 0, 0, 0, 0, 0, 0, 787, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 789, 791, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 793, 795, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 797, 799, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_05[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 801, 805, 808, 810, 812, 814, 817, 0, + 819, 821, 824, 826, 829, 0, 831, 0, + 833, 835, 0, 837, 839, 0, 842, 844, + 846, 848, 852, 0, 0, 0, 0, 0, + 0, 0, 854, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_06[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 856, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 860, 0, 862, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 866, 0, 0, 868, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_07[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_09[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 870, 872, 874, + 0, 0, 0, 0, 876, 0, 0, 0, + 0, 878, 880, 0, 0, 0, 0, 0, + 882, 0, 0, 884, 0, 0, 0, 886, + 888, 0, 0, 890, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 892, 894, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 896, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 898, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_0A[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 901, 903, + 0, 0, 0, 0, 905, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 907, 0, 0, 0, 0, + 0, 0, 909, 0, 0, 0, 0, 0, + 911, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_0B[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 915, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 917, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 921, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 923, 926, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_0C[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 928, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 930, + 0, 0, 0, 0, 0, 0, 932, 0, + 0, 0, 936, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_0D[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 938, 941, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 943, 0, 0, 947, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_0F[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 949, 0, 951, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 953, 0, 0, 0, + 0, 955, 0, 0, 0, 0, 957, 0, + 0, 0, 0, 959, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 961, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 965, 0, 967, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 969, 0, 0, 0, + 0, 971, 0, 0, 0, 0, 973, 0, + 0, 0, 0, 975, 0, 0, 0, 0, + 0, 0, 977, 979, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_10[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 981, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_1E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 983, 985, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 987, 989, 0, 0, 0, 0, + 0, 0, 991, 993, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 995, 998, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1001, 1003, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1005, 1007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_1F[] = { + 1009, 1014, 1019, 1021, 1023, 1025, 1027, 1029, + 1031, 1036, 1041, 1043, 1045, 1047, 1049, 1051, + 1053, 1056, 0, 0, 0, 0, 0, 0, + 1059, 1062, 0, 0, 0, 0, 0, 0, + 1065, 1070, 1075, 1077, 1079, 1081, 1083, 1085, + 1087, 1092, 1097, 1099, 1101, 1103, 1105, 1107, + 1109, 1113, 0, 0, 0, 0, 0, 0, + 1117, 1121, 0, 0, 0, 0, 0, 0, + 1125, 1128, 0, 0, 0, 0, 0, 0, + 1131, 1134, 0, 0, 0, 0, 0, 0, + 1137, 1141, 0, 0, 0, 0, 0, 0, + 0, 1145, 0, 0, 0, 0, 0, 0, + 1149, 1154, 1159, 1161, 1163, 1165, 1167, 1169, + 1171, 1176, 1181, 1183, 1185, 1187, 1189, 1191, + 1193, 0, 0, 0, 1195, 0, 0, 0, + 0, 0, 0, 0, 1197, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1199, 0, + 0, 0, 0, 0, 0, 0, 0, 1201, + 0, 0, 0, 0, 0, 0, 1205, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1207, 0, + 0, 0, 0, 0, 0, 0, 1209, 0, +}; + +static const Q_UINT16 li_21[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1213, 0, 1215, 0, 1217, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1219, 0, 1221, 0, 1223, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_22[] = { + 0, 0, 0, 1225, 0, 0, 0, 0, + 1227, 0, 0, 1229, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1231, 0, 1233, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1235, 0, 0, 0, + 0, 0, 0, 1237, 0, 1239, 0, 0, + 1241, 0, 0, 0, 0, 1243, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1245, 0, 0, 1247, 1249, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1251, 1253, 0, 0, 1255, 1257, + 0, 0, 1259, 1261, 1263, 1265, 0, 0, + 0, 0, 1267, 1269, 0, 0, 1271, 1273, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1275, 1277, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1279, 0, 0, 0, 0, 0, + 1281, 1283, 0, 1285, 0, 0, 0, 0, + 0, 0, 1287, 1289, 1291, 1293, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_2A[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1295, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 li_30[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1297, 0, + 0, 0, 0, 1299, 0, 1301, 0, 1303, + 0, 1305, 0, 1307, 0, 1309, 0, 1311, + 0, 1313, 0, 1315, 0, 1317, 0, 1319, + 0, 1321, 0, 0, 1323, 0, 1325, 0, + 1327, 0, 0, 0, 0, 0, 0, 1329, + 0, 0, 1332, 0, 0, 1335, 0, 0, + 1338, 0, 0, 1341, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1344, 0, 0, + 0, 0, 0, 0, 0, 0, 1346, 0, + 0, 0, 0, 1348, 0, 1350, 0, 1352, + 0, 1354, 0, 1356, 0, 1358, 0, 1360, + 0, 1362, 0, 1364, 0, 1366, 0, 1368, + 0, 1370, 0, 0, 1372, 0, 1374, 0, + 1376, 0, 0, 0, 0, 0, 0, 1378, + 0, 0, 1381, 0, 0, 1384, 0, 0, + 1387, 0, 0, 1390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1393, + 1395, 1397, 1399, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1401, 0, 0, +}; + +static const Q_UINT16 li_FB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1403, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 * const ligature_info[256] = { + li_00, li_01, li_02, li_03, li_04, li_05, li_06, li_07, + li_07, li_09, li_0A, li_0B, li_0C, li_0D, li_07, li_0F, + li_10, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_1E, li_1F, + li_07, li_21, li_22, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_2A, li_07, li_07, li_07, li_07, li_07, + li_30, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_07, li_07, li_07, li_07, li_07, + li_07, li_07, li_07, li_FB, li_07, li_07, li_07, li_07, +}; +// 15098 bytes + +static const Q_UINT8 dir_00[] = { + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 8, 7, 8, 9, 7, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 7, 7, 7, 8, + 9, 10, 10, 4, 4, 4, 10, 10, + 138, 138, 10, 4, 6, 4, 6, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 10, 138, 10, 138, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 18, + 18, 18, 18, 18, 18, 7, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 6, 10, 4, 4, 4, 4, 10, 10, + 10, 10, 0, 138, 10, 10, 10, 10, + 4, 4, 2, 2, 10, 0, 10, 10, + 10, 2, 0, 138, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_01[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_02[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_03[] = { + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 10, 10, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_04[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17, 17, 17, 17, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_05[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 1, 17, + 1, 17, 17, 1, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_06[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 13, + 0, 13, 77, 77, 77, 77, 45, 77, + 45, 77, 45, 45, 45, 45, 45, 77, + 77, 77, 77, 45, 45, 45, 45, 45, + 45, 45, 45, 0, 0, 0, 0, 0, + 109, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 45, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 4, 5, 5, 13, 45, 45, + 17, 77, 77, 77, 13, 77, 77, 77, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 45, 77, 45, 77, + 45, 45, 77, 77, 13, 77, 17, 17, + 17, 17, 17, 17, 17, 13, 17, 17, + 17, 17, 17, 17, 17, 13, 13, 17, + 17, 10, 17, 17, 17, 17, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 45, 45, 45, 13, 13, 0, +}; + +static const Q_UINT8 dir_07[] = { + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 18, + 77, 17, 45, 45, 45, 77, 77, 77, + 77, 77, 45, 45, 45, 45, 77, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 77, 45, 77, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_09[] = { + 0, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 17, 0, 0, + 0, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0A[] = { + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 0, 0, 0, 0, 17, + 17, 0, 0, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 0, 17, + 17, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0B[] = { + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 17, + 0, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0C[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, + 17, 0, 0, 0, 0, 0, 17, 17, + 17, 0, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0D[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 17, 17, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_0F[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 17, + 0, 17, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 0, + 17, 17, 17, 17, 17, 0, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_10[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 17, 17, + 17, 0, 17, 0, 0, 0, 17, 17, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_16[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_17[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_18[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 17, 17, 17, 18, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_1F[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 10, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 0, +}; + +static const Q_UINT8 dir_20[] = { + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 18, 18, 114, 0, 1, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 9, 7, 11, 14, 16, 12, 15, 9, + 4, 4, 4, 4, 4, 10, 10, 10, + 10, 138, 138, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 138, 138, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 9, + 18, 18, 18, 18, 0, 0, 0, 0, + 0, 0, 18, 18, 18, 18, 18, 18, + 2, 0, 0, 0, 2, 2, 2, 2, + 2, 2, 4, 4, 10, 138, 138, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 10, 138, 138, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_21[] = { + 10, 10, 0, 10, 10, 10, 10, 0, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, 10, 10, + 10, 0, 0, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 0, 10, 0, 10, + 0, 10, 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 138, 10, 10, 10, 10, 0, 0, 0, + 0, 0, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const Q_UINT8 dir_22[] = { + 10, 138, 138, 138, 138, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 138, 4, 4, 10, 138, 138, 10, + 10, 10, 138, 138, 138, 138, 10, 138, + 138, 138, 138, 10, 138, 10, 138, 10, + 10, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 138, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 10, 10, + 10, 10, 138, 138, 138, 138, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 138, + 138, 10, 138, 10, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 10, 138, + 138, 138, 138, 10, 10, 10, 10, 10, + 138, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 10, 10, 10, 10, 10, 138, 138, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 138, 138, 138, 138, 138, 10, 10, + 138, 138, 10, 10, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 10, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, +}; + +static const Q_UINT8 dir_23[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 10, 10, 10, 10, 10, 10, + 10, 138, 138, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_24[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, +}; + +static const Q_UINT8 dir_25[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const Q_UINT8 dir_26[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_27[] = { + 0, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 0, 10, + 10, 10, 10, 0, 0, 0, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const Q_UINT8 dir_29[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 138, 10, 10, 10, 10, 138, 138, + 138, 138, 138, 10, 138, 138, 10, 10, + 138, 138, 138, 138, 138, 10, 10, 10, + 10, 138, 10, 138, 138, 138, 10, 10, + 138, 138, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 138, 138, 138, 138, + 138, 138, 10, 10, 138, 138, 10, 10, +}; + +static const Q_UINT8 dir_2A[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 138, 138, + 138, 138, 10, 10, 138, 10, 138, 10, + 10, 138, 10, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 10, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 138, + 138, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 138, 138, 10, 10, + 10, 10, 138, 138, 138, 138, 10, 138, + 138, 10, 10, 138, 138, 10, 10, 10, + 10, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 10, 138, 10, + 10, 10, 138, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 10, 138, 10, 10, 10, 138, + 138, 138, 138, 138, 10, 138, 10, 10, +}; + +static const Q_UINT8 dir_2E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_2F[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_30[] = { + 9, 10, 10, 10, 10, 0, 0, 0, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 10, 10, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 17, 17, 17, + 10, 0, 0, 0, 0, 0, 10, 10, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 10, 10, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_32[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_A4[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_FB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 17, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, +}; + +static const Q_UINT8 dir_FC[] = { + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, +}; + +static const Q_UINT8 dir_FD[] = { + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 0, +}; + +static const Q_UINT8 dir_FE[] = { + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 6, 10, 6, 0, 10, 6, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 4, + 10, 10, 4, 4, 10, 10, 10, 0, + 10, 4, 4, 10, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 0, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 18, +}; + +static const Q_UINT8 dir_FF[] = { + 0, 10, 10, 4, 4, 4, 10, 10, + 138, 138, 10, 4, 6, 4, 6, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 10, 138, 10, 138, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 138, + 138, 10, 138, 138, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 10, 10, 10, 4, 4, 0, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 10, 10, 0, 0, +}; + +static const Q_UINT8 * const direction_info[256] = { + dir_00, dir_01, dir_02, dir_03, dir_04, dir_05, dir_06, dir_07, + dir_01, dir_09, dir_0A, dir_0B, dir_0C, dir_0D, dir_0E, dir_0F, + dir_10, dir_01, dir_01, dir_01, dir_01, dir_01, dir_16, dir_17, + dir_18, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_1F, + dir_20, dir_21, dir_22, dir_23, dir_24, dir_25, dir_26, dir_27, + dir_25, dir_29, dir_2A, dir_01, dir_01, dir_01, dir_2E, dir_2F, + dir_30, dir_01, dir_32, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_A4, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, dir_01, + dir_01, dir_01, dir_01, dir_FB, dir_FC, dir_FD, dir_FE, dir_FF, +}; +// 26362 bytes + +static const Q_UINT8 cmb_00[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_03[] = { + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 232, 220, 220, + 220, 220, 232, 216, 220, 220, 220, 220, + 220, 202, 202, 220, 220, 220, 220, 202, + 202, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 1, 1, 1, 1, + 1, 220, 220, 220, 220, 230, 230, 230, + 230, 230, 230, 230, 230, 240, 230, 220, + 220, 220, 230, 230, 230, 220, 220, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 234, 234, 233, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_04[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 230, 230, 230, 230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_05[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 220, 230, 230, 230, 230, 220, 230, + 230, 230, 222, 220, 230, 230, 230, 230, + 230, 230, 0, 220, 220, 220, 220, 220, + 230, 230, 220, 230, 230, 222, 228, 230, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 0, 20, 21, 22, 0, 23, + 0, 24, 25, 0, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_06[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 27, 28, 29, 30, 31, + 32, 33, 34, 230, 230, 220, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 230, 230, + 230, 230, 230, 230, 230, 0, 0, 230, + 230, 230, 230, 220, 230, 0, 0, 230, + 230, 0, 220, 230, 230, 220, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_07[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 220, 230, 230, 220, 230, 230, 220, + 220, 220, 230, 220, 220, 230, 220, 230, + 230, 230, 220, 230, 220, 230, 220, 230, + 220, 230, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_09[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 230, 220, 230, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0A[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0B[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0C[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 84, 91, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0D[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0E[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 103, 103, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 118, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 122, 122, 122, 122, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_0F[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 220, 220, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 220, 0, 220, + 0, 216, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 129, 130, 0, 132, 0, 0, 0, + 0, 0, 130, 130, 130, 130, 0, 0, + 130, 0, 230, 230, 9, 0, 230, 230, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 220, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_10[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, + 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_17[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_18[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 228, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_20[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 230, 1, 1, 230, 230, 230, 230, + 1, 1, 1, 230, 230, 0, 0, 0, + 0, 230, 0, 0, 0, 1, 1, 230, + 220, 230, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_30[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 218, 228, 232, 222, 224, 224, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_FB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 cmb_FE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 230, 230, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 * const combining_info[256] = { + cmb_00, cmb_00, cmb_00, cmb_03, cmb_04, cmb_05, cmb_06, cmb_07, + cmb_00, cmb_09, cmb_0A, cmb_0B, cmb_0C, cmb_0D, cmb_0E, cmb_0F, + cmb_10, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_17, + cmb_18, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_20, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_30, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, cmb_00, + cmb_00, cmb_00, cmb_00, cmb_FB, cmb_00, cmb_00, cmb_FE, cmb_00, +}; +// 32506 bytes + +static const Q_UINT16 case_00[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0, + 0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x39c, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x178, +}; + +static const Q_UINT16 case_01[] = { + 0x101, 0x100, 0x103, 0x102, 0x105, 0x104, 0x107, 0x106, + 0x109, 0x108, 0x10b, 0x10a, 0x10d, 0x10c, 0x10f, 0x10e, + 0x111, 0x110, 0x113, 0x112, 0x115, 0x114, 0x117, 0x116, + 0x119, 0x118, 0x11b, 0x11a, 0x11d, 0x11c, 0x11f, 0x11e, + 0x121, 0x120, 0x123, 0x122, 0x125, 0x124, 0x127, 0x126, + 0x129, 0x128, 0x12b, 0x12a, 0x12d, 0x12c, 0x12f, 0x12e, + 0x69, 0x49, 0x133, 0x132, 0x135, 0x134, 0x137, 0x136, + 0, 0x13a, 0x139, 0x13c, 0x13b, 0x13e, 0x13d, 0x140, + 0x13f, 0x142, 0x141, 0x144, 0x143, 0x146, 0x145, 0x148, + 0x147, 0, 0x14b, 0x14a, 0x14d, 0x14c, 0x14f, 0x14e, + 0x151, 0x150, 0x153, 0x152, 0x155, 0x154, 0x157, 0x156, + 0x159, 0x158, 0x15b, 0x15a, 0x15d, 0x15c, 0x15f, 0x15e, + 0x161, 0x160, 0x163, 0x162, 0x165, 0x164, 0x167, 0x166, + 0x169, 0x168, 0x16b, 0x16a, 0x16d, 0x16c, 0x16f, 0x16e, + 0x171, 0x170, 0x173, 0x172, 0x175, 0x174, 0x177, 0x176, + 0xff, 0x17a, 0x179, 0x17c, 0x17b, 0x17e, 0x17d, 0x53, + 0, 0x253, 0x183, 0x182, 0x185, 0x184, 0x254, 0x188, + 0x187, 0x256, 0x257, 0x18c, 0x18b, 0, 0x1dd, 0x259, + 0x25b, 0x192, 0x191, 0x260, 0x263, 0x1f6, 0x269, 0x268, + 0x199, 0x198, 0, 0, 0x26f, 0x272, 0x220, 0x275, + 0x1a1, 0x1a0, 0x1a3, 0x1a2, 0x1a5, 0x1a4, 0x280, 0x1a8, + 0x1a7, 0x283, 0, 0, 0x1ad, 0x1ac, 0x288, 0x1b0, + 0x1af, 0x28a, 0x28b, 0x1b4, 0x1b3, 0x1b6, 0x1b5, 0x292, + 0x1b9, 0x1b8, 0, 0, 0x1bd, 0x1bc, 0, 0x1f7, + 0, 0, 0, 0, 0x1c6, 0x1c4, 0x1c4, 0x1c9, + 0x1c7, 0x1c7, 0x1cc, 0x1ca, 0x1ca, 0x1ce, 0x1cd, 0x1d0, + 0x1cf, 0x1d2, 0x1d1, 0x1d4, 0x1d3, 0x1d6, 0x1d5, 0x1d8, + 0x1d7, 0x1da, 0x1d9, 0x1dc, 0x1db, 0x18e, 0x1df, 0x1de, + 0x1e1, 0x1e0, 0x1e3, 0x1e2, 0x1e5, 0x1e4, 0x1e7, 0x1e6, + 0x1e9, 0x1e8, 0x1eb, 0x1ea, 0x1ed, 0x1ec, 0x1ef, 0x1ee, + 0, 0x1f3, 0x1f1, 0x1f1, 0x1f5, 0x1f4, 0x195, 0x1bf, + 0x1f9, 0x1f8, 0x1fb, 0x1fa, 0x1fd, 0x1fc, 0x1ff, 0x1fe, +}; + +static const Q_UINT16 case_02[] = { + 0x201, 0x200, 0x203, 0x202, 0x205, 0x204, 0x207, 0x206, + 0x209, 0x208, 0x20b, 0x20a, 0x20d, 0x20c, 0x20f, 0x20e, + 0x211, 0x210, 0x213, 0x212, 0x215, 0x214, 0x217, 0x216, + 0x219, 0x218, 0x21b, 0x21a, 0x21d, 0x21c, 0x21f, 0x21e, + 0x19e, 0, 0x223, 0x222, 0x225, 0x224, 0x227, 0x226, + 0x229, 0x228, 0x22b, 0x22a, 0x22d, 0x22c, 0x22f, 0x22e, + 0x231, 0x230, 0x233, 0x232, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x181, 0x186, 0, 0x189, 0x18a, + 0, 0x18f, 0, 0x190, 0, 0, 0, 0, + 0x193, 0, 0, 0x194, 0, 0, 0, 0, + 0x197, 0x196, 0, 0, 0, 0, 0, 0x19c, + 0, 0, 0x19d, 0, 0, 0x19f, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x1a6, 0, 0, 0x1a9, 0, 0, 0, 0, + 0x1ae, 0, 0x1b1, 0x1b2, 0, 0, 0, 0, + 0, 0, 0x1b7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_03[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x399, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x3ac, 0, + 0x3ad, 0x3ae, 0x3af, 0, 0x3cc, 0, 0x3cd, 0x3ce, + 0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, + 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, + 0x3c0, 0x3c1, 0, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, + 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x386, 0x388, 0x389, 0x38a, + 0, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, + 0x398, 0x399, 0x39a, 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, + 0x3a0, 0x3a1, 0x3a3, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, + 0x3a8, 0x3a9, 0x3aa, 0x3ab, 0x38c, 0x38e, 0x38f, 0, + 0x392, 0x398, 0, 0, 0, 0x3a6, 0x3a0, 0, + 0x3d9, 0x3d8, 0x3db, 0x3da, 0x3dd, 0x3dc, 0x3df, 0x3de, + 0x3e1, 0x3e0, 0x3e3, 0x3e2, 0x3e5, 0x3e4, 0x3e7, 0x3e6, + 0x3e9, 0x3e8, 0x3eb, 0x3ea, 0x3ed, 0x3ec, 0x3ef, 0x3ee, + 0x39a, 0x3a1, 0x3a3, 0, 0x3b8, 0x395, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_04[] = { + 0x450, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, + 0x458, 0x459, 0x45a, 0x45b, 0x45c, 0x45d, 0x45e, 0x45f, + 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, + 0x438, 0x439, 0x43a, 0x43b, 0x43c, 0x43d, 0x43e, 0x43f, + 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, + 0x448, 0x449, 0x44a, 0x44b, 0x44c, 0x44d, 0x44e, 0x44f, + 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, + 0x418, 0x419, 0x41a, 0x41b, 0x41c, 0x41d, 0x41e, 0x41f, + 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, + 0x428, 0x429, 0x42a, 0x42b, 0x42c, 0x42d, 0x42e, 0x42f, + 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, + 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0x40d, 0x40e, 0x40f, + 0x461, 0x460, 0x463, 0x462, 0x465, 0x464, 0x467, 0x466, + 0x469, 0x468, 0x46b, 0x46a, 0x46d, 0x46c, 0x46f, 0x46e, + 0x471, 0x470, 0x473, 0x472, 0x475, 0x474, 0x477, 0x476, + 0x479, 0x478, 0x47b, 0x47a, 0x47d, 0x47c, 0x47f, 0x47e, + 0x481, 0x480, 0, 0, 0, 0, 0, 0, + 0, 0, 0x48b, 0x48a, 0x48d, 0x48c, 0x48f, 0x48e, + 0x491, 0x490, 0x493, 0x492, 0x495, 0x494, 0x497, 0x496, + 0x499, 0x498, 0x49b, 0x49a, 0x49d, 0x49c, 0x49f, 0x49e, + 0x4a1, 0x4a0, 0x4a3, 0x4a2, 0x4a5, 0x4a4, 0x4a7, 0x4a6, + 0x4a9, 0x4a8, 0x4ab, 0x4aa, 0x4ad, 0x4ac, 0x4af, 0x4ae, + 0x4b1, 0x4b0, 0x4b3, 0x4b2, 0x4b5, 0x4b4, 0x4b7, 0x4b6, + 0x4b9, 0x4b8, 0x4bb, 0x4ba, 0x4bd, 0x4bc, 0x4bf, 0x4be, + 0, 0x4c2, 0x4c1, 0x4c4, 0x4c3, 0x4c6, 0x4c5, 0x4c8, + 0x4c7, 0x4ca, 0x4c9, 0x4cc, 0x4cb, 0x4ce, 0x4cd, 0, + 0x4d1, 0x4d0, 0x4d3, 0x4d2, 0x4d5, 0x4d4, 0x4d7, 0x4d6, + 0x4d9, 0x4d8, 0x4db, 0x4da, 0x4dd, 0x4dc, 0x4df, 0x4de, + 0x4e1, 0x4e0, 0x4e3, 0x4e2, 0x4e5, 0x4e4, 0x4e7, 0x4e6, + 0x4e9, 0x4e8, 0x4eb, 0x4ea, 0x4ed, 0x4ec, 0x4ef, 0x4ee, + 0x4f1, 0x4f0, 0x4f3, 0x4f2, 0x4f5, 0x4f4, 0, 0, + 0x4f9, 0x4f8, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_05[] = { + 0x501, 0x500, 0x503, 0x502, 0x505, 0x504, 0x507, 0x506, + 0x509, 0x508, 0x50b, 0x50a, 0x50d, 0x50c, 0x50f, 0x50e, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x561, 0x562, 0x563, 0x564, 0x565, 0x566, 0x567, + 0x568, 0x569, 0x56a, 0x56b, 0x56c, 0x56d, 0x56e, 0x56f, + 0x570, 0x571, 0x572, 0x573, 0x574, 0x575, 0x576, 0x577, + 0x578, 0x579, 0x57a, 0x57b, 0x57c, 0x57d, 0x57e, 0x57f, + 0x580, 0x581, 0x582, 0x583, 0x584, 0x585, 0x586, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x531, 0x532, 0x533, 0x534, 0x535, 0x536, 0x537, + 0x538, 0x539, 0x53a, 0x53b, 0x53c, 0x53d, 0x53e, 0x53f, + 0x540, 0x541, 0x542, 0x543, 0x544, 0x545, 0x546, 0x547, + 0x548, 0x549, 0x54a, 0x54b, 0x54c, 0x54d, 0x54e, 0x54f, + 0x550, 0x551, 0x552, 0x553, 0x554, 0x555, 0x556, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_1E[] = { + 0x1e01, 0x1e00, 0x1e03, 0x1e02, 0x1e05, 0x1e04, 0x1e07, 0x1e06, + 0x1e09, 0x1e08, 0x1e0b, 0x1e0a, 0x1e0d, 0x1e0c, 0x1e0f, 0x1e0e, + 0x1e11, 0x1e10, 0x1e13, 0x1e12, 0x1e15, 0x1e14, 0x1e17, 0x1e16, + 0x1e19, 0x1e18, 0x1e1b, 0x1e1a, 0x1e1d, 0x1e1c, 0x1e1f, 0x1e1e, + 0x1e21, 0x1e20, 0x1e23, 0x1e22, 0x1e25, 0x1e24, 0x1e27, 0x1e26, + 0x1e29, 0x1e28, 0x1e2b, 0x1e2a, 0x1e2d, 0x1e2c, 0x1e2f, 0x1e2e, + 0x1e31, 0x1e30, 0x1e33, 0x1e32, 0x1e35, 0x1e34, 0x1e37, 0x1e36, + 0x1e39, 0x1e38, 0x1e3b, 0x1e3a, 0x1e3d, 0x1e3c, 0x1e3f, 0x1e3e, + 0x1e41, 0x1e40, 0x1e43, 0x1e42, 0x1e45, 0x1e44, 0x1e47, 0x1e46, + 0x1e49, 0x1e48, 0x1e4b, 0x1e4a, 0x1e4d, 0x1e4c, 0x1e4f, 0x1e4e, + 0x1e51, 0x1e50, 0x1e53, 0x1e52, 0x1e55, 0x1e54, 0x1e57, 0x1e56, + 0x1e59, 0x1e58, 0x1e5b, 0x1e5a, 0x1e5d, 0x1e5c, 0x1e5f, 0x1e5e, + 0x1e61, 0x1e60, 0x1e63, 0x1e62, 0x1e65, 0x1e64, 0x1e67, 0x1e66, + 0x1e69, 0x1e68, 0x1e6b, 0x1e6a, 0x1e6d, 0x1e6c, 0x1e6f, 0x1e6e, + 0x1e71, 0x1e70, 0x1e73, 0x1e72, 0x1e75, 0x1e74, 0x1e77, 0x1e76, + 0x1e79, 0x1e78, 0x1e7b, 0x1e7a, 0x1e7d, 0x1e7c, 0x1e7f, 0x1e7e, + 0x1e81, 0x1e80, 0x1e83, 0x1e82, 0x1e85, 0x1e84, 0x1e87, 0x1e86, + 0x1e89, 0x1e88, 0x1e8b, 0x1e8a, 0x1e8d, 0x1e8c, 0x1e8f, 0x1e8e, + 0x1e91, 0x1e90, 0x1e93, 0x1e92, 0x1e95, 0x1e94, 0, 0, + 0, 0, 0, 0x1e60, 0, 0, 0, 0, + 0x1ea1, 0x1ea0, 0x1ea3, 0x1ea2, 0x1ea5, 0x1ea4, 0x1ea7, 0x1ea6, + 0x1ea9, 0x1ea8, 0x1eab, 0x1eaa, 0x1ead, 0x1eac, 0x1eaf, 0x1eae, + 0x1eb1, 0x1eb0, 0x1eb3, 0x1eb2, 0x1eb5, 0x1eb4, 0x1eb7, 0x1eb6, + 0x1eb9, 0x1eb8, 0x1ebb, 0x1eba, 0x1ebd, 0x1ebc, 0x1ebf, 0x1ebe, + 0x1ec1, 0x1ec0, 0x1ec3, 0x1ec2, 0x1ec5, 0x1ec4, 0x1ec7, 0x1ec6, + 0x1ec9, 0x1ec8, 0x1ecb, 0x1eca, 0x1ecd, 0x1ecc, 0x1ecf, 0x1ece, + 0x1ed1, 0x1ed0, 0x1ed3, 0x1ed2, 0x1ed5, 0x1ed4, 0x1ed7, 0x1ed6, + 0x1ed9, 0x1ed8, 0x1edb, 0x1eda, 0x1edd, 0x1edc, 0x1edf, 0x1ede, + 0x1ee1, 0x1ee0, 0x1ee3, 0x1ee2, 0x1ee5, 0x1ee4, 0x1ee7, 0x1ee6, + 0x1ee9, 0x1ee8, 0x1eeb, 0x1eea, 0x1eed, 0x1eec, 0x1eef, 0x1eee, + 0x1ef1, 0x1ef0, 0x1ef3, 0x1ef2, 0x1ef5, 0x1ef4, 0x1ef7, 0x1ef6, + 0x1ef9, 0x1ef8, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_1F[] = { + 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0, 0, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0, 0, + 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0, 0, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0, 0, + 0, 0x1f59, 0, 0x1f5b, 0, 0x1f5d, 0, 0x1f5f, + 0, 0x1f51, 0, 0x1f53, 0, 0x1f55, 0, 0x1f57, + 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, + 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0, 0, + 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fb8, 0x1fb9, 0, 0x1fbc, 0, 0, 0, 0, + 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0, 0x399, 0, + 0, 0, 0, 0x1fcc, 0, 0, 0, 0, + 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0, 0, 0, + 0x1fd8, 0x1fd9, 0, 0, 0, 0, 0, 0, + 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0, 0, 0, 0, + 0x1fe8, 0x1fe9, 0, 0, 0, 0x1fec, 0, 0, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0, 0, 0, + 0, 0, 0, 0x1ffc, 0, 0, 0, 0, + 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0, 0, 0, +}; + +static const Q_UINT16 case_21[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x3c9, 0, + 0, 0, 0x6b, 0xe5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, + 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_24[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x24d0, 0x24d1, + 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, + 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, + 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, + 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd, + 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5, + 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd, + 0x24ce, 0x24cf, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_FF[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0, 0, 0, 0, 0, + 0, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, + 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, + 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, + 0xff38, 0xff39, 0xff3a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 * const case_info[256] = { + case_00, case_01, case_02, case_03, case_04, case_05, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, case_1E, case_1F, + 0, case_21, 0, 0, case_24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, case_FF, +}; +// 39162 bytes + +static const Q_INT8 num_00[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2, 3, -1, -1, -1, -1, + -1, 1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_06[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_09[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_0B[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_0D[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_0E[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_0F[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_10[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_13[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_17[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_18[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_20[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 num_24[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, 2, 3, 4, + 5, 6, 7, 8, 9, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1, 2, 3, + 4, 5, 6, 7, 8, 9, -1, -1, +}; + +static const Q_INT8 num_27[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1, 2, + 3, 4, 5, 6, 7, 8, 9, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +static const Q_INT8 * const decimal_info[256] = { + num_00, 0, 0, 0, 0, 0, num_06, 0, + 0, num_09, num_09, num_0B, num_09, num_0D, num_0E, num_0F, + num_10, 0, 0, num_13, 0, 0, 0, num_17, + num_18, 0, 0, 0, 0, 0, 0, 0, + num_20, 0, 0, 0, num_24, 0, 0, num_27, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, num_18, +}; +// 47354 bytes + +// END OF GENERATED DATA + +#endif + +static inline QChar::Category category( const QChar &c ) +{ +#ifndef QT_NO_UNICODETABLES + return (QChar::Category)(unicode_info[c.row()][c.cell()]); +#else +// ### just ASCII + if ( c.unicode() < 0x100 ) { + return (QChar::Category)(ui_00[c.unicode()]); + } + return QChar::Letter_Uppercase; //####### +#endif +} + +static inline QChar lower( const QChar &c ) +{ +#ifndef QT_NO_UNICODETABLES + uchar row = c.row(); + uchar cell = c.cell(); + if ( unicode_info[row][cell] != QChar::Letter_Uppercase ) + return c; + Q_UINT16 lower = *( case_info[row] + cell ); + if ( lower == 0 ) + return c; + return lower; +#else + if ( c.row() ) + return c; + else + return QChar( tolower((uchar) c.latin1()) ); +#endif +} + +static inline QChar upper( const QChar &c ) +{ +#ifndef QT_NO_UNICODETABLES + uchar row = c.row(); + uchar cell = c.cell(); + if ( unicode_info[row][cell] != QChar::Letter_Lowercase ) + return c; + Q_UINT16 upper = *(case_info[row]+cell); + if ( upper == 0 ) + return c; + return upper; +#else + if ( c.row() ) + return c; + else + return QChar( toupper((uchar) c.latin1()) ); +#endif +} + +static inline QChar::Direction direction( const QChar &c ) +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = direction_info[c.row()]; + if(!rowp) return QChar::DirL; + return (QChar::Direction) ( *(rowp+c.cell()) & 0x1f ); +#else + return QChar::DirL; +#endif +} + +static inline bool mirrored( const QChar &c ) +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = direction_info[c.row()]; + if ( !rowp ) + return FALSE; + return *(rowp+c.cell())>128; +#else + return FALSE; +#endif +} + +#ifndef QT_NO_UNICODETABLES +static const Q_UINT16 symmetricPairs[] = { + 0x0028, 0x0029, 0x003C, 0x003E, 0x005B, 0x005D, 0x007B, 0x007D, + 0x00AB, 0x00BB, 0x2039, 0x203A, 0x2045, 0x2046, 0x207D, 0x207E, + 0x208D, 0x208E, 0x2208, 0x220B, 0x2209, 0x220C, 0x220A, 0x220D, + 0x2215, 0x29F5, 0x223C, 0x223D, 0x2243, 0x22CD, 0x2252, 0x2253, + 0x2254, 0x2255, 0x2264, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, + 0x226A, 0x226B, 0x226E, 0x226F, 0x2270, 0x2271, 0x2272, 0x2273, + 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, 0x227A, 0x227B, + 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, 0x2281, 0x2282, 0x2283, + 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, 0x228A, 0x228B, + 0x228F, 0x2290, 0x2291, 0x2292, 0x2298, 0x29B8, 0x22A2, 0x22A3, + 0x22A6, 0x2ADE, 0x22A8, 0x2AE4, 0x22A9, 0x2AE3, 0x22AB, 0x2AE5, + 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0x22B6, 0x22B7, + 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22D0, 0x22D1, 0x22D6, 0x22D7, + 0x22D8, 0x22D9, 0x22DA, 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, + 0x22E0, 0x22E1, 0x22E2, 0x22E3, 0x22E4, 0x22E5, 0x22E6, 0x22E7, + 0x22E8, 0x22E9, 0x22EA, 0x22EB, 0x22EC, 0x22ED, 0x22F0, 0x22F1, + 0x22F2, 0x22FA, 0x22F3, 0x22FB, 0x22F4, 0x22FC, 0x22F6, 0x22FD, + 0x22F7, 0x22FE, 0x2308, 0x2309, 0x230A, 0x230B, 0x2329, 0x232A, + 0x2768, 0x2769, 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, + 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27D5, 0x27D6, + 0x27DD, 0x27DE, 0x27E2, 0x27E3, 0x27E4, 0x27E5, 0x27E6, 0x27E7, + 0x27E8, 0x27E9, 0x27EA, 0x27EB, 0x2983, 0x2984, 0x2985, 0x2986, + 0x2987, 0x2988, 0x2989, 0x298A, 0x298B, 0x298C, 0x298D, 0x2990, + 0x298E, 0x298F, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, + 0x2997, 0x2998, 0x29C0, 0x29C1, 0x29C4, 0x29C5, 0x29CF, 0x29D0, + 0x29D1, 0x29D2, 0x29D4, 0x29D5, 0x29D8, 0x29D9, 0x29DA, 0x29DB, + 0x29F8, 0x29F9, 0x29FC, 0x29FD, 0x2A2B, 0x2A2C, 0x2A34, 0x2A35, + 0x2A3C, 0x2A3D, 0x2A64, 0x2A65, 0x2A79, 0x2A7A, 0x2A7D, 0x2A7E, + 0x2A7F, 0x2A80, 0x2A81, 0x2A82, 0x2A83, 0x2A84, 0x2A8B, 0x2A8C, + 0x2A91, 0x2A92, 0x2A93, 0x2A94, 0x2A95, 0x2A96, 0x2A97, 0x2A98, + 0x2A99, 0x2A9A, 0x2A9B, 0x2A9C, 0x2AA1, 0x2AA2, 0x2AA6, 0x2AA7, + 0x2AA8, 0x2AA9, 0x2AAA, 0x2AAB, 0x2AAC, 0x2AAD, 0x2AAF, 0x2AB0, + 0x2AB3, 0x2AB4, 0x2ABB, 0x2ABC, 0x2ABD, 0x2ABE, 0x2ABF, 0x2AC0, + 0x2AC1, 0x2AC2, 0x2AC3, 0x2AC4, 0x2AC5, 0x2AC6, 0x2ACD, 0x2ACE, + 0x2ACF, 0x2AD0, 0x2AD1, 0x2AD2, 0x2AD3, 0x2AD4, 0x2AD5, 0x2AD6, + 0x2AEC, 0x2AED, 0x2AF7, 0x2AF8, 0x2AF9, 0x2AFA, 0x3008, 0x3009, + 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3010, 0x3011, + 0x3014, 0x3015, 0x3016, 0x3017, 0x3018, 0x3019, 0x301A, 0x301B, + 0xFF08, 0xFF09, 0xFF1C, 0xFF1E, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, + 0xFF5F, 0xFF60, 0xFF62, 0xFF63, +}; + +// ### shouldn't this be const? +static const int symmetricPairsSize = + sizeof(symmetricPairs)/sizeof(symmetricPairs[0]); + +/* + * ---------------------------------------------------------------------- + * End of unicode tables + * ---------------------------------------------------------------------- + */ + +#endif + +static int ucstrcmp( const QString &as, const QString &bs ) +{ + const QChar *a = as.unicode(); + const QChar *b = bs.unicode(); + if ( a == b ) + return 0; + if ( a == 0 ) + return 1; + if ( b == 0 ) + return -1; + int l=QMIN(as.length(),bs.length()); + while ( l-- && *a == *b ) + a++,b++; + if ( l==-1 ) + return ( as.length()-bs.length() ); + return a->unicode() - b->unicode(); +} + +static int ucstrncmp( const QChar *a, const QChar *b, int l ) +{ + while ( l-- && *a == *b ) + a++,b++; + if ( l==-1 ) + return 0; + return a->unicode() - b->unicode(); +} + +static int ucstrnicmp( const QChar *a, const QChar *b, int l ) +{ + while ( l-- && ::lower( *a ) == ::lower( *b ) ) + a++,b++; + if ( l==-1 ) + return 0; + return ::lower( *a ).unicode() - ::lower( *b ).unicode(); +} + +static uint computeNewMax( uint len ) +{ + uint newMax = 4; + while ( newMax < len ) + newMax *= 2; + // try to spare some memory + if ( newMax >= 1024 * 1024 && len <= newMax - (newMax >> 2) ) + newMax -= newMax >> 2; + return newMax; +} + +/*! + \class QCharRef qstring.h + \reentrant + \brief The QCharRef class is a helper class for QString. + + \ingroup text + + When you get an object of type QCharRef, if you can assign to it, + the assignment will apply to the character in the string from + which you got the reference. That is its whole purpose in life. + The QCharRef becomes invalid once modifications are made to the + string: if you want to keep the character, copy it into a QChar. + + Most of the QChar member functions also exist in QCharRef. + However, they are not explicitly documented here. + + \sa QString::operator[]() QString::at() QChar +*/ + +/*! + \class QChar qstring.h + \reentrant + \brief The QChar class provides a lightweight Unicode character. + + \ingroup text + + Unicode characters are (so far) 16-bit entities without any markup + or structure. This class represents such an entity. It is + lightweight, so it can be used everywhere. Most compilers treat it + like a "short int". (In a few years it may be necessary to make + QChar 32-bit when more than 65536 Unicode code points have been + defined and come into use.) + + QChar provides a full complement of testing/classification + functions, converting to and from other formats, converting from + composed to decomposed Unicode, and trying to compare and + case-convert if you ask it to. + + The classification functions include functions like those in + ctype.h, but operating on the full range of Unicode characters. + They all return TRUE if the character is a certain type of + character; otherwise they return FALSE. These classification + functions are isNull() (returns TRUE if the character is U+0000), + isPrint() (TRUE if the character is any sort of printable + character, including whitespace), isPunct() (any sort of + punctation), isMark() (Unicode Mark), isLetter (a letter), + isNumber() (any sort of numeric character), isLetterOrNumber(), + and isDigit() (decimal digits). All of these are wrappers around + category() which return the Unicode-defined category of each + character. + + QChar further provides direction(), which indicates the "natural" + writing direction of this character. The joining() function + indicates how the character joins with its neighbors (needed + mostly for Arabic) and finally mirrored(), which indicates whether + the character needs to be mirrored when it is printed in its + "unnatural" writing direction. + + Composed Unicode characters (like å) can be converted to + decomposed Unicode ("a" followed by "ring above") by using + decomposition(). + + In Unicode, comparison is not necessarily possible and case + conversion is very difficult at best. Unicode, covering the + "entire" world, also includes most of the world's case and sorting + problems. Qt tries, but not very hard: operator==() and friends + will do comparison based purely on the numeric Unicode value (code + point) of the characters, and upper() and lower() will do case + changes when the character has a well-defined upper/lower-case + equivalent. There is no provision for locale-dependent case + folding rules or comparison; these functions are meant to be fast + so they can be used unambiguously in data structures. (See + QString::localeAwareCompare() though.) + + The conversion functions include unicode() (to a scalar), latin1() + (to scalar, but converts all non-Latin1 characters to 0), row() + (gives the Unicode row), cell() (gives the Unicode cell), + digitValue() (gives the integer value of any of the numerous digit + characters), and a host of constructors. + + More information can be found in the document \link unicode.html + About Unicode. \endlink + + \sa QString QCharRef +*/ + +/*! + \enum QChar::Category + + This enum maps the Unicode character categories. + + The following characters are normative in Unicode: + + \value Mark_NonSpacing Unicode class name Mn + + \value Mark_SpacingCombining Unicode class name Mc + + \value Mark_Enclosing Unicode class name Me + + \value Number_DecimalDigit Unicode class name Nd + + \value Number_Letter Unicode class name Nl + + \value Number_Other Unicode class name No + + \value Separator_Space Unicode class name Zs + + \value Separator_Line Unicode class name Zl + + \value Separator_Paragraph Unicode class name Zp + + \value Other_Control Unicode class name Cc + + \value Other_Format Unicode class name Cf + + \value Other_Surrogate Unicode class name Cs + + \value Other_PrivateUse Unicode class name Co + + \value Other_NotAssigned Unicode class name Cn + + + The following categories are informative in Unicode: + + \value Letter_Uppercase Unicode class name Lu + + \value Letter_Lowercase Unicode class name Ll + + \value Letter_Titlecase Unicode class name Lt + + \value Letter_Modifier Unicode class name Lm + + \value Letter_Other Unicode class name Lo + + \value Punctuation_Connector Unicode class name Pc + + \value Punctuation_Dash Unicode class name Pd + + \value Punctuation_Open Unicode class name Ps + + \value Punctuation_Close Unicode class name Pe + + \value Punctuation_InitialQuote Unicode class name Pi + + \value Punctuation_FinalQuote Unicode class name Pf + + \value Punctuation_Other Unicode class name Po + + \value Symbol_Math Unicode class name Sm + + \value Symbol_Currency Unicode class name Sc + + \value Symbol_Modifier Unicode class name Sk + + \value Symbol_Other Unicode class name So + + + There are two categories that are specific to Qt: + + \value NoCategory used when Qt is dazed and confused and cannot + make sense of anything. + + \value Punctuation_Dask old typo alias for Punctuation_Dash + +*/ + +/*! + \enum QChar::Direction + + This enum type defines the Unicode direction attributes. See \link + http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. + + In order to conform to C/C++ naming conventions "Dir" is prepended + to the codes used in the Unicode Standard. +*/ + +/*! + \enum QChar::Decomposition + + This enum type defines the Unicode decomposition attributes. See + \link http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. +*/ + +/*! + \enum QChar::Joining + + This enum type defines the Unicode joining attributes. See \link + http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. +*/ + +/*! + \enum QChar::CombiningClass + + This enum type defines names for some of the Unicode combining + classes. See \link http://www.unicode.org/ the Unicode + Standard\endlink for a description of the values. +*/ + +/*! + \fn void QChar::setCell( uchar cell ) + \internal +*/ + +/*! + \fn void QChar::setRow( uchar row ) + \internal +*/ + + +/*! + \fn QChar::QChar() + + Constructs a null QChar (one that isNull()). +*/ + + +/*! + \fn QChar::QChar( char c ) + + Constructs a QChar corresponding to ASCII/Latin1 character \a c. +*/ + + +/*! + \fn QChar::QChar( uchar c ) + + Constructs a QChar corresponding to ASCII/Latin1 character \a c. +*/ + + +/*! + \fn QChar::QChar( uchar c, uchar r ) + + Constructs a QChar for Unicode cell \a c in row \a r. +*/ + + +/*! + \fn QChar::QChar( const QChar& c ) + + Constructs a copy of \a c. This is a deep copy, if such a + lightweight object can be said to have deep copies. +*/ + + +/*! + \fn QChar::QChar( ushort rc ) + + Constructs a QChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn QChar::QChar( short rc ) + + Constructs a QChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn QChar::QChar( uint rc ) + + Constructs a QChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn QChar::QChar( int rc ) + + Constructs a QChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn bool QChar::networkOrdered () + + \obsolete + + Returns TRUE if this character is in network byte order (MSB + first); otherwise returns FALSE. This is platform dependent. +*/ + + +/*! + \fn bool QChar::isNull() const + + Returns TRUE if the character is the Unicode character 0x0000, + i.e. ASCII NUL; otherwise returns FALSE. +*/ + +/*! + \fn uchar QChar::cell () const + + Returns the cell (least significant byte) of the Unicode + character. +*/ + +/*! + \fn uchar QChar::row () const + + Returns the row (most significant byte) of the Unicode character. +*/ + +/*! + Returns TRUE if the character is a printable character; otherwise + returns FALSE. This is any character not of category Cc or Cn. + + Note that this gives no indication of whether the character is + available in a particular \link QFont font\endlink. +*/ +bool QChar::isPrint() const +{ + Category c = ::category( *this ); + return !(c == Other_Control || c == Other_NotAssigned); +} + +/*! + Returns TRUE if the character is a separator character + (Separator_* categories); otherwise returns FALSE. +*/ +bool QChar::isSpace() const +{ + if( ucs >= 9 && ucs <=13 ) return TRUE; + Category c = ::category( *this ); + return c >= Separator_Space && c <= Separator_Paragraph; +} + +/*! + Returns TRUE if the character is a mark (Mark_* categories); + otherwise returns FALSE. +*/ +bool QChar::isMark() const +{ + Category c = ::category( *this ); + return c >= Mark_NonSpacing && c <= Mark_Enclosing; +} + +/*! + Returns TRUE if the character is a punctuation mark (Punctuation_* + categories); otherwise returns FALSE. +*/ +bool QChar::isPunct() const +{ + Category c = ::category( *this ); + return (c >= Punctuation_Connector && c <= Punctuation_Other); +} + +/*! + Returns TRUE if the character is a letter (Letter_* categories); + otherwise returns FALSE. +*/ +bool QChar::isLetter() const +{ + Category c = ::category( *this ); + return (c >= Letter_Uppercase && c <= Letter_Other); +} + +/*! + Returns TRUE if the character is a number (of any sort - Number_* + categories); otherwise returns FALSE. + + \sa isDigit() +*/ +bool QChar::isNumber() const +{ + Category c = ::category( *this ); + return c >= Number_DecimalDigit && c <= Number_Other; +} + +/*! + Returns TRUE if the character is a letter or number (Letter_* or + Number_* categories); otherwise returns FALSE. +*/ +bool QChar::isLetterOrNumber() const +{ + Category c = ::category( *this ); + return (c >= Letter_Uppercase && c <= Letter_Other) + || (c >= Number_DecimalDigit && c <= Number_Other); +} + + +/*! + Returns TRUE if the character is a decimal digit + (Number_DecimalDigit); otherwise returns FALSE. +*/ +bool QChar::isDigit() const +{ + return (::category( *this ) == Number_DecimalDigit); +} + + +/*! + Returns TRUE if the character is a symbol (Symbol_* categories); + otherwise returns FALSE. +*/ +bool QChar::isSymbol() const +{ + Category c = ::category( *this ); + return c >= Symbol_Math && c <= Symbol_Other; +} + +/*! + Returns the numeric value of the digit, or -1 if the character is + not a digit. +*/ +int QChar::digitValue() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_INT8 *dec_row = decimal_info[row()]; + if( !dec_row ) + return -1; + return dec_row[cell()]; +#else + // ##### just latin1 + if ( ucs < '0' || ucs > '9' ) + return -1; + else + return ucs - '0'; +#endif +} + +/*! + Returns the character category. + + \sa Category +*/ +QChar::Category QChar::category() const +{ + return ::category( *this ); +} + +/*! + Returns the character's direction. + + \sa Direction +*/ +QChar::Direction QChar::direction() const +{ + return ::direction( *this ); +} + +/*! + \warning This function is not supported (it may change to use + Unicode character classes). + + Returns information about the joining properties of the character + (needed for example, for Arabic). +*/ +QChar::Joining QChar::joining() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = direction_info[row()]; + if ( !rowp ) + return QChar::OtherJoining; + return (Joining) ((*(rowp+cell()) >> 5) &0x3); +#else + return OtherJoining; +#endif +} + + +/*! + Returns TRUE if the character is a mirrored character (one that + should be reversed if the text direction is reversed); otherwise + returns FALSE. +*/ +bool QChar::mirrored() const +{ + return ::mirrored( *this ); +} + +/*! + Returns the mirrored character if this character is a mirrored + character, otherwise returns the character itself. +*/ +QChar QChar::mirroredChar() const +{ +#ifndef QT_NO_UNICODETABLES + if(!::mirrored( *this )) + return *this; + + int i; + int c = unicode(); + for (i = 0; i < symmetricPairsSize; i ++) { + if (symmetricPairs[i] == c) + return symmetricPairs[(i%2) ? (i-1) : (i+1)]; + } +#endif + return *this; +} + +#ifndef QT_NO_UNICODETABLES +// ### REMOVE ME 4.0 +static QString shared_decomp; +#endif +/*! + \nonreentrant + + Decomposes a character into its parts. Returns QString::null if no + decomposition exists. +*/ +const QString &QChar::decomposition() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT16 *r = decomposition_info[row()]; + if(!r) return QString::null; + + Q_UINT16 pos = r[cell()]; + if(!pos) return QString::null; + pos+=2; + + QString s; + Q_UINT16 c; + while((c = decomposition_map[pos++]) != 0) s += QChar(c); + // ### In 4.0, return s, and not shared_decomp. shared_decomp + // prevents this function from being reentrant. + shared_decomp = s; + return shared_decomp; +#else + return QString::null; +#endif +} + +/*! + Returns the tag defining the composition of the character. Returns + QChar::Single if no decomposition exists. +*/ +QChar::Decomposition QChar::decompositionTag() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT16 *r = decomposition_info[row()]; + if(!r) return QChar::Single; + + Q_UINT16 pos = r[cell()]; + if(!pos) return QChar::Single; + + return (QChar::Decomposition) decomposition_map[pos]; +#else + return Single; // ########### FIX eg. just latin1 +#endif +} + +/*! + Returns the combining class for the character as defined in the + Unicode standard. This is mainly useful as a positioning hint for + marks attached to a base character. + + The Qt text rendering engine uses this information to correctly + position non spacing marks around a base character. +*/ +unsigned char QChar::combiningClass() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = combining_info[row()]; + if ( !rowp ) + return 0; + return *(rowp+cell()); +#else + return 0; +#endif +} + + +/*! + Returns the lowercase equivalent if the character is uppercase; + otherwise returns the character itself. +*/ +QChar QChar::lower() const +{ + return ::lower( *this ); +} + +/*! + Returns the uppercase equivalent if the character is lowercase; + otherwise returns the character itself. +*/ +QChar QChar::upper() const +{ + return ::upper( *this ); +} + +/*! + \fn QChar::operator char() const + + Returns the Latin1 character equivalent to the QChar, or 0. This + is mainly useful for non-internationalized software. + + \sa unicode() +*/ + +/*! + \fn ushort QChar::unicode() const + + Returns the numeric Unicode value equal to the QChar. Normally, + you should use QChar objects as they are equivalent, but for some + low-level tasks (e.g. indexing into an array of Unicode + information), this function is useful. +*/ + +/*! + \fn ushort & QChar::unicode() + + \overload + + Returns a reference to the numeric Unicode value equal to the + QChar. +*/ + +/***************************************************************************** + Documentation of QChar related functions + *****************************************************************************/ + +/*! + \fn bool operator==( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if \a c1 and \a c2 are the same Unicode character; + otherwise returns FALSE. +*/ + +/*! + \fn bool operator==( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if \a c is the ASCII/Latin1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn bool operator==( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if \a c is the ASCII/Latin1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if \a c1 and \a c2 are not the same Unicode + character; otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if \a c is not the ASCII/Latin1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if \a c is not the ASCII/Latin1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator<=( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c1 is less than + that of \a c2, or they are the same Unicode character; otherwise + returns FALSE. +*/ + +/*! + \fn int operator<=( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is less than or + equal to that of the ASCII/Latin1 character \a ch; otherwise + returns FALSE. +*/ + +/*! + \fn int operator<=( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is less than or equal to that of \a c; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c1 is greater than + that of \a c2, or they are the same Unicode character; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is greater than + or equal to that of the ASCII/Latin1 character \a ch; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is greater than or equal to that of \a c; + otherwise returns FALSE. +*/ + +/*! + \fn int operator<( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c1 is less than + that of \a c2; otherwise returns FALSE. +*/ + +/*! + \fn int operator<( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is less than that + of the ASCII/Latin1 character \a ch; otherwise returns FALSE. +*/ + +/*! + \fn int operator<( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is less than that of \a c; otherwise returns + FALSE. +*/ + +/*! + \fn int operator>( QChar c1, QChar c2 ) + + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c1 is greater than + that of \a c2; otherwise returns FALSE. +*/ + +/*! + \fn int operator>( QChar c, char ch ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is greater than + that of the ASCII/Latin1 character \a ch; otherwise returns FALSE. +*/ + +/*! + \fn int operator>( char ch, QChar c ) + + \overload + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is greater than that of \a c; otherwise returns + FALSE. +*/ + +#ifndef QT_NO_UNICODETABLES + +// small class used internally in QString::Compose() +class QLigature +{ +public: + QLigature( QChar c ); + + Q_UINT16 first() { cur = ligatures; return cur ? *cur : 0; } + Q_UINT16 next() { return cur && *cur ? *(cur++) : 0; } + Q_UINT16 current() { return cur ? *cur : 0; } + + int match(QString & str, unsigned int index); + QChar head(); + QChar::Decomposition tag(); + +private: + Q_UINT16 *ligatures; + Q_UINT16 *cur; +}; + +QLigature::QLigature( QChar c ) +{ + const Q_UINT16 *r = ligature_info[c.row()]; + if( !r ) + ligatures = 0; + else + { + const Q_UINT16 pos = r[c.cell()]; + ligatures = (Q_UINT16 *)&(ligature_map[pos]); + } + cur = ligatures; +} + +QChar QLigature::head() +{ + if(current()) + return QChar(decomposition_map[current()+1]); + + return QChar::null; +} + +QChar::Decomposition QLigature::tag() +{ + if(current()) + return (QChar::Decomposition) decomposition_map[current()]; + + return QChar::Canonical; +} + +int QLigature::match(QString & str, unsigned int index) +{ + unsigned int i=index; + + if(!current()) return 0; + + Q_UINT16 lig = current() + 2; + Q_UINT16 ch; + + while ((i < str.length()) && (ch = decomposition_map[lig])) { + if (str[(int)i] != QChar(ch)) + return 0; + i++; + lig++; + } + + if (!decomposition_map[lig]) + { + return i-index; + } + return 0; +} + + +// this function is just used in QString::compose() +static inline bool format(QChar::Decomposition tag, QString & str, + int index, int len) +{ + unsigned int l = index + len; + unsigned int r = index; + + bool left = FALSE, right = FALSE; + + left = ((l < str.length()) && + ((str[(int)l].joining() == QChar::Dual) || + (str[(int)l].joining() == QChar::Right))); + if (r > 0) { + r--; + //printf("joining(right) = %d\n", str[(int)r].joining()); + right = (str[(int)r].joining() == QChar::Dual); + } + + + switch (tag) { + case QChar::Medial: + return (left & right); + case QChar::Initial: + return (left && !right); + case QChar::Final: + return (right);// && !left); + case QChar::Isolated: + default: + return (!right && !left); + } +} // format() +#endif + +/* + QString::compose() and visual() were developed by Gordon Tisher + <tisher@uniserve.ca>, with input from Lars Knoll <knoll@mpi-hd.mpg.de>, + who developed the unicode data tables. +*/ +/*! + \warning This function is not supported in Qt 3.x. It is provided + for experimental and illustrative purposes only. It is mainly of + interest to those experimenting with Arabic and other + composition-rich texts. + + Applies possible ligatures to a QString. Useful when + composition-rich text requires rendering with glyph-poor fonts, + but it also makes compositions such as QChar(0x0041) ('A') and + QChar(0x0308) (Unicode accent diaresis), giving QChar(0x00c4) + (German A Umlaut). +*/ +void QString::compose() +{ +#ifndef QT_NO_UNICODETABLES + unsigned int index=0, len; + unsigned int cindex = 0; + + QChar code, head; + + QMemArray<QChar> dia; + + QString composed = *this; + + while (index < length()) { + code = at(index); + //printf("\n\nligature for 0x%x:\n", code.unicode()); + QLigature ligature(code); + ligature.first(); + while(ligature.current()) { + if ((len = ligature.match(*this, index)) != 0) { + head = ligature.head(); + unsigned short code = head.unicode(); + // we exclude Arabic presentation forms A and a few + // other ligatures, which are undefined in most fonts + if(!(code > 0xfb50 && code < 0xfe80) && + !(code > 0xfb00 && code < 0xfb2a)) { + // joining info is only needed for Arabic + if (format(ligature.tag(), *this, index, len)) { + //printf("using ligature 0x%x, len=%d\n",code,len); + // replace letter + composed.replace(cindex, len, QChar(head)); + index += len-1; + // we continue searching in case we have a final + // form because medial ones are preferred. + if ( len != 1 || ligature.tag() !=QChar::Final ) + break; + } + } + } + ligature.next(); + } + cindex++; + index++; + } + *this = composed; +#endif +} + + +// These macros are used for efficient allocation of QChar strings. +// IMPORTANT! If you change these, make sure you also change the +// "delete unicode" statement in ~QStringData() in qstring.h correspondingly! + +#define QT_ALLOC_QCHAR_VEC( N ) (QChar*) new char[ sizeof(QChar)*( N ) ] +#define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P )) + + +/*! + This utility function converts the 8-bit string \a ba to Unicode, + returning the result. + + The caller is responsible for deleting the return value with + delete[]. +*/ + +QChar* QString::asciiToUnicode( const QByteArray& ba, uint* len ) +{ + if ( ba.isNull() ) { + *len = 0; + return 0; + } + int l = 0; + while ( l < (int)ba.size() && ba[l] ) + l++; + char* str = ba.data(); + QChar *uc = new QChar[ l ]; // Can't use macro, since function is public + QChar *result = uc; + if ( len ) + *len = l; + while (l--) + *uc++ = *str++; + return result; +} + +static QChar* internalAsciiToUnicode( const QByteArray& ba, uint* len ) +{ + if ( ba.isNull() ) { + *len = 0; + return 0; + } + int l = 0; + while ( l < (int)ba.size() && ba[l] ) + l++; + char* str = ba.data(); + QChar *uc = QT_ALLOC_QCHAR_VEC( l ); + QChar *result = uc; + if ( len ) + *len = l; + while (l--) + *uc++ = *str++; + return result; +} + +/*! + \overload + + This utility function converts the '\0'-terminated 8-bit string \a + str to Unicode, returning the result and setting \a *len to the + length of the Unicode string. + + The caller is responsible for deleting the return value with + delete[]. +*/ + +QChar* QString::asciiToUnicode( const char *str, uint* len, uint maxlen ) +{ + QChar* result = 0; + uint l = 0; + if ( str ) { + if ( maxlen != (uint)-1 ) { + while ( l < maxlen && str[l] ) + l++; + } else { + // Faster? + l = qstrlen(str); + } + QChar *uc = new QChar[ l ]; // Can't use macro since function is public + result = uc; + uint i = l; + while ( i-- ) + *uc++ = *str++; + } + if ( len ) + *len = l; + return result; +} + +static QChar* internalAsciiToUnicode( const char *str, uint* len, + uint maxlen = (uint)-1 ) +{ + QChar* result = 0; + uint l = 0; + if ( str ) { + if ( maxlen != (uint)-1 ) { + while ( l < maxlen && str[l] ) + l++; + } else { + // Faster? + l = qstrlen(str); + } + QChar *uc = QT_ALLOC_QCHAR_VEC( l ); + result = uc; + uint i = l; + while ( i-- ) + *uc++ = *str++; + } + if ( len ) + *len = l; + return result; +} + +/*! + This utility function converts \a l 16-bit characters from \a uc + to ASCII, returning a '\0'-terminated string. + + The caller is responsible for deleting the resultant string with + delete[]. +*/ +char* QString::unicodeToAscii(const QChar *uc, uint l) +{ + if (!uc) { + return 0; + } + char *a = new char[l+1]; + char *result = a; + while (l--) { + *a++ = (uc->unicode() > 0xff) ? '?' : (char)uc->unicode(); + uc++; + } + *a = '\0'; + return result; +} + +/***************************************************************************** + QString member functions + *****************************************************************************/ + +/*! + \class QString qstring.h + \reentrant + + \brief The QString class provides an abstraction of Unicode text + and the classic C '\0'-terminated char array. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + QString uses \link shclass.html implicit sharing\endlink, which + makes it very efficient and easy to use. + + In all of the QString methods that take \c {const char *} + parameters, the \c {const char *} is interpreted as a classic + C-style '\0'-terminated ASCII string. It is legal for the \c + {const char *} parameter to be 0. If the \c {const char *} is not + '\0'-terminated, the results are undefined. Functions that copy + classic C strings into a QString will not copy the terminating + '\0' character. The QChar array of the QString (as returned by + unicode()) is generally not terminated by a '\0'. If you need to + pass a QString to a function that requires a C '\0'-terminated + string use latin1(). + + \keyword QString::null + A QString that has not been assigned to anything is \e null, i.e. + both the length and data pointer is 0. A QString that references + the empty string ("", a single '\0' char) is \e empty. Both null + and empty QStrings are legal parameters to the methods. Assigning + \c{(const char *) 0} to QString gives a null QString. For + convenience, \c QString::null is a null QString. When sorting, + empty strings come first, followed by non-empty strings, followed + by null strings. We recommend using \c{if ( !str.isNull() )} to + check for a non-null string rather than \c{if ( !str )}; see \l + operator!() for an explanation. + + Note that if you find that you are mixing usage of \l QCString, + QString, and \l QByteArray, this causes lots of unnecessary + copying and might indicate that the true nature of the data you + are dealing with is uncertain. If the data is '\0'-terminated 8-bit + data, use \l QCString; if it is unterminated (i.e. contains '\0's) + 8-bit data, use \l QByteArray; if it is text, use QString. + + Lists of strings are handled by the QStringList class. You can + split a string into a list of strings using QStringList::split(), + and join a list of strings into a single string with an optional + separator using QStringList::join(). You can obtain a list of + strings from a string list that contain a particular substring or + that match a particular \link qregexp.html regex\endlink using + QStringList::grep(). + + <b>Note for C programmers</b> + + Due to C++'s type system and the fact that QString is implicitly + shared, QStrings may be treated like ints or other simple base + types. For example: + + \code + QString boolToString( bool b ) + { + QString result; + if ( b ) + result = "True"; + else + result = "False"; + return result; + } + \endcode + + The variable, result, is an auto variable allocated on the stack. + When return is called, because we're returning by value, The copy + constructor is called and a copy of the string is returned. (No + actual copying takes place thanks to the implicit sharing, see + below.) + + Throughout Qt's source code you will encounter QString usages like + this: + \code + QString func( const QString& input ) + { + QString output = input; + // process output + return output; + } + \endcode + + The 'copying' of input to output is almost as fast as copying a + pointer because behind the scenes copying is achieved by + incrementing a reference count. QString (like all Qt's implicitly + shared classes) operates on a copy-on-write basis, only copying if + an instance is actually changed. + + If you wish to create a deep copy of a QString without losing any + Unicode information then you should use QDeepCopy. + + \sa QChar QCString QByteArray QConstString +*/ + +/*! \enum Qt::ComparisonFlags +\internal +*/ +/*! + \enum Qt::StringComparisonMode + + This enum type is used to set the string comparison mode when + searching for an item. It is used by QListBox, QListView and + QIconView, for example. We'll refer to the string being searched + as the 'target' string. + + \value CaseSensitive The strings must match case sensitively. + \value ExactMatch The target and search strings must match exactly. + \value BeginsWith The target string begins with the search string. + \value EndsWith The target string ends with the search string. + \value Contains The target string contains the search string. + + If you OR these flags together (excluding \c CaseSensitive), the + search criteria be applied in the following order: \c ExactMatch, + \c BeginsWith, \c EndsWith, \c Contains. + + Matching is case-insensitive unless \c CaseSensitive is set. \c + CaseSensitive may be OR-ed with any combination of the other + flags. + +*/ +Q_EXPORT QStringData *QString::shared_null = 0; +QT_STATIC_CONST_IMPL QString QString::null; +QT_STATIC_CONST_IMPL QChar QChar::null; +QT_STATIC_CONST_IMPL QChar QChar::replacement((ushort)0xfffd); +QT_STATIC_CONST_IMPL QChar QChar::byteOrderMark((ushort)0xfeff); +QT_STATIC_CONST_IMPL QChar QChar::byteOrderSwapped((ushort)0xfffe); +QT_STATIC_CONST_IMPL QChar QChar::nbsp((ushort)0x00a0); + +QStringData* QString::makeSharedNull() +{ + QString::shared_null = new QStringData; +#if defined( Q_OS_MAC ) + QString *that = const_cast<QString *>(&QString::null); + that->d = QString::shared_null; +#endif + return QString::shared_null; +} + +// Uncomment this to get some useful statistics. +// #define Q2HELPER(x) x + +#ifdef Q2HELPER +static int stat_construct_charstar=0; +static int stat_construct_charstar_size=0; +static int stat_construct_null=0; +static int stat_construct_int=0; +static int stat_construct_int_size=0; +static int stat_construct_ba=0; +static int stat_get_ascii=0; +static int stat_get_ascii_size=0; +static int stat_copy_on_write=0; +static int stat_copy_on_write_size=0; +static int stat_fast_copy=0; +Q_EXPORT void qt_qstring_stats() +{ + qDebug("construct_charstar = %d (%d chars)", stat_construct_charstar, stat_construct_charstar_size); + qDebug("construct_null = %d", stat_construct_null); + qDebug("construct_int = %d (%d chars)", stat_construct_int, stat_construct_int_size); + qDebug("construct_ba = %d", stat_construct_ba); + qDebug("get_ascii = %d (%d chars)", stat_get_ascii, stat_get_ascii_size); + qDebug("copy_on_write = %d (%d chars)", stat_copy_on_write, stat_copy_on_write_size); + qDebug("fast_copy = %d", stat_fast_copy); +} +#else +#define Q2HELPER(x) +#endif + +/*! + \fn QString::QString() + + Constructs a null string, i.e. both the length and data pointer + are 0. + + \sa isNull() +*/ + +/*! + Constructs a string of length one, containing the character \a ch. +*/ +QString::QString( QChar ch ) +{ + d = new QStringData( QT_ALLOC_QCHAR_VEC( 1 ), 1, 1 ); + d->unicode[0] = ch; +} + +/*! + Constructs an implicitly shared copy of \a s. This is very fast + since it only involves incrementing a reference count. +*/ +QString::QString( const QString &s ) : + d(s.d) +{ + Q2HELPER(stat_fast_copy++) + d->ref(); +} + +/*! + \internal + + Private function. + + Constructs a string with preallocated space for \a size characters. + + The string is empty. + + \sa isNull() +*/ + +QString::QString( int size, bool /*dummy*/ ) +{ + if ( size ) { + Q2HELPER(stat_construct_int++) + int l = size; + Q2HELPER(stat_construct_int_size+=l) + QChar* uc = QT_ALLOC_QCHAR_VEC( l ); + d = new QStringData( uc, 0, l ); + } else { + Q2HELPER(stat_construct_null++) + d = shared_null ? shared_null : (shared_null=new QStringData); + d->ref(); + } +} + +/*! + Constructs a string that is a deep copy of \a ba interpreted as a + classic C string. +*/ + +QString::QString( const QByteArray& ba ) +{ + Q2HELPER(stat_construct_ba++) + uint l; + QChar *uc = internalAsciiToUnicode(ba,&l); + d = new QStringData(uc,l,l); +} + +/*! + Constructs a string that is a deep copy of the first \a length + characters in the QChar array. + + If \a unicode and \a length are 0, then a null string is created. + + If only \a unicode is 0, the string is empty but has \a length + characters of space preallocated: QString expands automatically + anyway, but this may speed up some cases a little. We recommend + using the plain constructor and setLength() for this purpose since + it will result in more readable code. + + \sa isNull() setLength() +*/ + +QString::QString( const QChar* unicode, uint length ) +{ + if ( !unicode && !length ) { + d = shared_null ? shared_null : makeSharedNull(); + d->ref(); + } else { + QChar* uc = QT_ALLOC_QCHAR_VEC( length ); + if ( unicode ) + memcpy(uc, unicode, length*sizeof(QChar)); + d = new QStringData(uc,unicode ? length : 0,length); + } +} + +/*! + Constructs a string that is a deep copy of \a str, interpreted as + a classic C string. + + If \a str is 0, then a null string is created. + + This is a cast constructor, but it is perfectly safe: converting a + Latin1 const char* to QString preserves all the information. You + can disable this constructor by defining \c QT_NO_CAST_ASCII when + you compile your applications. You can also make QString objects + by using setLatin1(), fromLatin1(), fromLocal8Bit(), and + fromUtf8(). Or whatever encoding is appropriate for the 8-bit data + you have. + + \sa isNull() +*/ + +QString::QString( const char *str ) +{ + Q2HELPER(stat_construct_charstar++) + uint l; + QChar *uc = internalAsciiToUnicode(str,&l); + Q2HELPER(stat_construct_charstar_size+=l) + d = new QStringData(uc,l,l); +} + +/*! + \fn QString::~QString() + + Destroys the string and frees the string's data if this is the + last reference to the string. +*/ + + +/*! + Deallocates any space reserved solely by this QString. + + If the string does not share its data with another QString + instance, nothing happens; otherwise the function creates a new, + unique copy of this string. This function is called whenever the + string is modified. +*/ + +void QString::real_detach() +{ + setLength( length() ); +} + +void QString::deref() +{ + if ( d->deref() ) { + if ( d != shared_null ) + delete d; + d = 0; // helps debugging + } +} + +void QStringData::deleteSelf() +{ + delete this; +} + +/*! + \fn QString& QString::operator=( QChar c ) + + Sets the string to contain just the single character \a c. +*/ + +/*! + \fn QString& QString::operator=( char c ) + + \overload + + Sets the string to contain just the single character \a c. +*/ + +/*! + \overload + + Assigns a shallow copy of \a s to this string and returns a + reference to this string. This is very fast because the string + isn't actually copied. +*/ +QString &QString::operator=( const QString &s ) +{ + Q2HELPER(stat_fast_copy++) + s.d->ref(); + deref(); + d = s.d; + return *this; +} + +/*! + \overload + + Assigns a deep copy of \a cs, interpreted as a classic C string, + to this string and returns a reference to this string. +*/ +QString &QString::operator=( const QCString& cs ) +{ + return setLatin1(cs); +} + + +/*! + \overload + + Assigns a deep copy of \a str, interpreted as a classic C string + to this string and returns a reference to this string. + + If \a str is 0, then a null string is created. + + \sa isNull() +*/ +QString &QString::operator=( const char *str ) +{ + return setLatin1(str); +} + + +/*! + \fn bool QString::isNull() const + + Returns TRUE if the string is null; otherwise returns FALSE. A + null string is always empty. + + \code + QString a; // a.unicode() == 0, a.length() == 0 + a.isNull(); // TRUE, because a.unicode() == 0 + a.isEmpty(); // TRUE + \endcode + + \sa isEmpty(), length() +*/ + +/*! + \fn bool QString::isEmpty() const + + Returns TRUE if the string is empty, i.e. if length() == 0; + otherwise returns FALSE. Null strings are also empty. + + \code + QString a( "" ); + a.isEmpty(); // TRUE + a.isNull(); // FALSE + + QString b; + b.isEmpty(); // TRUE + b.isNull(); // TRUE + \endcode + + \sa isNull(), length() +*/ + +/*! + \fn uint QString::length() const + + Returns the length of the string. + + Null strings and empty strings have zero length. + + \sa isNull(), isEmpty() +*/ + +/*! + If \a newLen is less than the length of the string, then the + string is truncated at position \a newLen. Otherwise nothing + happens. + + \code + QString s = "truncate me"; + s.truncate( 5 ); // s == "trunc" + \endcode + + \sa setLength() +*/ + +void QString::truncate( uint newLen ) +{ + if ( newLen < d->len ) + setLength( newLen ); +} + +/*! + Ensures that at least \a newLen characters are allocated to the + string, and sets the length of the string to \a newLen. Any new + space allocated contains arbitrary data. + + If \a newLen is 0, then the string becomes empty, unless the + string is null, in which case it remains null. + + If it is not possible to allocate enough memory, the string + remains unchanged. + + This function always detaches the string from other references to + the same data. + + This function is useful for code that needs to build up a long + string and wants to avoid repeated reallocation. In this example, + we want to add to the string until some condition is true, and + we're fairly sure that size is big enough: + \code + QString result; + int resultLength = 0; + result.setLength( newLen ) // allocate some space + while ( ... ) { + result[resultLength++] = ... // fill (part of) the space with data + } + result.truncate[resultLength]; // and get rid of the undefined junk + \endcode + + If \a newLen is an underestimate, the worst that will happen is + that the loop will slow down. + + \sa truncate(), isNull(), isEmpty(), length() +*/ + +void QString::setLength( uint newLen ) +{ + if ( d->count != 1 || newLen > d->maxl || + ( newLen * 4 < d->maxl && d->maxl > 4 ) ) { + // detach, grow or shrink + Q2HELPER(stat_copy_on_write++) + Q2HELPER(stat_copy_on_write_size+=d->len) + uint newMax = computeNewMax( newLen ); + QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( nd ) { + uint len = QMIN( d->len, newLen ); + if ( d->unicode ) + memcpy( nd, d->unicode, sizeof(QChar)*len ); + deref(); + d = new QStringData( nd, newLen, newMax ); + } + } else { + d->len = newLen; + d->setDirty(); + } +} + +/*! + This function will return a string that replaces the lowest + numbered occurrence of \c %1, \c %2, ..., \c %9 with \a a. + + The \a fieldwidth value specifies the minimum amount of space that + \a a is padded to. A positive value will produce right-aligned + text, whereas a negative value will produce left-aligned text. + + \code + QString firstName( "Joe" ); + QString lastName( "Bloggs" ); + QString fullName; + fullName = QString( "First name is '%1', last name is '%2'" ) + .arg( firstName ) + .arg( lastName ); + + // fullName == First name is 'Joe', last name is 'Bloggs' + \endcode + + Note that using arg() to construct sentences as we've done in the + example above does not usually translate well into other languages + because sentence structure and word order often differ between + languages. + + If there is no place marker (\c %1 or \c %2, etc.), a warning + message (qWarning()) is output and the text is appended at the + end of the string. We recommend that the correct number of place + markers is always used in production code. +*/ +QString QString::arg( const QString& a, int fieldwidth ) const +{ + int pos, len; + QString r = *this; + + if ( !findArg( pos, len ) ) { + qWarning( "QString::arg(): Argument missing: %s, %s", + latin1(), a.latin1() ); + // Make sure the text at least appears SOMEWHERE + r += ' '; + pos = r.length(); + len = 0; + } + + r.replace( pos, len, a ); + if ( fieldwidth < 0 ) { + QString s; + while ( (uint)-fieldwidth > a.length() ) { + s += ' '; + fieldwidth++; + } + r.insert( pos + a.length(), s ); + } else if ( fieldwidth ) { + QString s; + while ( (uint)fieldwidth > a.length() ) { + s += ' '; + fieldwidth--; + } + r.insert( pos, s ); + } + + return r; +} + + +/*! + \overload + + The \a fieldwidth value specifies the minimum amount of space that + \a a is padded to. A positive value will produce a right-aligned + number, whereas a negative value will produce a left-aligned + number. + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. + + \code + QString str; + str = QString( "Decimal 63 is %1 in hexadecimal" ) + .arg( 63, 0, 16 ); + // str == "Decimal 63 is 3f in hexadecimal" + \endcode +*/ +QString QString::arg( long a, int fieldwidth, int base ) const +{ + return arg( QString::number(a, base), fieldwidth ); +} + +/*! + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. +*/ +QString QString::arg( ulong a, int fieldwidth, int base ) const +{ + return arg( QString::number(a, base), fieldwidth ); +} + +/*! + \fn QString QString::arg( int a, int fieldwidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. +*/ + +/*! + \fn QString QString::arg( uint a, int fieldwidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. +*/ + +/*! + \fn QString QString::arg( short a, int fieldwidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. +*/ + +/*! + \fn QString QString::arg( ushort a, int fieldwidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. +*/ + + +/*! + \overload + + \a a is assumed to be in the Latin1 character set. +*/ +QString QString::arg( char a, int fieldwidth ) const +{ + QString c; + c += a; + return arg( c, fieldwidth ); +} + +/*! + \overload +*/ +QString QString::arg( QChar a, int fieldwidth ) const +{ + QString c; + c += a; + return arg( c, fieldwidth ); +} + +/*! + \overload + + \target arg-formats + + Argument \a a is formatted according to the \a fmt format specified, + which is 'g' by default and can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \code + double d = 12.34; + QString ds = QString( "'E' format, precision 3, gives %1" ) + .arg( d, 0, 'E', 3 ); + // ds == "1.234E+001" + \endcode +*/ +QString QString::arg( double a, int fieldwidth, char fmt, int prec ) const +{ + return arg( QString::number( a, fmt, prec ), fieldwidth ); +} + + +/* + Just 1-digit arguments. +*/ +bool QString::findArg( int& pos, int& len ) const +{ + char lowest=0; + register const QChar *uc = d->unicode; + const uint l = length(); + for (uint i = 0; i < l; i++) { + if ( uc[i] == '%' && i+1<l ) { + QChar dig = uc[i+1]; + if ( dig >= '0' && dig <= '9' ) { + if ( !lowest || dig < lowest ) { + lowest = dig; + pos = i; + len = 2; + } + } + } + } + return lowest != 0; +} + +/*! + Safely builds a formatted string from the format string \a cformat + and an arbitrary list of arguments. The format string supports all + the escape sequences of printf() in the standard C library. + + The %s escape sequence expects a utf8() encoded string. The format + string \e cformat is expected to be in latin1. If you need a + Unicode format string, use arg() instead. For typesafe string + building, with full Unicode support, you can use QTextOStream like + this: + + \code + QString str; + QString s = ...; + int x = ...; + QTextOStream( &str ) << s << " : " << x; + \endcode + + For \link QObject::tr() translations,\endlink especially if the + strings contains more than one escape sequence, you should + consider using the arg() function instead. This allows the order + of the replacements to be controlled by the translator, and has + Unicode support. + + \sa arg() +*/ + +#ifndef QT_NO_SPRINTF +QString &QString::sprintf( const char* cformat, ... ) +{ + va_list ap; + va_start( ap, cformat ); + + if ( !cformat || !*cformat ) { + // Qt 1.x compat + *this = fromLatin1( "" ); + return *this; + } + QString format = fromLatin1( cformat ); + + QRegExp escape( "%#?0?-? ?\\+?'?[0-9*]*\\.?[0-9*]*h?l?L?q?Z?" ); + QString result; + uint last = 0; + int pos; + int len = 0; + + for (;;) { + pos = escape.search( format, last ); + len = escape.matchedLength(); + // Non-escaped text + if ( pos > (int)last ) + result += format.mid( last, pos - last ); + if ( pos < 0 ) { + // The rest + if ( last < format.length() ) + result += format.mid( last ); + break; + } + last = pos + len + 1; + + // Escape + QString f = format.mid( pos, len ); + uint width, decimals; + int params = 0; + int wpos = f.find('*'); + if ( wpos >= 0 ) { + params++; + width = va_arg( ap, int ); + if ( f.find('*', wpos + 1) >= 0 ) { + decimals = va_arg( ap, int ); + params++; + } else { + decimals = 0; + } + } else { + decimals = width = 0; + } + QString replacement; + if ( format[pos + len] == 's' || format[pos + len] == 'S' || + format[pos + len] == 'c' ) + { + bool rightjust = ( f.find('-') < 0 ); + // %-5s really means left adjust in sprintf + + if ( wpos < 0 ) { + QRegExp num( fromLatin1("[0-9]+") ); + int p = num.search( f ); + int nlen = num.matchedLength(); + int q = f.find( '.' ); + if ( q < 0 || (p < q && p >= 0) ) + width = f.mid( p, nlen ).toInt(); + if ( q >= 0 ) { + p = num.search( f, q ); + // "decimals" is used to specify string truncation + if ( p >= 0 ) + decimals = f.mid( p, nlen ).toInt(); + } + } + + if ( format[pos + len] == 's' ) { + QString s = QString::fromUtf8( va_arg(ap, char*) ); + replacement = ( decimals <= 0 ) ? s : s.left( decimals ); + } else { + int ch = va_arg(ap, int); + replacement = QChar((ushort)ch); + } + if ( replacement.length() < width ) { + replacement = rightjust + ? replacement.rightJustify(width) + : replacement.leftJustify(width); + } + } else if ( format[pos+len] == '%' ) { + replacement = '%'; + } else if ( format[pos+len] == 'n' ) { + int* n = va_arg(ap, int*); + *n = result.length(); + } else { + char in[64], out[330]; + strncpy(in,f.latin1(),63); + out[0] = '\0'; + char fch = format[pos+len].latin1(); + in[f.length()] = fch; + switch ( fch ) { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + { + int value = va_arg( ap, int ); + switch ( params ) { + case 0: + ::sprintf( out, in, value ); + break; + case 1: + ::sprintf( out, in, width, value ); + break; + case 2: + ::sprintf( out, in, width, decimals, value ); + } + } + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + { + double value = va_arg( ap, double ); + switch ( params ) { + case 0: + ::sprintf( out, in, value ); + break; + case 1: + ::sprintf( out, in, width, value ); + break; + case 2: + ::sprintf( out, in, width, decimals, value ); + } + } + break; + case 'p': + { + void* value = va_arg( ap, void * ); + switch ( params ) { + case 0: + ::sprintf( out, in, value ); + break; + case 1: + ::sprintf( out, in, width, value ); + break; + case 2: + ::sprintf( out, in, width, decimals, value ); + } + } + } + replacement = fromLatin1( out ); + } + result += replacement; + } + *this = result; + + va_end( ap ); + return *this; +} +#endif + +/*! + Fills the string with \a len characters of value \a c, and returns + a reference to the string. + + If \a len is negative (the default), the current string length is + used. + + \code + QString str; + str.fill( 'g', 5 ); // string == "ggggg" + \endcode +*/ + +QString& QString::fill( QChar c, int len ) +{ + if ( len < 0 ) + len = length(); + if ( len == 0 ) { + *this = ""; + } else { + deref(); + QChar * nd = QT_ALLOC_QCHAR_VEC( len ); + d = new QStringData(nd,len,len); + while (len--) *nd++ = c; + } + return *this; +} + + +/*! + \fn QString QString::copy() const + + \obsolete + + In Qt 2.0 and later, all calls to this function are needless. Just + remove them. +*/ + +/*! + \overload + + Finds the first occurrence of the character \a c, starting at + position \a index. If \a index is -1, the search starts at the + last character; if -2, at the next to last character and so on. + (See findRev() for searching backwards.) + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + Returns the position of \a c or -1 if \a c could not be found. +*/ + +int QString::find( QChar c, int index, bool cs ) const +{ + const uint l = length(); + if ( index < 0 ) + index += l; + if ( (uint)index >= l ) + return -1; + register const QChar *uc = unicode()+index; + const QChar *end = unicode() + l; + if ( cs ) { + while ( uc < end && *uc != c ) + uc++; + } else { + c = ::lower( c ); + while ( uc < end && ::lower( *uc ) != c ) + uc++; + } + if ( uint(uc - unicode()) >= l ) + return -1; + return (int)(uc - unicode()); +} + +/* an implementation of the Boyer-Moore search algorithm +*/ + +/* initializes the skiptable to know haw far ahead we can skip on a wrong match +*/ +static void bm_init_skiptable( const QString &pattern, uint *skiptable, bool cs ) +{ + int i = 0; + register uint *st = skiptable; + int l = pattern.length(); + while ( i++ < 0x100/8 ) { + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + } + const QChar *uc = pattern.unicode(); + if ( cs ) { + while( l-- ) { + skiptable[ uc->cell() ] = l; + uc++; + } + } else { + while( l-- ) { + skiptable[ ::lower( *uc ).cell() ] = l; + uc++; + } + } +} + +static int bm_find( const QString &str, int index, const QString &pattern, uint *skiptable, bool cs ) +{ + const uint l = str.length(); + if ( pattern.isEmpty() ) + return index > (int)l ? -1 : index; + + const QChar *uc = str.unicode(); + const QChar *puc = pattern.unicode(); + const uint pl = pattern.length(); + const uint pl_minus_one = pl - 1; + + register const QChar *current = uc + index + pl_minus_one; + const QChar *end = uc + l; + if ( cs ) { + while( current < end ) { + uint skip = skiptable[ current->cell() ]; + if ( !skip ) { + // possible match + while( skip < pl ) { + if ( *(current - skip ) != puc[pl_minus_one-skip] ) + break; + skip++; + } + if ( skip > pl_minus_one ) { // we have a match + return (current - uc) - skip + 1; + } + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if ( skiptable[ (current-skip)->cell() ] == pl ) + skip = pl - skip; + else + skip = 1; + } + current += skip; + } + } else { + while( current < end ) { + uint skip = skiptable[ ::lower( *current ).cell() ]; + if ( !skip ) { + // possible match + while( skip < pl ) { + if ( ::lower( *(current - skip) ) != ::lower( puc[pl_minus_one-skip] ) ) + break; + skip++; + } + if ( skip > pl_minus_one ) // we have a match + return (current - uc) - skip + 1; + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if ( skiptable[ ::lower( (current - skip)->cell() ) ] == pl ) + skip = pl - skip; + else + skip = 1; + } + current += skip; + } + } + // not found + return -1; +} + + +#define REHASH( a ) \ + if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \ + hashHaystack -= (a) << sl_minus_1; \ + hashHaystack <<= 1 + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index. If \a index is -1, the search starts at the + last character, if it is -2, at the next to last character and so + on. (See findRev() for searching backwards.) + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + Returns the position of \a str or -1 if \a str could not be found. +*/ + +int QString::find( const QString& str, int index, bool cs ) const +{ + const uint l = length(); + const uint sl = str.length(); + if ( index < 0 ) + index += l; + if ( sl + index > l ) + return -1; + if ( !sl ) + return index; + + if ( sl == 1 ) + return find( *str.unicode(), index, cs ); + + // we use the Boyer-Moore algorithm in cases where the overhead + // for the hash table should pay off, otherwise we use a simple + // hash function + if ( l > 500 && sl > 5 ) { + uint skiptable[0x100]; + bm_init_skiptable( str, skiptable, cs ); + return bm_find( *this, index, str, skiptable, cs ); + } + + /* + We use some hashing for efficiency's sake. Instead of + comparing strings, we compare the hash value of str with that of + a part of this QString. Only if that matches, we call ucstrncmp + or ucstrnicmp. + */ + const QChar* needle = str.unicode(); + const QChar* haystack = unicode() + index; + const QChar* end = unicode() + (l-sl); + const uint sl_minus_1 = sl-1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + needle[i].unicode() ); + hashHaystack = ((hashHaystack<<1) + haystack[i].unicode() ); + } + hashHaystack -= (haystack+sl_minus_1)->unicode(); + + while ( haystack <= end ) { + hashHaystack += (haystack+sl_minus_1)->unicode(); + if ( hashHaystack == hashNeedle + && ucstrncmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + + REHASH( haystack->unicode() ); + ++haystack; + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + ::lower( needle[i].unicode() ).unicode() ); + hashHaystack = ((hashHaystack<<1) + + ::lower( haystack[i].unicode() ).unicode() ); + } + + hashHaystack -= ::lower(*(haystack+sl_minus_1)).unicode(); + while ( haystack <= end ) { + hashHaystack += ::lower(*(haystack+sl_minus_1)).unicode(); + if ( hashHaystack == hashNeedle + && ucstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + + REHASH( ::lower(*haystack).unicode() ); + ++haystack; + } + } + return -1; +} + +/*! + \fn int QString::findRev( const char* str, int index ) const + + Equivalent to findRev(QString(\a str), \a index). +*/ + +/*! + \fn int QString::find( const char* str, int index ) const + + \overload + + Equivalent to find(QString(\a str), \a index). +*/ + +/*! + \overload + + Finds the first occurrence of the character \a c, starting at + position \a index and searching backwards. If the index is -1, the + search starts at the last character, if it is -2, at the next to + last character and so on. + + Returns the position of \a c or -1 if \a c could not be found. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + \code + QString string( "bananas" ); + int i = string.findRev( 'a' ); // i == 5 + \endcode +*/ + +int QString::findRev( QChar c, int index, bool cs ) const +{ + const uint l = length(); + if ( index < 0 ) + index += l; + if ( (uint)index >= l ) + return -1; + const QChar *end = unicode(); + register const QChar *uc = end + index; + if ( cs ) { + while ( uc >= end && *uc != c ) + uc--; + } else { + c = ::lower( c ); + while ( uc >= end && ::lower( *uc ) != c ) + uc--; + } + return uc - end; +} + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index and searching backwards. If the index is -1, the + search starts at the last character, if it is -2, at the next to + last character and so on. + + Returns the position of \a str or -1 if \a str could not be found. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + \code + QString string("bananas"); + int i = string.findRev( "ana" ); // i == 3 + \endcode +*/ + +int QString::findRev( const QString& str, int index, bool cs ) const +{ + /* + See QString::find() for explanations. + */ + const uint l = length(); + if ( index < 0 ) + index += l; + const uint sl = str.length(); + int delta = l-sl; + if ( index < 0 || index > (int)l || delta < 0 ) + return -1; + if ( index > delta ) + index = delta; + + if ( sl == 1 ) + return findRev( *str.unicode(), index, cs ); + + const QChar* needle = str.unicode(); + const QChar* haystack = unicode() + index; + const QChar* end = unicode(); + const uint sl_minus_1 = sl-1; + const QChar* n = needle+sl_minus_1; + const QChar* h = haystack+sl_minus_1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + (n-i)->unicode() ); + hashHaystack = ((hashHaystack<<1) + (h-i)->unicode() ); + } + hashHaystack -= haystack->unicode(); + + while ( haystack >= end ) { + hashHaystack += haystack->unicode(); + if ( hashHaystack == hashNeedle + && ucstrncmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + --haystack; + REHASH( (haystack+sl)->unicode() ); + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + ::lower( (n-i)->unicode() ).unicode() ); + hashHaystack = ((hashHaystack<<1) + + ::lower( (h-i)->unicode() ).unicode() ); + } + hashHaystack -= ::lower(*haystack).unicode(); + + while ( haystack >= end ) { + hashHaystack += ::lower(*haystack).unicode(); + if ( hashHaystack == hashNeedle + && ucstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + --haystack; + REHASH( ::lower(*(haystack+sl)).unicode() ); + } + } + return -1; +} + +#undef REHASH + +/*! + \enum QString::SectionFlags + + \value SectionDefault Empty fields are counted, leading and + trailing separators are not included, and the separator is + compared case sensitively. + + \value SectionSkipEmpty Treat empty fields as if they don't exist, + i.e. they are not considered as far as \e start and \e end are + concerned. + + \value SectionIncludeLeadingSep Include the leading separator (if + any) in the result string. + + \value SectionIncludeTrailingSep Include the trailing separator + (if any) in the result string. + + \value SectionCaseInsensitiveSeps Compare the separator + case-insensitively. + + Any of the last four values can be OR-ed together to form a flag. + + \sa section() +*/ + +/*! + \fn QString QString::section( QChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + character, \a sep. The returned string consists of the fields from + position \a start to position \a end inclusive. If \a end is not + specified, all fields from position \a start to the end of the + string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + QString csv( "forename,middlename,surname,phone" ); + QString s = csv.section( ',', 2, 2 ); // s == "surname" + + QString path( "/usr/local/bin/myapp" ); // First field is empty + QString s = path.section( '/', 3, 4 ); // s == "bin/myapp" + QString s = path.section( '/', 3, 3, SectionSkipEmpty ); // s == "myapp" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + QString csv( "forename,middlename,surname,phone" ); + QString s = csv.section( ',', -3, -2 ); // s == "middlename,surname" + + QString path( "/usr/local/bin/myapp" ); // First field is empty + QString s = path.section( '/', -1 ); // s == "myapp" + \endcode + + \sa QStringList::split() +*/ + +/*! + \overload + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + string, \a sep. The returned string consists of the fields from + position \a start to position \a end inclusive. If \a end is not + specified, all fields from position \a start to the end of the + string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + QString data( "forename**middlename**surname**phone" ); + QString s = data.section( "**", 2, 2 ); // s == "surname" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + QString data( "forename**middlename**surname**phone" ); + QString s = data.section( "**", -3, -2 ); // s == "middlename**surname" + \endcode + + \sa QStringList::split() +*/ + +QString QString::section( const QString &sep, int start, int end, int flags ) const +{ + const QChar *uc = unicode(); + if ( !uc ) + return QString(); + QString _sep = (flags & SectionCaseInsensitiveSeps) ? sep.lower() : sep; + const QChar *uc_sep = _sep.unicode(); + if(!uc_sep) + return QString(); + bool match = FALSE, last_match = TRUE; + + //find start + int n = length(), sep_len = _sep.length(); + const QChar *begin = start < 0 ? uc + n : uc; + while(start) { + match = FALSE; + int c = 0; + for(const QChar *tmp = start < 0 ? begin - sep_len : begin; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if(flags & SectionCaseInsensitiveSeps) { + if( ::lower( *tmp ) != *(uc_sep + c)) + break; + } else { + if( *tmp != *(uc_sep + c) ) + break; + } + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + if(start > 0 && (flags & SectionSkipEmpty) && match && last_match) + match = FALSE; + last_match = match; + + if(start < 0) { + if(match) { + begin -= sep_len; + if(!++start) + break; + } else { + if(start == -1 && begin == uc) + break; + begin--; + } + } else { + if(match) { + if(!--start) + break; + begin += sep_len; + } else { + if(start == 1 && begin == uc + n) + break; + begin++; + } + } + if(begin > uc + n || begin < uc) + return QString(); + } + if(match && !(flags & SectionIncludeLeadingSep)) + begin+=sep_len; + if(begin > uc + n || begin < uc) + return QString(); + + //now find last + match = FALSE; + const QChar *last = end < 0 ? uc + n : uc; + if(end == -1) { + int c = 0; + for(const QChar *tmp = end < 0 ? last - sep_len : last; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if(flags & SectionCaseInsensitiveSeps) { + if( ::lower( *tmp ) != *(uc_sep + c)) + break; + } else { + if( *tmp != *(uc_sep + c) ) + break; + } + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + } else { + end++; + last_match = TRUE; + while(end) { + match = FALSE; + int c = 0; + for(const QChar *tmp = end < 0 ? last - sep_len : last; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if(flags & SectionCaseInsensitiveSeps) { + if( ::lower( *tmp ) != *(uc_sep + c)) + break; + } else { + if( *tmp != *(uc_sep + c) ) + break; + } + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + if(end > 0 && (flags & SectionSkipEmpty) && match && last_match) + match = FALSE; + last_match = match; + + if(end < 0) { + if(match) { + if(!++end) + break; + last -= sep_len; + } else { + last--; + } + } else { + if(match) { + last += sep_len; + if(!--end) + break; + } else { + last++; + } + } + if(last >= uc + n) { + last = uc + n; + break; + } else if(last < uc) { + return QString(); + } + } + } + if(match && !(flags & SectionIncludeTrailingSep)) + last -= sep_len; + if(last < uc || last > uc + n || begin >= last) + return QString(); + + //done + return QString(begin, last - begin); +} + +#ifndef QT_NO_REGEXP +class section_chunk { +public: + section_chunk(int l, QString s) { length = l; string = s; } + int length; + QString string; +}; +/*! + \overload + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + regular expression, \a reg. The returned string consists of the + fields from position \a start to position \a end inclusive. If \a + end is not specified, all fields from position \a start to the end + of the string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + QString line( "forename\tmiddlename surname \t \t phone" ); + QRegExp sep( "\s+" ); + QString s = line.section( sep, 2, 2 ); // s == "surname" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + QString line( "forename\tmiddlename surname \t \t phone" ); + QRegExp sep( "\\s+" ); + QString s = line.section( sep, -3, -2 ); // s == "middlename surname" + \endcode + + \warning Using this QRegExp version is much more expensive than + the overloaded string and character versions. + + \sa QStringList::split() simplifyWhiteSpace() +*/ + +QString QString::section( const QRegExp ®, int start, int end, int flags ) const +{ + const QChar *uc = unicode(); + if(!uc) + return QString(); + + QRegExp sep(reg); + sep.setCaseSensitive(!(flags & SectionCaseInsensitiveSeps)); + + QPtrList<section_chunk> l; + l.setAutoDelete(TRUE); + int n = length(), m = 0, last_m = 0, last = 0, last_len = 0; + + while( ( m = sep.search( *this, m ) ) != -1 ) { + l.append(new section_chunk(last_len, QString(uc + last_m, m - last_m))); + last_m = m; + last_len = sep.matchedLength(); + if((m += sep.matchedLength()) >= n) { + last = 1; + break; + } + } + if(!last) + l.append(new section_chunk(last_len, QString(uc + last_m, n - last_m))); + + if(start < 0) + start = l.count() + start; + if(end == -1) + end = l.count(); + else if(end < 0) + end = l.count() + end; + + int i = 0; + QString ret; + for ( section_chunk *chk=l.first(); chk; chk=l.next(), i++ ) { + if((flags & SectionSkipEmpty) && chk->length == (int)chk->string.length()) { + if(i <= start) + start++; + end++; + } + if(i == start) { + ret = (flags & SectionIncludeLeadingSep) ? chk->string : chk->string.mid(chk->length); + } else if(i > start) { + ret += chk->string; + } + if(i == end) { + if((chk=l.next()) && flags & SectionIncludeTrailingSep) + ret += chk->string.left(chk->length); + break; + } + } + return ret; +} +#endif + +/*! + \fn QString QString::section( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + \overload +*/ + +/*! + \fn QString QString::section( const char *sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + \overload +*/ + + +/*! + Returns the number of times the character \a c occurs in the + string. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + \code + QString string( "Trolltech and Qt" ); + int i = string.contains( 't', FALSE ); // i == 3 + \endcode +*/ + +int QString::contains( QChar c, bool cs ) const +{ + int count = 0; + const QChar *uc = unicode(); + if ( !uc ) + return 0; + int n = length(); + if ( cs ) { + while ( n-- ) + if ( *uc++ == c ) + count++; + } else { + c = ::lower( c ); + while ( n-- ) { + if ( ::lower( *uc ) == c ) + count++; + uc++; + } + } + return count; +} + +/*! + \overload + + Returns the number of times the string \a str occurs in the string. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. +*/ +int QString::contains( const char* str, bool cs ) const +{ + return contains( QString(str), cs ); +} + +/*! + \fn int QString::contains( char c, bool cs ) const + + \overload +*/ + +/*! + \fn int QString::find( char c, int index, bool cs ) const + + \overload + + Find character \a c starting from position \a index. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. +*/ + +/*! + \fn int QString::findRev( char c, int index, bool cs ) const + + \overload + + Find character \a c starting from position \a index and working + backwards. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. +*/ + +/*! + \overload + + Returns the number of times \a str occurs in the string. + + If \a cs is TRUE, the search is case sensitive; otherwise the + search is case insensitive. + + This function counts overlapping strings, so in the example below, + there are two instances of "ana" in "bananas". + + \code + QString str( "bananas" ); + int i = str.contains( "ana" ); // i == 2 + \endcode + + \sa findRev() +*/ + +int QString::contains( const QString &str, bool cs ) const +{ + if ( isNull() ) + return 0; + int count = 0; + uint skiptable[0x100]; + bm_init_skiptable( str, skiptable, cs ); + int i = -1; + // use boyer-moore for the ultimate speed experience + while ( ( i = bm_find( *this, i+1, str, skiptable, cs ) ) != -1 ) + count++; + return count; +} + +/*! + Returns a substring that contains the \a len leftmost characters + of the string. + + The whole string is returned if \a len exceeds the length of the + string. + + \code + QString s = "Pineapple"; + QString t = s.left( 4 ); // t == "Pine" + \endcode + + \sa right(), mid(), isEmpty() +*/ + +QString QString::left( uint len ) const +{ + if ( isEmpty() ) { + return QString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else if ( len >= length() ) { + return *this; + } else { + QString s( len, TRUE ); + memcpy( s.d->unicode, d->unicode, len * sizeof(QChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string that contains the \a len rightmost characters of + the string. + + If \a len is greater than the length of the string then the whole + string is returned. + + \code + QString string( "Pineapple" ); + QString t = string.right( 5 ); // t == "apple" + \endcode + + \sa left(), mid(), isEmpty() +*/ + +QString QString::right( uint len ) const +{ + if ( isEmpty() ) { + return QString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else { + uint l = length(); + if ( len >= l ) + return *this; + QString s( len, TRUE ); + memcpy( s.d->unicode, d->unicode+(l-len), len*sizeof(QChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string that contains the \a len characters of this + string, starting at position \a index. + + Returns a null string if the string is empty or \a index is out of + range. Returns the whole string from \a index if \a index + \a len + exceeds the length of the string. + + \code + QString s( "Five pineapples" ); + QString t = s.mid( 5, 4 ); // t == "pine" + \endcode + + \sa left(), right() +*/ + +QString QString::mid( uint index, uint len ) const +{ + uint slen = length(); + if ( isEmpty() || index >= slen ) { + return QString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else { + if ( len > slen-index ) + len = slen - index; + if ( index == 0 && len == slen ) + return *this; + register const QChar *p = unicode()+index; + QString s( len, TRUE ); + memcpy( s.d->unicode, p, len * sizeof(QChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string of length \a width that contains this string + padded by the \a fill character. + + If \a truncate is FALSE and the length of the string is more than + \a width, then the returned string is a copy of the string. + + If \a truncate is TRUE and the length of the string is more than + \a width, then any characters in a copy of the string after length + \a width are removed, and the copy is returned. + + \code + QString s( "apple" ); + QString t = s.leftJustify( 8, '.' ); // t == "apple..." + \endcode + + \sa rightJustify() +*/ + +QString QString::leftJustify( uint width, QChar fill, bool truncate ) const +{ + QString result; + int len = length(); + int padlen = width - len; + if ( padlen > 0 ) { + result.setLength(len+padlen); + if ( len ) + memcpy( result.d->unicode, unicode(), sizeof(QChar)*len ); + QChar* uc = result.d->unicode + len; + while (padlen--) + *uc++ = fill; + } else { + if ( truncate ) + result = left( width ); + else + result = *this; + } + return result; +} + +/*! + Returns a string of length \a width that contains the \a fill + character followed by the string. + + If \a truncate is FALSE and the length of the string is more than + \a width, then the returned string is a copy of the string. + + If \a truncate is TRUE and the length of the string is more than + \a width, then the resulting string is truncated at position \a + width. + + \code + QString string( "apple" ); + QString t = string.rightJustify( 8, '.' ); // t == "...apple" + \endcode + + \sa leftJustify() +*/ + +QString QString::rightJustify( uint width, QChar fill, bool truncate ) const +{ + QString result; + int len = length(); + int padlen = width - len; + if ( padlen > 0 ) { + result.setLength( len+padlen ); + QChar* uc = result.d->unicode; + while (padlen--) + *uc++ = fill; + if ( len ) + memcpy( uc, unicode(), sizeof(QChar)*len ); + } else { + if ( truncate ) + result = left( width ); + else + result = *this; + } + return result; +} + +/*! + Returns a lowercase copy of the string. + + \code + QString string( "TROlltECH" ); + str = string.lower(); // str == "trolltech" + \endcode + + \sa upper() +*/ + +QString QString::lower() const +{ + QString s(*this); + int l=length(); + if ( l ) { + s.real_detach(); // could do this only when we find a change + register QChar *p=s.d->unicode; + if ( p ) { + while ( l-- ) { + *p = ::lower( *p ); + p++; + } + } + } + return s; +} + +/*! + Returns an uppercase copy of the string. + + \code + QString string( "TeXt" ); + str = string.upper(); // t == "TEXT" + \endcode + + \sa lower() +*/ + +QString QString::upper() const +{ + QString s(*this); + int l=length(); + if ( l ) { + s.real_detach(); // could do this only when we find a change + register QChar *p=s.d->unicode; + if ( p ) { + while ( l-- ) { + *p = ::upper( *p ); + p++; + } + } + } + return s; +} + + +/*! + Returns a string that has whitespace removed from the start and + the end. + + Whitespace means any character for which QChar::isSpace() returns + TRUE. This includes Unicode characters with decimal values 9 + (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR) and 32 (Space), and may + also include other Unicode characters. + + \code + QString string = " white space "; + QString s = string.stripWhiteSpace(); // s == "white space" + \endcode + + \sa simplifyWhiteSpace() +*/ + +QString QString::stripWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return *this; + register const QChar *s = unicode(); + if ( !s->isSpace() && !s[length()-1].isSpace() ) + return *this; + + int start = 0; + int end = length() - 1; + while ( start<=end && s[start].isSpace() ) // skip white space from start + start++; + if ( start <= end ) { // only white space + while ( end && s[end].isSpace() ) // skip white space from end + end--; + } + int l = end - start + 1; + if ( l <= 0 ) + return QString::fromLatin1(""); + + QString result( l, TRUE ); + memcpy( result.d->unicode, &s[start], sizeof(QChar)*l ); + result.d->len = l; + return result; +} + + +/*! + Returns a string that has whitespace removed from the start and + the end, and which has each sequence of internal whitespace + replaced with a single space. + + Whitespace means any character for which QChar::isSpace() returns + TRUE. This includes Unicode characters with decimal values 9 + (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR), and 32 (Space). + + \code + QString string = " lots\t of\nwhite space "; + QString t = string.simplifyWhiteSpace(); + // t == "lots of white space" + \endcode + + \sa stripWhiteSpace() +*/ + +QString QString::simplifyWhiteSpace() const +{ + if ( isEmpty() ) + return *this; + QString result; + result.setLength( length() ); + const QChar *from = unicode(); + const QChar *fromend = from+length(); + int outc=0; + QChar *to = result.d->unicode; + for (;;) { + while ( from!=fromend && from->isSpace() ) + from++; + while ( from!=fromend && !from->isSpace() ) + to[outc++] = *from++; + if ( from!=fromend ) + to[outc++] = ' '; + else + break; + } + if ( outc > 0 && to[outc-1] == ' ' ) + outc--; + result.truncate( outc ); + return result; +} + + +/*! + Inserts \a s into the string at position \a index. + + If \a index is beyond the end of the string, the string is + extended with spaces to length \a index and \a s is then appended + and returns a reference to the string. + + \code + QString string( "I like fish" ); + str = string.insert( 2, "don't " ); + // str == "I don't like fish" + \endcode + + \sa remove(), replace() +*/ + +QString &QString::insert( uint index, const QString &s ) +{ + // the sub function takes care of &s == this case. + return insert( index, s.unicode(), s.length() ); +} + +/*! + \overload + + Inserts the character in \a s into the string at position \a index + \a len number of times and returns a reference to the string. +*/ + +QString &QString::insert( uint index, const QChar* s, uint len ) +{ + if ( len == 0 ) + return *this; + uint olen = length(); + int nlen = olen + len; + + if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { + // Part of me - take a copy. + QChar *tmp = QT_ALLOC_QCHAR_VEC( len ); + memcpy(tmp,s,len*sizeof(QChar)); + insert(index,tmp,len); + QT_DELETE_QCHAR_VEC( tmp ); + return *this; + } + + if ( index >= olen ) { // insert after end of string + setLength( len + index ); + int n = index - olen; + QChar* uc = d->unicode+olen; + while (n--) + *uc++ = ' '; + memcpy( d->unicode+index, s, sizeof(QChar)*len ); + } else { // normal insert + setLength( nlen ); + memmove( d->unicode + index + len, unicode() + index, + sizeof(QChar) * (olen - index) ); + memcpy( d->unicode + index, s, sizeof(QChar) * len ); + } + return *this; +} + +/*! + \overload + + Insert \a c into the string at position \a index and returns a + reference to the string. + + If \a index is beyond the end of the string, the string is + extended with spaces (ASCII 32) to length \a index and \a c is + then appended. +*/ + +QString &QString::insert( uint index, QChar c ) // insert char +{ + QString s( c ); + return insert( index, s ); +} + +/*! + \fn QString& QString::insert( uint index, char c ) + + \overload + + Insert character \a c at position \a index. +*/ + +/*! + \fn QString &QString::prepend( const QString &s ) + + Inserts \a s at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a s). + + \code + QString string = "42"; + string.prepend( "The answer is " ); + // string == "The answer is 42" + \endcode + + \sa insert() +*/ + +/*! + \fn QString& QString::prepend( char ch ) + + \overload + + Inserts \a ch at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a ch). + + \sa insert() +*/ + +/*! + \fn QString& QString::prepend( QChar ch ) + + \overload + + Inserts \a ch at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a ch). + + \sa insert() +*/ + +/*! \fn QString& QString::prepend( const QByteArray &s ) + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() + */ + +/*! + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() + */ +QString &QString::prepend( const char *s ) +{ + return insert( 0, QString(s) ); +} + +/*! + Removes \a len characters from the string starting at position \a + index, and returns a reference to the string. + + If \a index is beyond the length of the string, nothing happens. + If \a index is within the string, but \a index + \a len is beyond + the end of the string, the string is truncated at position \a + index. + + \code + QString string( "Montreal" ); + string.remove( 1, 4 ); // string == "Meal" + \endcode + + \sa insert(), replace() +*/ + +QString &QString::remove( uint index, uint len ) +{ + uint olen = length(); + if ( index >= olen ) { + // range problems + } else if ( index + len >= olen ) { // index ok + setLength( index ); + } else if ( len != 0 ) { + real_detach(); + memmove( d->unicode+index, d->unicode+index+len, + sizeof(QChar)*(olen-index-len) ); + setLength( olen-len ); + } + return *this; +} + +/*! \overload + + Removes every occurrence of the character \a c in the string. + Returns a reference to the string. + + This is the same as replace(\a c, ""). +*/ +QString &QString::remove( QChar c ) +{ + int i = 0; + while ( i < (int) length() ) { + if ( constref(i) == c ) { + remove( i, 1 ); + } else { + i++; + } + } + return *this; +} + +/*! \overload + + \fn QString &QString::remove( char c ) + + Removes every occurrence of the character \a c in the string. + Returns a reference to the string. + + This is the same as replace(\a c, ""). +*/ + +/*! \overload + + Removes every occurrence of \a str in the string. Returns a + reference to the string. + + This is the same as replace(\a str, ""). +*/ +QString &QString::remove( const QString & str ) +{ + int index = 0; + if ( !str.isEmpty() ) { + while ( (index = find(str, index)) != -1 ) + remove( index, str.length() ); + } + return *this; +} + +/*! \overload + + Replaces every occurrence of \a c1 with the char \a c2. + Returns a reference to the string. +*/ +QString &QString::replace( QChar c1, QChar c2 ) +{ + real_detach(); + uint i = 0; + while ( i < d->len ) { + if ( d->unicode[i] == c1 ) + d->unicode[i] = c2; + i++; + } + return *this; +} + + +#ifndef QT_NO_REGEXP_CAPTURE + +/*! \overload + + Removes every occurrence of the regular expression \a rx in the + string. Returns a reference to the string. + + This is the same as replace(\a rx, ""). +*/ + +QString &QString::remove( const QRegExp & rx ) +{ + return replace( rx, QString::null ); +} + +#endif + +/*! \overload + + Removes every occurrence of \a str in the string. Returns a + reference to the string. +*/ +QString &QString::remove( const char *str ) +{ + return remove( QString::fromLatin1(str) ); +} + +/*! + Replaces \a len characters from the string with \a s, starting at + position \a index, and returns a reference to the string. + + If \a index is beyond the length of the string, nothing is deleted + and \a s is appended at the end of the string. If \a index is + valid, but \a index + \a len is beyond the end of the string, + the string is truncated at position \a index, then \a s is + appended at the end. + + \code + QString string( "Say yes!" ); + string = string.replace( 4, 3, "NO" ); + // string == "Say NO!" + \endcode + + \sa insert(), remove() +*/ + +QString &QString::replace( uint index, uint len, const QString &s ) +{ + return replace( index, len, s.unicode(), s.length() ); +} + +/*! \overload + + This is the same as replace(\a index, \a len, QString(\a c)). +*/ +QString &QString::replace( uint index, uint len, QChar c ) +{ + return replace( index, len, &c, 1 ); +} + +/*! \overload + \fn QString &QString::replace( uint index, uint len, char c ) + + This is the same as replace(\a index, \a len, QChar(\a c)). +*/ + +/*! + \overload + + Replaces \a len characters with \a slen characters of QChar data + from \a s, starting at position \a index, and returns a reference + to the string. + + \sa insert(), remove() +*/ + +QString &QString::replace( uint index, uint len, const QChar* s, uint slen ) +{ + real_detach(); + if ( len == slen && index + len <= length() ) { + // Optimized common case: replace without size change + memcpy( d->unicode+index, s, len * sizeof(QChar) ); + } else if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { + // Part of me - take a copy. + QChar *tmp = QT_ALLOC_QCHAR_VEC( slen ); + memcpy( tmp, s, slen * sizeof(QChar) ); + replace( index, len, tmp, slen ); + QT_DELETE_QCHAR_VEC( tmp ); + } else { + remove( index, len ); + insert( index, s, slen ); + } + return *this; +} + +/*! \overload + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. + + Example: + \code + QString s = "a,b,c"; + s.replace( QChar(','), " or " ); + // s == "a or b or c" + \endcode +*/ +QString &QString::replace( QChar c, const QString & after ) +{ + return replace( QString( c ), after ); +} + +/*! \overload + \fn QString &QString::replace( char c, const QString & after ) + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. +*/ + +/*! \overload + + Replaces every occurrence of the string \a before in the string + with the string \a after. Returns a reference to the string. + + Example: + \code + QString s = "Greek is Greek"; + s.replace( "Greek", "English" ); + // s == "English is English" + \endcode +*/ +QString &QString::replace( const QString & before, const QString & after ) +{ + if ( before == after || isNull() ) + return *this; + + real_detach(); + + int index = 0; + uint skiptable[256]; + bm_init_skiptable( before, skiptable, TRUE ); + const int bl = before.length(); + const int al = after.length(); + + if ( bl == al ) { + if ( bl ) { + const QChar *auc = after.unicode(); + while( (index = bm_find(*this, index, before, skiptable, TRUE) ) != -1 ) { + memcpy( d->unicode+index, auc, al*sizeof(QChar) ); + index += bl; + } + } + } else if ( al < bl ) { + const QChar *auc = after.unicode(); + uint to = 0; + uint movestart = 0; + uint num = 0; + while( (index = bm_find(*this, index, before, skiptable, TRUE) ) != -1 ) { + if ( num ) { + int msize = index - movestart; + if ( msize > 0 ) { + memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(QChar) ); + to += msize; + } + } else { + to = index; + } + if ( al ) { + memcpy( d->unicode+to, auc, al*sizeof(QChar) ); + to += al; + } + index += bl; + movestart = index; + num++; + } + if ( num ) { + int msize = d->len - movestart; + if ( msize > 0 ) + memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(QChar) ); + setLength( d->len - num*(bl-al) ); + } + } else { + // the most complex case. We don't want to loose performance by doing repeated + // copies and reallocs of the string. + while( index != -1 ) { + uint indices[4096]; + uint pos = 0; + while( pos < 4095 ) { + index = bm_find(*this, index, before, skiptable, TRUE); + if ( index == -1 ) + break; + indices[pos++] = index; + index += bl; + // avoid infinite loop + if ( !bl ) + index++; + } + if ( !pos ) + break; + + // we have a table of replacement positions, use them for fast replacing + int adjust = pos*(al-bl); + // index has to be adjusted in case we get back into the loop above. + if ( index != -1 ) + index += adjust; + uint newlen = d->len + adjust; + int moveend = d->len; + if ( newlen > d->len ) + setLength( newlen ); + + while( pos ) { + pos--; + int movestart = indices[pos] + bl; + int insertstart = indices[pos] + pos*(al-bl); + int moveto = insertstart + al; + memmove( d->unicode + moveto, d->unicode + movestart, (moveend - movestart)*sizeof(QChar) ); + memcpy( d->unicode + insertstart, after.unicode(), al*sizeof(QChar) ); + moveend = movestart-bl; + } + } + } + return *this; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/*! \overload + + Replaces every occurrence of the regexp \a rx in the string with \a str. + Returns a reference to the string. For example: + \code + QString s = "banana"; + s.replace( QRegExp("an"), "" ); + // s == "ba" + \endcode + + For regexps containing \link qregexp.html#capturing-text capturing + parentheses \endlink, occurrences of <b>\\1</b>, <b>\\2</b>, ..., + in \a str are replaced with \a{rx}.cap(1), cap(2), ... + + \code + QString t = "A <i>bon mot</i>."; + t.replace( QRegExp("<i>([^<]*)</i>"), "\\emph{\\1}" ); + // t == "A \\emph{bon mot}." + \endcode + + \sa find(), findRev(), QRegExp::cap() +*/ + +QString &QString::replace( const QRegExp &rx, const QString &str ) +{ + if ( isNull() ) + return *this; + + real_detach(); + + QRegExp rx2 = rx; + int index = 0; + int numCaptures = rx2.numCaptures(); + int al = str.length(); + QRegExp::CaretMode caretMode = QRegExp::CaretAtZero; + + if ( numCaptures > 0 ) { + if ( numCaptures > 9 ) + numCaptures = 9; + + const QChar *uc = str.unicode(); + int numBackRefs = 0; + + for ( int i = 0; i < al - 1; i++ ) { + if ( uc[i] == '\\' ) { + int no = uc[i + 1].digitValue(); + if ( no > 0 && no <= numCaptures ) + numBackRefs++; + } + } + + /* + This is the harder case where we have back-references. We + don't try to optimize it. + */ + if ( numBackRefs > 0 ) { + int *capturePositions = new int[numBackRefs]; + int *captureNumbers = new int[numBackRefs]; + int j = 0; + + for ( int i = 0; i < al - 1; i++ ) { + if ( uc[i] == '\\' ) { + int no = uc[i + 1].digitValue(); + if ( no > 0 && no <= numCaptures ) { + capturePositions[j] = i; + captureNumbers[j] = no; + j++; + } + } + } + + while ( index <= (int)length() ) { + index = rx2.search( *this, index, caretMode ); + if ( index == -1 ) + break; + + QString str2 = str; + for ( j = numBackRefs - 1; j >= 0; j-- ) + str2.replace( capturePositions[j], 2, + rx2.cap(captureNumbers[j]) ); + + replace( index, rx2.matchedLength(), str2 ); + index += str2.length(); + + if ( rx2.matchedLength() == 0 ) { + // avoid infinite loop on 0-length matches (e.g., [a-z]*) + index++; + } else if ( index == 0 ) { + caretMode = QRegExp::CaretWontMatch; + } + } + delete[] capturePositions; + delete[] captureNumbers; + return *this; + } + } + + /* + This is the simple and optimized case where we don't have + back-references. + */ + while ( index != -1 ) { + struct { + int pos; + int length; + } replacements[2048]; + + uint pos = 0; + int adjust = 0; + while( pos < 2047 ) { + index = rx2.search( *this, index, caretMode ); + if ( index == -1 ) + break; + int ml = rx2.matchedLength(); + replacements[pos].pos = index; + replacements[pos++].length = ml; + index += ml; + adjust += al - ml; + // avoid infinite loop + if ( !ml ) + index++; + } + if ( !pos ) + break; + replacements[pos].pos = d->len; + uint newlen = d->len + adjust; + + // to continue searching at the right position after we did + // the first round of replacements + if ( index != -1 ) + index += adjust; + QChar *newuc = QT_ALLOC_QCHAR_VEC( newlen + 1 ); + QChar *uc = newuc; + int copystart = 0; + uint i = 0; + while( i < pos ) { + int copyend = replacements[i].pos; + int size = copyend - copystart; + memcpy( uc, d->unicode + copystart, size*sizeof(QChar) ); + uc += size; + memcpy( uc, str.unicode(), al*sizeof( QChar ) ); + uc += al; + copystart = copyend + replacements[i].length; + i++; + } + memcpy( uc, d->unicode + copystart, + (d->len - copystart) * sizeof(QChar) ); + QT_DELETE_QCHAR_VEC( d->unicode ); + d->unicode = newuc; + d->len = newlen; + d->maxl = newlen + 1; + d->setDirty(); + caretMode = QRegExp::CaretWontMatch; + } + return *this; +} +#endif + +#ifndef QT_NO_REGEXP +/*! + Finds the first match of the regular expression \a rx, starting + from position \a index. If \a index is -1, the search starts at + the last character; if -2, at the next to last character and so + on. (See findRev() for searching backwards.) + + Returns the position of the first match of \a rx or -1 if no match + was found. + + \code + QString string( "bananas" ); + int i = string.find( QRegExp("an"), 0 ); // i == 1 + \endcode + + \sa findRev() replace() contains() +*/ + +int QString::find( const QRegExp &rx, int index ) const +{ + return rx.search( *this, index ); +} + +/*! + \overload + + Finds the first match of the regexp \a rx, starting at position \a + index and searching backwards. If the index is -1, the search + starts at the last character, if it is -2, at the next to last + character and so on. (See findRev() for searching backwards.) + + Returns the position of the match or -1 if no match was found. + + \code + QString string( "bananas" ); + int i = string.findRev( QRegExp("an") ); // i == 3 + \endcode + + \sa find() +*/ + +int QString::findRev( const QRegExp &rx, int index ) const +{ + return rx.searchRev( *this, index ); +} + +/*! + \overload + + Returns the number of times the regexp, \a rx, matches in the + string. + + This function counts overlapping matches, so in the example below, + there are four instances of "ana" or "ama". + + \code + QString str = "banana and panama"; + QRegExp rxp = QRegExp( "a[nm]a", TRUE, FALSE ); + int i = str.contains( rxp ); // i == 4 + \endcode + + \sa find() findRev() +*/ + +int QString::contains( const QRegExp &rx ) const +{ + int count = 0; + int index = -1; + int len = length(); + while ( index < len - 1 ) { // count overlapping matches + index = rx.search( *this, index + 1 ); + if ( index == -1 ) + break; + count++; + } + return count; +} + +#endif //QT_NO_REGEXP + +static bool ok_in_base( QChar c, int base ) +{ + if ( base <= 10 ) + return c.isDigit() && c.digitValue() < base; + else + return c.isDigit() || (c >= 'a' && c < char('a'+base-10)) + || (c >= 'A' && c < char('A'+base-10)); +} + +/*! + Returns the string converted to a \c long value to the base \a + base, which is 10 by default and must be between 2 and 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \sa number() +*/ + +long QString::toLong( bool *ok, int base ) const +{ + const QChar *p = unicode(); + long val = 0; + int l = length(); + const long max_mult = INT_MAX / base; + bool is_ok = FALSE; + int neg = 0; + if ( !p ) + goto bye; + while ( l && p->isSpace() ) // skip leading space + l--,p++; + if ( !l ) + goto bye; + if ( *p == '-' ) { + l--; + p++; + neg = 1; + } else if ( *p == '+' ) { + l--; + p++; + } + + // NOTE: toULong() code is similar + if ( !l || !ok_in_base(*p,base) ) + goto bye; + while ( l && ok_in_base(*p,base) ) { + l--; + int dv; + if ( p->isDigit() ) { + dv = p->digitValue(); + } else { + if ( *p >= 'a' && *p <= 'z' ) + dv = *p - 'a' + 10; + else + dv = *p - 'A' + 10; + } + if ( val > max_mult || + (val == max_mult && dv > (INT_MAX % base) + neg) ) + goto bye; + val = base * val + dv; + p++; + } + if ( neg ) + val = -val; + while ( l && p->isSpace() ) // skip trailing space + l--,p++; + if ( !l ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to an \c {unsigned long} value to the + base \a base, which is 10 by default and must be between 2 and 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \sa number() +*/ + +ulong QString::toULong( bool *ok, int base ) const +{ + const QChar *p = unicode(); + ulong val = 0; + int l = length(); + const ulong max_mult = UINT_MAX / base; + bool is_ok = FALSE; + if ( !p ) + goto bye; + while ( l && p->isSpace() ) // skip leading space + l--,p++; + if ( !l ) + goto bye; + if ( *p == '+' ) + l--,p++; + + // NOTE: toLong() code is similar + if ( !l || !ok_in_base(*p,base) ) + goto bye; + while ( l && ok_in_base(*p,base) ) { + l--; + uint dv; + if ( p->isDigit() ) { + dv = p->digitValue(); + } else { + if ( *p >= 'a' && *p <= 'z' ) + dv = *p - 'a' + 10; + else + dv = *p - 'A' + 10; + } + if ( val > max_mult || (val == max_mult && dv > UINT_MAX % base) ) + goto bye; + val = base * val + dv; + p++; + } + + while ( l && p->isSpace() ) // skip trailing space + l--,p++; + if ( !l ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to a \c short value to the base \a + base, which is 10 by default and must be between 2 and 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. +*/ + +short QString::toShort( bool *ok, int base ) const +{ + long v = toLong( ok, base ); + if ( ok && *ok && (v < -32768 || v > 32767) ) { + *ok = FALSE; + v = 0; + } + return (short)v; +} + +/*! + Returns the string converted to an \c {unsigned short} value to + the base \a base, which is 10 by default and must be between 2 and + 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. +*/ + +ushort QString::toUShort( bool *ok, int base ) const +{ + ulong v = toULong( ok, base ); + if ( ok && *ok && (v > 65535) ) { + *ok = FALSE; + v = 0; + } + return (ushort)v; +} + + +/*! + Returns the string converted to an \c int value to the base \a + base, which is 10 by default and must be between 2 and 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \code + QString str( "FF" ); + bool ok; + int hex = str.toInt( &ok, 16 ); // hex == 255, ok == TRUE + int dec = str.toInt( &ok, 10 ); // dec == 0, ok == FALSE + \endcode + + \sa number() +*/ + +int QString::toInt( bool *ok, int base ) const +{ + return (int)toLong( ok, base ); +} + +/*! + Returns the string converted to an \c{unsigned int} value to the + base \a base, which is 10 by default and must be between 2 and 36. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \sa number() +*/ + +uint QString::toUInt( bool *ok, int base ) const +{ + return (uint)toULong( ok, base ); +} + +/*! + Returns the string converted to a \c double value. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \code + QString string( "1234.56" ); + double a = string.toDouble(); // a == 1234.56 + \endcode + + \sa number() +*/ + +double QString::toDouble( bool *ok ) const +{ + char *end; + + const char *a = latin1(); + double val = strtod( a ? a : "", &end ); + if ( ok ) + *ok = ( a && *a && (end == 0 || (end - a) == (int)length()) ); + return val; +} + +/*! + Returns the string converted to a \c float value. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \sa number() +*/ + +float QString::toFloat( bool *ok ) const +{ + return (float)toDouble( ok ); +} + + +/*! + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. + + \code + QString string; + string = string.setNum( 1234 ); // string == "1234" + \endcode +*/ + +QString &QString::setNum( long n, int base ) +{ +#if defined(QT_CHECK_RANGE) + if ( base < 2 || base > 36 ) { + qWarning( "QString::setNum: Invalid base %d", base ); + base = 10; + } +#endif + char charbuf[65*sizeof(QChar)]; + QChar *buf = (QChar*)charbuf; + QChar *p = &buf[64]; + int len = 0; + bool neg; + if ( n < 0 ) { + neg = TRUE; + if ( n == INT_MIN ) { + // Cannot always negate this special case + QString s1, s2; + s1.setNum(n/base); + s2.setNum((-(n+base))%base); + *this = s1 + s2; + return *this; + } + n = -n; + } else { + neg = FALSE; + } + do { + *--p = "0123456789abcdefghijklmnopqrstuvwxyz"[((int)(n%base))]; + n /= base; + ++len; + } while ( n ); + if ( neg ) { + *--p = '-'; + ++len; + } + return setUnicode( p, len ); +} + +/*! + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +QString &QString::setNum( ulong n, int base ) +{ +#if defined(QT_CHECK_RANGE) + if ( base < 2 || base > 36 ) { + qWarning( "QString::setNum: Invalid base %d", base ); + base = 10; + } +#endif + char charbuf[65*sizeof(QChar)]; + QChar *buf = (QChar*)charbuf; + QChar *p = &buf[64]; + int len = 0; + do { + *--p = "0123456789abcdefghijklmnopqrstuvwxyz"[((int)(n%base))]; + n /= base; + len++; + } while ( n ); + return setUnicode(p,len); +} + +/*! + \fn QString &QString::setNum( int n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn QString &QString::setNum( uint n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn QString &QString::setNum( short n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn QString &QString::setNum( ushort n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \overload + + Sets the string to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + string. + + The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link + #arg-formats arg \endlink() for an explanation of the formats. +*/ + +QString &QString::setNum( double n, char f, int prec ) +{ +#if defined(QT_CHECK_RANGE) + if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) { + qWarning( "QString::setNum: Invalid format char '%c'", f ); + f = 'f'; + } +#endif + char format[20]; + char *fs = format; // generate format string: %.<prec>l<f> + *fs++ = '%'; + if ( prec >= 0 ) { + if ( prec > 99 ) // rather than crash in sprintf() + prec = 99; + *fs++ = '.'; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + } + *fs++ = 'l'; + *fs++ = f; + *fs = '\0'; +#ifndef QT_NO_SPRINTF + sprintf( format, n ); + return *this; +#else + char buf[512]; + ::sprintf( buf, format, n ); // snprintf is unfortunately not portable + return setLatin1(buf); +#endif +} + +/*! + \fn QString &QString::setNum( float n, char f, int prec ) + + \overload + + Sets the string to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + string. + + The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link + #arg-formats arg \endlink() for an explanation of the formats. +*/ + + +/*! + A convenience function that returns a string equivalent of the + number \a n to base \a base, which is 10 by default and must be + between 2 and 36. + + \code + long a = 63; + QString str = QString::number( a, 16 ); // str == "3f" + QString str = QString::number( a, 16 ).upper(); // str == "3F" + \endcode + + \sa setNum() +*/ +QString QString::number( long n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +QString QString::number( ulong n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +QString QString::number( int n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + A convenience factory function that returns a string + representation of the number \a n to the base \a base, which is 10 + by default and must be between 2 and 36. + + \sa setNum() +*/ +QString QString::number( uint n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + Argument \a n is formatted according to the \a f format specified, + which is \c g by default, and can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \code + double d = 12.34; + QString ds = QString( "'E' format, precision 3, gives %1" ) + .arg( d, 0, 'E', 3 ); + // ds == "1.234E+001" + \endcode + + \sa setNum() + */ +QString QString::number( double n, char f, int prec ) +{ + QString s; + s.setNum( n, f, prec ); + return s; +} + + +/*! \obsolete + + Sets the character at position \a index to \a c and expands the + string if necessary, filling with spaces. + + This method is redundant in Qt 3.x, because operator[] will expand + the string as necessary. +*/ + +void QString::setExpand( uint index, QChar c ) +{ + int spaces = index - d->len; + at(index) = c; + while (spaces-->0) + d->unicode[--index]=' '; +} + + +/*! + \fn const char* QString::data() const + + \obsolete + + Returns a pointer to a '\0'-terminated classic C string. + + In Qt 1.x, this returned a char* allowing direct manipulation of the + string as a sequence of bytes. In Qt 2.x where QString is a Unicode + string, char* conversion constructs a temporary string, and hence + direct character operations are meaningless. +*/ + +/*! + \fn bool QString::operator!() const + + Returns TRUE if this is a null string; otherwise returns FALSE. + + \code + QString name = getName(); + if ( !name ) + name = "Rodney"; + \endcode + + Note that if you say + + \code + QString name = getName(); + if ( name ) + doSomethingWith(name); + \endcode + + It will call "operator const char*()", which is inefficent; you + may wish to define the macro \c QT_NO_ASCII_CAST when writing code + which you wish to remain Unicode-clean. + + When you want the above semantics, use: + + \code + QString name = getName(); + if ( !name.isNull() ) + doSomethingWith(name); + \endcode + + \sa isEmpty() +*/ + + +/*! + \fn QString& QString::append( const QString& str ) + + Appends \a str to the string and returns a reference to the + result. + + \code + string = "Test"; + string.append( "ing" ); // string == "Testing" + \endcode + + Equivalent to operator+=(). +*/ + +/*! + \fn QString& QString::append( char ch ) + + \overload + + Appends character \a ch to the string and returns a reference to + the result. + + Equivalent to operator+=(). +*/ + +/*! + \fn QString& QString::append( QChar ch ) + + \overload + + Appends character \a ch to the string and returns a reference to + the result. + + Equivalent to operator+=(). +*/ + +/*! \fn QString& QString::append( const QByteArray &str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). + */ + +/*! \fn QString& QString::append( const char *str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). + */ + +/*! + Appends \a str to the string and returns a reference to the string. +*/ +QString& QString::operator+=( const QString &str ) +{ + uint len1 = length(); + uint len2 = str.length(); + if ( len2 ) { + setLength(len1+len2); + memcpy( d->unicode+len1, str.unicode(), sizeof(QChar)*len2 ); + } else if ( isNull() && !str.isNull() ) { // ## just for 1.x compat: + *this = fromLatin1( "" ); + } + return *this; +} + +/*! + \overload + + Appends \a str to the string and returns a reference to the string. +*/ +QString& QString::operator+=( const char *str ) +{ + if ( str ) { + uint len1 = length(); + uint len2 = strlen( str ); + if ( len2 ) { + setLength(len1+len2); + uint i = 0; + while( i < len2 ) { + d->unicode[len1+i] = str[i]; + i++; + } + } else if ( isNull() ) { // ## just for 1.x compat: + *this = fromLatin1( "" ); + } + } + return *this; +} + +/*! \overload + + Appends \a c to the string and returns a reference to the string. +*/ + +QString &QString::operator+=( QChar c ) +{ + setLength(length()+1); + d->unicode[length()-1] = c; + return *this; +} + +/*! + \overload + + Appends \a c to the string and returns a reference to the string. +*/ + +QString &QString::operator+=( char c ) +{ + setLength(length()+1); + d->unicode[length()-1] = c; + return *this; +} + +/*! + \fn QString &QString::operator+=( const QByteArray &str ) + \overload + + Appends \a str to the string and returns a reference to the string. +*/ + + + +/*! + \fn char QChar::latin1() const + + Returns a latin-1 copy of this character, if this character is in + the latin-1 character set. If not, this function returns 0. +*/ + + +/*! + Returns a Latin-1 representation of the string. Note that the + returned value is undefined if the string contains non-Latin-1 + characters. If you want to convert strings into formats other than + Unicode, see the QTextCodec classes. + + This function is mainly useful for boot-strapping legacy code to + use Unicode. + + The result remains valid so long as one unmodified copy of the + source string exists. + + \sa utf8(), local8Bit() +*/ +const char* QString::latin1() const +{ + if ( !d->ascii ) { + Q2HELPER(stat_get_ascii++) + Q2HELPER(stat_get_ascii_size+=d->len) + d->ascii = unicodeToAscii( d->unicode, d->len ); + } + return d->ascii; +} + +/*! + \fn const char* QString::ascii() const + \obsolete + + This function simply calls latin1() and returns the result. +*/ + +/*! + Returns the string encoded in UTF8 format. + + See QTextCodec for more diverse coding/decoding of Unicode strings. + + \sa QString::fromUtf8(), local8Bit(), latin1() +*/ +QCString QString::utf8() const +{ + int l = length(); + int rlen = l*3+1; + QCString rstr(rlen); + uchar* cursor = (uchar*)rstr.data(); + const QChar *ch = d->unicode; + for (int i=0; i<l; i++) { + ushort u = ch->unicode(); + if ( u < 0x80 ) { + *cursor++ = (uchar)u; + } else { + if ( u < 0x0800 ) { + *cursor++ = 0xc0 | ((uchar) (u >> 6)); + } else { + *cursor++ = 0xe0 | ((uchar) (u >> 12)); + *cursor++ = 0x80 | ( ((uchar) (u >> 6)) & 0x3f); + } + *cursor++ = 0x80 | ((uchar) (u&0x3f)); + } + ch++; + } + rstr.truncate( cursor - (uchar*)rstr.data() ); + return rstr; +} + +/*! + Returns the Unicode string decoded from the first \a len + characters of \a utf8, ignoring the rest of \a utf8. If \a len is + -1 then the length of \a utf8 is used. If \a len is bigger than + the length of \a utf8 then it will use the length of \a utf8. + + \code + QString str = QString::fromUtf8( "123456789", 5 ); + // str == "12345" + \endcode + + See QTextCodec for more diverse coding/decoding of Unicode strings. +*/ +QString QString::fromUtf8( const char* utf8, int len ) +{ + if ( !utf8 ) + return QString::null; + + if ( len < 0 ) len = qstrlen( utf8 ); + QString result; + result.setLength( len ); // worst case + QChar *qch = (QChar *)result.unicode(); + ushort uc = 0; + int need = 0; + for (int i=0; i<len; i++) { + uchar ch = utf8[i]; + if (need) { + if ( (ch&0xc0) == 0x80 ) { + uc = (uc << 6) | (ch & 0x3f); + need--; + if ( !need ) { + *qch = uc; + qch++; + } + } else { + // error + *qch = QChar::replacement; + qch++; + need = 0; + } + } else { + if ( ch < 128 ) { + *qch = ch; + qch++; + } else if ( (ch&0xe0) == 0xc0 ) { + uc = ch &0x1f; + need = 1; + } else if ( (ch&0xf0) == 0xe0 ) { + uc = ch &0x0f; + need = 2; + } + } + } + result.truncate( qch - result.unicode() ); + return result; +} + +/*! + Returns the Unicode string decoded from the first \a len + characters of \a chars, ignoring the rest of \a chars. If \a len + is -1 then the length of \a chars is used. If \a len is bigger + than the length of \a chars then it will use the length of \a + chars. + + This is the same as the QString(const char*) constructor, but you + can make that constructor invisible if you compile with the define + \c QT_NO_CAST_ASCII, in which case you can explicitly create a + QString from Latin-1 text using this function. + + \code + QString str = QString::fromLatin1( "123456789", 5 ); + // str == "12345" + \endcode +*/ +QString QString::fromLatin1( const char* chars, int len ) +{ + uint l; + QChar *uc; + if ( len < 0 ) + len = -1; + uc = internalAsciiToUnicode( chars, &l, len ); + return QString( new QStringData(uc, l, l), TRUE ); +} + +/*! + \fn const QChar* QString::unicode() const + + Returns the Unicode representation of the string. The result + remains valid until the string is modified. +*/ + +/*! + Returns the string encoded in a locale-specific format. On X11, + this is the QTextCodec::codecForLocale(). On Windows, it is a + system-defined encoding. On Mac OS X, this always uses utf8 as the + encoding. + + See QTextCodec for more diverse coding/decoding of Unicode + strings. + + \sa QString::fromLocal8Bit(), latin1(), utf8() +*/ + + +QCString QString::local8Bit() const +{ +#ifdef QT_NO_TEXTCODEC + return latin1(); +#else +#ifdef Q_WS_X11 + QTextCodec* codec = QTextCodec::codecForLocale(); + return codec + ? codec->fromUnicode(*this) + : QCString(latin1()); +#endif +#if defined( Q_WS_MACX ) + return utf8(); +#endif +#if defined( Q_WS_MAC9 ) + return QCString(latin1()); //I'm evil.. +#endif +#ifdef Q_WS_WIN + return qt_winQString2MB( *this ); +#endif +#ifdef Q_WS_QWS + return utf8(); // ##### if there is ANY 8 bit format supported? +#endif +#endif +} + +/*! + Returns the Unicode string decoded from the first \a len + characters of \a local8Bit, ignoring the rest of \a local8Bit. If + \a len is -1 then the length of \a local8Bit is used. If \a len is + bigger than the length of \a local8Bit then it will use the length + of \a local8Bit. + + \code + QString str = QString::fromLocal8Bit( "123456789", 5 ); + // str == "12345" + \endcode + + \a local8Bit is assumed to be encoded in a locale-specific format. + + See QTextCodec for more diverse coding/decoding of Unicode strings. +*/ +QString QString::fromLocal8Bit( const char* local8Bit, int len ) +{ +#ifdef QT_NO_TEXTCODEC + return fromLatin1( local8Bit, len ); +#else + + if ( !local8Bit ) + return QString::null; +#ifdef Q_WS_X11 + QTextCodec* codec = QTextCodec::codecForLocale(); + if ( len < 0 ) len = qstrlen(local8Bit); + return codec + ? codec->toUnicode( local8Bit, len ) + : fromLatin1( local8Bit, len ); +#endif +#if defined( Q_WS_MAC ) + return fromUtf8(local8Bit,len); +#endif +// Should this be OS_WIN32? +#ifdef Q_WS_WIN + if ( len >= 0 ) { + QCString s(local8Bit,len+1); + return qt_winMB2QString(s); + } + return qt_winMB2QString( local8Bit ); +#endif +#ifdef Q_WS_QWS + return fromUtf8(local8Bit,len); +#endif +#endif // QT_NO_TEXTCODEC +} + +/*! + \fn QString::operator const char *() const + + Returns latin1(). Be sure to see the warnings documented in the + latin1() function. Note that for new code which you wish to be + strictly Unicode-clean, you can define the macro \c + QT_NO_ASCII_CAST when compiling your code to hide this function so + that automatic casts are not done. This has the added advantage + that you catch the programming error described in operator!(). +*/ + + +/*! + Returns the QString as a zero terminated array of unsigned shorts + if the string is not null; otherwise returns zero. + + The result remains valid so long as one unmodified + copy of the source string exists. +*/ +const unsigned short *QString::ucs2() const +{ + if ( ! d->unicode ) + return 0; + unsigned int len = d->len; + if ( d->maxl < len + 1 ) { + // detach, grow or shrink + Q2HELPER(stat_copy_on_write++) + Q2HELPER(stat_copy_on_write_size += len) + uint newMax = computeNewMax( len + 1 ); + QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( nd ) { + if ( d->unicode ) + memcpy( nd, d->unicode, sizeof(QChar)*len ); + ((QString *)this)->deref(); + ((QString *)this)->d = new QStringData( nd, len, newMax ); + } + } + d->unicode[len] = 0; + return (unsigned short *) d->unicode; +} + +/*! + Constructs a string that is a deep copy of \a str, interpreted as a + UCS2 encoded, zero terminated, Unicode string. + + If \a str is 0, then a null string is created. + + \sa isNull() +*/ +QString QString::fromUcs2( const unsigned short *str ) +{ + if ( !str ) { + return QString::null; + } else { + int length = 0; + while( str[length] != 0 ) + length++; + QChar* uc = QT_ALLOC_QCHAR_VEC( length ); + memcpy( uc, str, length*sizeof(QChar) ); + return QString( new QStringData( uc, length, length ), TRUE ); + } +} + +/*! + \fn QChar QString::at( uint ) const + + Returns the character at index \a i, or 0 if \a i is beyond the + length of the string. + + \code + const QString string( "abcdefgh" ); + QChar ch = string.at( 4 ); + // ch == 'e' + \endcode + + If the QString is not const (i.e. const QString) or const& (i.e. + const QString &), then the non-const overload of at() will be used + instead. +*/ + +/*! + \fn QChar QString::constref(uint i) const + + Returns the QChar at index \a i by value. + + Equivalent to at(\a i). + + \sa ref() +*/ + +/*! + \fn QChar& QString::ref(uint i) + + Returns the QChar at index \a i by reference, expanding the string + with QChar::null if necessary. The resulting reference can be + assigned to, or otherwise used immediately, but becomes invalid + once furher modifications are made to the string. + + \code + QString string("ABCDEF"); + QChar ch = string.ref( 3 ); // ch == 'D' + \endcode + + \sa constref() +*/ + +/*! + \fn QChar QString::operator[]( int ) const + + Returns the character at index \a i, or QChar::null if \a i is + beyond the length of the string. + + If the QString is not const (i.e., const QString) or const\& + (i.e., const QString\&), then the non-const overload of operator[] + will be used instead. +*/ + +/*! + \fn QCharRef QString::operator[]( int ) + + \overload + + The function returns a reference to the character at index \a i. + The resulting reference can then be assigned to, or used + immediately, but it will become invalid once further modifications + are made to the original string. + + If \a i is beyond the length of the string then the string is + expanded with QChar::nulls, so that the QCharRef references a + valid (null) character in the string. + + The QCharRef internal class can be used much like a constant + QChar, but if you assign to it, you change the original string + (which will detach itself because of QString's copy-on-write + semantics). You will get compilation errors if you try to use the + result as anything but a QChar. +*/ + +/*! + \fn QCharRef QString::at( uint i ) + + \overload + + The function returns a reference to the character at index \a i. + The resulting reference can then be assigned to, or used + immediately, but it will become invalid once further modifications + are made to the original string. + + If \a i is beyond the length of the string then the string is + expanded with QChar::null. +*/ + +/* + Internal chunk of code to handle the + uncommon cases of at() above. +*/ +void QString::subat( uint i ) +{ + uint olen = d->len; + if ( i >= olen ) { + setLength( i+1 ); // i is index; i+1 is needed length + for ( uint j=olen; j<=i; j++ ) + d->unicode[j] = QChar::null; + } else { + // Just be sure to detach + real_detach(); + } +} + + +/*! + Resizes the string to \a len characters and copies \a unicode into + the string. If \a unicode is 0, nothing is copied, but the + string is still resized to \a len. If \a len is zero, then the + string becomes a \link isNull() null\endlink string. + + \sa setLatin1(), isNull() +*/ + +QString& QString::setUnicode( const QChar *unicode, uint len ) +{ + if ( len == 0 ) { // set to null string + if ( d != shared_null ) { // beware of nullstring being set to nullstring + deref(); + d = shared_null ? shared_null : makeSharedNull(); + d->ref(); + } + } else if ( d->count != 1 || len > d->maxl || + ( len * 4 < d->maxl && d->maxl > 4 ) ) { + // detach, grown or shrink + Q2HELPER(stat_copy_on_write++) + Q2HELPER(stat_copy_on_write_size+=d->len) + uint newMax = computeNewMax( len ); + QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( unicode ) + memcpy( nd, unicode, sizeof(QChar)*len ); + deref(); + d = new QStringData( nd, len, newMax ); + } else { + d->len = len; + d->setDirty(); + if ( unicode ) + memcpy( d->unicode, unicode, sizeof(QChar)*len ); + } + return *this; +} + +/*! + Resizes the string to \a len characters and copies \a + unicode_as_ushorts into the string (on some X11 client platforms + this will involve a byte-swapping pass). + + If \a unicode_as_ushorts is 0, nothing is copied, but the string + is still resized to \a len. If \a len is zero, the string becomes + a \link isNull() null\endlink string. + + \sa setLatin1(), isNull() +*/ +QString& QString::setUnicodeCodes( const ushort* unicode_as_ushorts, uint len ) +{ + return setUnicode((const QChar*)unicode_as_ushorts, len); +} + + +/*! + Sets this string to \a str, interpreted as a classic Latin1 C + string. If \a len is -1 (the default), then it is set to + strlen(str). + + If \a str is 0 a null string is created. If \a str is "", an empty + string is created. + + \sa isNull(), isEmpty() +*/ + +QString &QString::setLatin1( const char *str, int len ) +{ + if ( str == 0 ) + return setUnicode(0,0); + if ( len < 0 ) + len = qstrlen(str); + if ( len == 0 ) { // won't make a null string + *this = QString::fromLatin1( "" ); + } else { + setUnicode( 0, len ); // resize but not copy + QChar *p = d->unicode; + while ( len-- ) + *p++ = *str++; + } + return *this; +} + +/*! \internal + */ +void QString::checkSimpleText() const +{ + QChar *p = d->unicode; + QChar *end = p + d->len; + d->simpletext = 1; + while( p < end ) { + ushort uc = p->unicode(); + // sort out regions of complex text formatting + if ( uc > 0x058f && ( uc < 0x1100 || uc > 0xfb0f ) ) { + d->simpletext = 0; + return; + } + p++; + } +} + +/*! \fn bool QString::simpleText() const + \internal +*/ + +/*! \internal + */ +bool QString::isRightToLeft() const +{ + int len = length(); + QChar *p = d->unicode; + while( len-- ) { + switch( ::direction( *p ) ) + { + case QChar::DirL: + case QChar::DirLRO: + case QChar::DirLRE: + return FALSE; + case QChar::DirR: + case QChar::DirAL: + case QChar::DirRLO: + case QChar::DirRLE: + return TRUE; + default: + break; + } + ++p; + } + return FALSE; +} + + +/*! + \fn int QString::compare( const QString & s1, const QString & s2 ) + + Lexically compares \a s1 with \a s2 and returns an integer less + than, equal to, or greater than zero if \a s1 is less than, equal + to, or greater than \a s2. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). + + \code + int a = QString::compare( "def", "abc" ); // a > 0 + int b = QString::compare( "abc", "def" ); // b < 0 + int c = QString::compare(" abc", "abc" ); // c == 0 + \endcode +*/ + +/*! + \overload + + Lexically compares this string with \a s and returns an integer + less than, equal to, or greater than zero if it is less than, equal + to, or greater than \a s. +*/ +int QString::compare( const QString& s ) const +{ + return ucstrcmp( *this, s ); +} + +/*! + \fn int QString::localeAwareCompare( const QString & s1, const QString & s2 ) + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + \sa QString::compare() QTextCodec::locale() +*/ + +/*! + \overload + + Compares this string with \a s. +*/ + +#if !defined(CSTR_LESS_THAN) +#define CSTR_LESS_THAN 1 +#define CSTR_EQUAL 2 +#define CSTR_GREATER_THAN 3 +#endif + +int QString::localeAwareCompare( const QString& s ) const +{ + // do the right thing for null and empty + if ( isEmpty() || s.isEmpty() ) + return compare( s ); + +#if defined(Q_WS_WIN) + int res; + QT_WA( { + const TCHAR* s1 = (TCHAR*)ucs2(); + const TCHAR* s2 = (TCHAR*)s.ucs2(); + res = CompareStringW( LOCALE_USER_DEFAULT, 0, s1, length(), s2, s.length() ); + } , { + QCString s1 = local8Bit(); + QCString s2 = s.local8Bit(); + res = CompareStringA( LOCALE_USER_DEFAULT, 0, s1.data(), s1.length(), s2.data(), s2.length() ); + } ); + + switch ( res ) { + case CSTR_LESS_THAN: + return -1; + case CSTR_GREATER_THAN: + return 1; + default: + return 0; + } +#elif defined(Q_WS_X11) + // declared in <string.h> + int delta = strcoll( local8Bit(), s.local8Bit() ); + if ( delta == 0 ) + delta = ucstrcmp( *this, s ); + return delta; +#else + return ucstrcmp( *this, s ); +#endif +} + +bool operator==( const QString &s1, const QString &s2 ) +{ + if ( s1.unicode() == s2.unicode() ) + return TRUE; + return (s1.length() == s2.length()) && s1.isNull() == s2.isNull() && + (memcmp((char*)s1.unicode(),(char*)s2.unicode(), + s1.length()*sizeof(QChar)) == 0 ); +} + +bool operator!=( const QString &s1, const QString &s2 ) +{ return !(s1==s2); } + +bool operator<( const QString &s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<=( const QString &s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator>( const QString &s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>=( const QString &s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + + +bool operator==( const QString &s1, const char *s2 ) +{ + if ( !s2 ) + return s1.isNull(); + + int len = s1.length(); + const QChar *uc = s1.unicode(); + while ( len ) { + if ( !(*s2) || uc->unicode() != (uchar) *s2 ) + return FALSE; + ++uc; + ++s2; + --len; + } + return !*s2; +} + +bool operator==( const char *s1, const QString &s2 ) +{ return (s2 == s1); } + +bool operator!=( const QString &s1, const char *s2 ) +{ return !(s1==s2); } + +bool operator!=( const char *s1, const QString &s2 ) +{ return !(s1==s2); } + +bool operator<( const QString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<( const char *s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<=( const QString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator<=( const char *s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator>( const QString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>( const char *s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>=( const QString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + +bool operator>=( const char *s1, const QString &s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + + +/***************************************************************************** + Documentation for QString related functions + *****************************************************************************/ + +/*! + \fn bool operator==( const QString &s1, const QString &s2 ) + + \relates QString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator==( const QString &s1, const char *s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) == 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator==( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) == 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const QString &s1, const QString &s2 ) + + \relates QString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const QString &s1, const char *s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator<( const QString &s1, const char *s2 ) + + \relates QString + + Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \< 0. +*/ + +/*! + \fn bool operator<( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \< 0. +*/ + +/*! + \fn bool operator<=( const QString &s1, const char *s2 ) + + \relates QString + + Returns TRUE if \a s1 is lexically less than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1,\a s2) \<= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator<=( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is lexically less than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \<= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator>( const QString &s1, const char *s2 ) + + \relates QString + + Returns TRUE if \a s1 is lexically greater than \a s2; otherwise + returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \> 0. +*/ + +/*! + \fn bool operator>( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is lexically greater than \a s2; otherwise + returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \> 0. +*/ + +/*! + \fn bool operator>=( const QString &s1, const char *s2 ) + + \relates QString + + Returns TRUE if \a s1 is lexically greater than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \>= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator>=( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns TRUE if \a s1 is lexically greater than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \>= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn const QString operator+( const QString &s1, const QString &s2 ) + + \relates QString + + Returns a string which is the result of concatenating the string + \a s1 and the string \a s2. + + Equivalent to \a {s1}.append(\a s2). +*/ + +/*! + \fn const QString operator+( const QString &s1, const char *s2 ) + + \overload + \relates QString + + Returns a string which is the result of concatenating the string + \a s1 and character \a s2. + + Equivalent to \a {s1}.append(\a s2). +*/ + +/*! + \fn const QString operator+( const char *s1, const QString &s2 ) + + \overload + \relates QString + + Returns a string which is the result of concatenating the + character \a s1 and string \a s2. +*/ + +/*! + \fn const QString operator+( const QString &s, char c ) + + \overload + \relates QString + + Returns a string which is the result of concatenating the string + \a s and character \a c. + + Equivalent to \a {s}.append(\a c). +*/ + +/*! + \fn const QString operator+( char c, const QString &s ) + + \overload + \relates QString + + Returns a string which is the result of concatenating the + character \a c and string \a s. + + Equivalent to \a {s}.prepend(\a c). +*/ + + +/***************************************************************************** + QString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \relates QString + + Writes the string \a str to the stream \a s. + + See also \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator<<( QDataStream &s, const QString &str ) +{ + if ( s.version() == 1 ) { + QCString l( str.latin1() ); + s << l; + } + else { + int byteOrder = s.byteOrder(); + const QChar* ub = str.unicode(); + if ( ub || s.version() < 3 ) { + static const uint auto_size = 1024; + char t[auto_size]; + char *b; + if ( str.length()*sizeof(QChar) > auto_size ) { + b = new char[str.length()*sizeof(QChar)]; + } else { + b = t; + } + int l = str.length(); + char *c=b; + while ( l-- ) { + if ( byteOrder == QDataStream::BigEndian ) { + *c++ = (char)ub->row(); + *c++ = (char)ub->cell(); + } else { + *c++ = (char)ub->cell(); + *c++ = (char)ub->row(); + } + ub++; + } + s.writeBytes( b, sizeof(QChar)*str.length() ); + if ( str.length()*sizeof(QChar) > auto_size ) + delete [] b; + } else { + // write null marker + s << (Q_UINT32)0xffffffff; + } + } + return s; +} + +/*! + \relates QString + + Reads a string from the stream \a s into string \a str. + + See also \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QString &str ) +{ +#ifdef QT_QSTRING_UCS_4 +#if defined(Q_CC_GNU) +#warning "operator>> not working properly" +#endif +#endif + if ( s.version() == 1 ) { + QCString l; + s >> l; + str = QString( l ); + } + else { + Q_UINT32 bytes; + s >> bytes; // read size of string + if ( bytes == 0xffffffff ) { // null string + str = QString::null; + } else if ( bytes > 0 ) { // not empty + int byteOrder = s.byteOrder(); + str.setLength( bytes/2 ); + QChar* ch = str.d->unicode; + static const uint auto_size = 1024; + char t[auto_size]; + char *b; + if ( bytes > auto_size ) { + b = new char[bytes]; + } else { + b = t; + } + s.readRawBytes( b, bytes ); + int bt = bytes/2; + char *oldb = b; + while ( bt-- ) { + if ( byteOrder == QDataStream::BigEndian ) + *ch++ = (ushort) (((ushort)b[0])<<8) | (uchar)b[1]; + else + *ch++ = (ushort) (((ushort)b[1])<<8) | (uchar)b[0]; + b += 2; + } + if ( bytes > auto_size ) + delete [] oldb; + } else { + str = ""; + } + } + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QConstString member functions + *****************************************************************************/ + +/*! + \class QConstString qstring.h + \reentrant + \ingroup text + \brief The QConstString class provides string objects using constant Unicode data. + + In order to minimize copying, highly optimized applications can + use QConstString to provide a QString-compatible object from + existing Unicode data. It is then the programmer's responsibility + to ensure that the Unicode data exists for the entire lifetime of + the QConstString object. + + A QConstString is created with the QConstString constructor. The + string held by the object can be obtained by calling string(). +*/ + +/*! + Constructs a QConstString that uses the first \a length Unicode + characters in the array \a unicode. Any attempt to modify copies + of the string will cause it to create a copy of the data, thus it + remains forever unmodified. + + The data in \a unicode is not copied. The caller must be able to + guarantee that \a unicode will not be deleted or modified. +*/ +QConstString::QConstString( const QChar* unicode, uint length ) : + QString( new QStringData( (QChar*)unicode, length, length ), TRUE ) +{ +} + +/*! + Destroys the QConstString, creating a copy of the data if other + strings are still using it. +*/ +QConstString::~QConstString() +{ + if ( d->count > 1 ) { + QChar* cp = QT_ALLOC_QCHAR_VEC( d->len ); + memcpy( cp, d->unicode, d->len*sizeof(QChar) ); + d->unicode = cp; + } else { + d->unicode = 0; + } + + // The original d->unicode is now unlinked. +} + +/*! + \fn const QString& QConstString::string() const + + Returns a constant string referencing the data passed during + construction. +*/ + +/*! + Returns TRUE if the string starts with \a s; otherwise returns + FALSE. + + \code + QString string("Bananas"); + bool a = string.startsWith("Ban"); // a == TRUE + \endcode + + \sa endsWith() +*/ +bool QString::startsWith( const QString& s ) const +{ + if ( isNull() ) + return s.isNull(); + if ( s.length() > length() ) + return FALSE; + for ( int i =0; i < (int) s.length(); i++ ) { + if ( d->unicode[i] != s[i] ) + return FALSE; + } + return TRUE; +} + +/*! + Returns TRUE if the string ends with \a s; otherwise returns + FALSE. + + \sa startsWith() +*/ +bool QString::endsWith( const QString& s ) const +{ + if ( isNull() ) + return s.isNull(); + int pos = length() - s.length(); + if ( pos < 0 ) + return FALSE; + for ( uint i = 0; i < s.length(); i++ ) { + if ( d->unicode[pos+i] != s[(int)i] ) + return FALSE; + } + return TRUE; +} + +/*! \fn void QString::detach() + If the string does not share its data with another QString instance, + nothing happens; otherwise the function creates a new, unique copy of + this string. This function is called whenever the map is modified. The + implicit sharing mechanism is implemented this way. +*/ + +#if defined(Q_OS_WIN32) + +#include <windows.h> + +/*! + \obsolete + + Returns a static Windows TCHAR* from a QString, adding NUL if \a + addnul is TRUE. + + The lifetime of the return value is until the next call to this function, + or until the last copy of str is deleted, whatever comes first. + + Use ucs2() instead. +*/ +const void* qt_winTchar(const QString& str, bool) +{ + // So that the return value lives long enough. + static QString str_cache; + str_cache = str; +#ifdef UNICODE + return str_cache.ucs2(); +#else + return str_cache.latin1(); +#endif +} + +/*! + Makes a new '\0'-terminated Windows TCHAR* from a QString. +*/ +void* qt_winTchar_new(const QString& str) +{ + if ( str.isNull() ) + return 0; + int l = str.length()+1; + TCHAR *tc = new TCHAR[ l ]; +#ifdef UNICODE + memcpy( tc, str.ucs2(), sizeof(TCHAR)*l ); +#else + memcpy( tc, str.latin1(), sizeof(TCHAR)*l ); +#endif + return tc; +} + +/*! + Makes a QString from a Windows TCHAR*. +*/ +QString qt_winQString(void* tc) +{ +#ifdef UNICODE + return QString::fromUcs2( (ushort*)tc ); +#else + return QString::fromLatin1( (TCHAR *)tc ); +#endif +} + +QCString qt_winQString2MB( const QString& s, int uclen ) +{ + if ( uclen < 0 ) + uclen = s.length(); + if ( s.isNull() ) + return QCString(); + if ( uclen == 0 ) + return QCString(""); + BOOL used_def; + QCString mb(4096); + int len; + while ( !(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)s.unicode(), uclen, + mb.data(), mb.size()-1, 0, &used_def)) ) + { + int r = GetLastError(); + if ( r == ERROR_INSUFFICIENT_BUFFER ) { + mb.resize(1+WideCharToMultiByte( CP_ACP, 0, + (const WCHAR*)s.unicode(), uclen, + 0, 0, 0, &used_def)); + // and try again... + } else { +#ifndef QT_NO_DEBUG + // Fail. + qWarning("WideCharToMultiByte cannot convert multibyte text (error %d): %s (UTF8)", + r, s.utf8().data()); +#endif + break; + } + } + mb[len]='\0'; + return mb; +} + +// WATCH OUT: mblen must include the NUL (or just use -1) +QString qt_winMB2QString( const char* mb, int mblen ) +{ + if ( !mb || !mblen ) + return QString::null; + const int wclen_auto = 4096; + WCHAR wc_auto[wclen_auto]; + int wclen = wclen_auto; + WCHAR *wc = wc_auto; + int len; + while ( !(len=MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, + mb, mblen, wc, wclen )) ) + { + int r = GetLastError(); + if ( r == ERROR_INSUFFICIENT_BUFFER ) { + if ( wc != wc_auto ) { + qWarning("Size changed in MultiByteToWideChar"); + break; + } else { + wclen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, + mb, mblen, 0, 0 ); + wc = new WCHAR[wclen]; + // and try again... + } + } else { + // Fail. + qWarning("MultiByteToWideChar cannot convert multibyte text"); + break; + } + } + if ( len <= 0 ) + return QString::null; + QString s( (QChar*)wc, len - 1 ); // len - 1: we don't want terminator + if ( wc != wc_auto ) + delete [] wc; + return s; +} + +#endif // Q_OS_WIN32 diff --git a/qmake/tools/qstringlist.cpp b/qmake/tools/qstringlist.cpp new file mode 100644 index 0000000..0720e7f --- a/dev/null +++ b/qmake/tools/qstringlist.cpp @@ -0,0 +1,376 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QStringList +** +** Created : 990406 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qstringlist.h" + +#ifndef QT_NO_STRINGLIST +#include "qregexp.h" +#include "qstrlist.h" +#include "qdatastream.h" +#include "qtl.h" + +/*! + \class QStringList qstringlist.h + \reentrant + \brief The QStringList class provides a list of strings. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + It is used to store and manipulate strings that logically belong + together. Essentially QStringList is a QValueList of QString + objects. Unlike QStrList, which stores pointers to characters, + QStringList holds real QString objects. It is the class of choice + whenever you work with Unicode strings. QStringList is part of the + \link qtl.html Qt Template Library\endlink. + + Like QString itself, QStringList objects are implicitly shared. + Passing them around as value-parameters is both fast and safe. + + Strings can be added to a list using append(), operator+=() or + operator<<(), e.g. + \code + QStringList fonts; + fonts.append( "Times" ); + fonts += "Courier"; + fonts += "Courier New"; + fonts << "Helvetica [Cronyx]" << "Helvetica [Adobe]"; + \endcode + + String lists have an iterator, QStringList::Iterator(), e.g. + \code + for ( QStringList::Iterator it = fonts.begin(); it != fonts.end(); ++it ) { + cout << *it << ":"; + } + cout << endl; + // Output: + // Times:Courier:Courier New:Helvetica [Cronyx]:Helvetica [Adobe]: + \endcode + + Many Qt functions return const string lists; to iterate over these + you should make a copy and iterate over the copy. + + You can concatenate all the strings in a string list into a single + string (with an optional separator) using join(), e.g. + \code + QString allFonts = fonts.join( ", " ); + cout << allFonts << endl; + // Output: + // Times, Courier, Courier New, Helvetica [Cronyx], Helvetica [Adobe] + \endcode + + You can sort the list with sort(), and extract a new list which + contains only those strings which contain a particular substring + (or match a particular regular expression) using the grep() + functions, e.g. + \code + fonts.sort(); + cout << fonts.join( ", " ) << endl; + // Output: + // Courier, Courier New, Helvetica [Adobe], Helvetica [Cronyx], Times + + QStringList helveticas = fonts.grep( "Helvetica" ); + cout << helveticas.join( ", " ) << endl; + // Output: + // Helvetica [Adobe], Helvetica [Cronyx] + \endcode + + Existing strings can be split into string lists with character, + string or regular expression separators, e.g. + \code + QString s = "Red\tGreen\tBlue"; + QStringList colors = QStringList::split( "\t", s ); + cout << colors.join( ", " ) << endl; + // Output: + // Red, Green, Blue + \endcode +*/ + +/*! + \fn QStringList::QStringList() + + Creates an empty string list. +*/ + +/*! + \fn QStringList::QStringList( const QStringList& l ) + + Creates a copy of the list \a l. This function is very fast + because QStringList is implicitly shared. In most situations this + acts like a deep copy, for example, if this list or the original + one or some other list referencing the same shared data is + modified, the modifying list first makes a copy, i.e. + copy-on-write. + In a threaded environment you may require a real deep copy + \omit see \l QDeepCopy\endomit. +*/ + +/*! + \fn QStringList::QStringList (const QString & i) + + Constructs a string list consisting of the single string \a i. + Longer lists are easily created as follows: + + \code + QStringList items; + items << "Buy" << "Sell" << "Update" << "Value"; + \endcode +*/ + +/*! + \fn QStringList::QStringList (const char* i) + + Constructs a string list consisting of the single latin-1 string \a i. +*/ + +/*! + \fn QStringList::QStringList( const QValueList<QString>& l ) + + Constructs a new string list that is a copy of \a l. +*/ + +/*! + Sorts the list of strings in ascending case-sensitive order. + + Sorting is very fast. It uses the \link qtl.html Qt Template + Library's\endlink efficient HeapSort implementation that has a + time complexity of O(n*log n). + + If you want to sort your strings in an arbitrary order consider + using a QMap. For example you could use a QMap\<QString,QString\> + to create a case-insensitive ordering (e.g. mapping the lowercase + text to the text), or a QMap\<int,QString\> to sort the strings by + some integer index, etc. +*/ +void QStringList::sort() +{ + qHeapSort( *this ); +} + +/*! + \overload + + This version of the function uses a QChar as separator, rather + than a regular expression. + + \sa join() QString::section() +*/ + +QStringList QStringList::split( const QChar &sep, const QString &str, + bool allowEmptyEntries ) +{ + return split( QString(sep), str, allowEmptyEntries ); +} + +/*! + \overload + + This version of the function uses a QString as separator, rather + than a regular expression. + + If \a sep is an empty string, the return value is a list of + one-character strings: split( QString( "" ), "four" ) returns the + four-item list, "f", "o", "u", "r". + + If \a allowEmptyEntries is TRUE, an empty string is inserted in + the list wherever the separator matches twice without intervening + text. + + \sa join() QString::section() +*/ + +QStringList QStringList::split( const QString &sep, const QString &str, + bool allowEmptyEntries ) +{ + QStringList lst; + + int j = 0; + int i = str.find( sep, j ); + + while ( i != -1 ) { + if ( i > j && i <= (int)str.length() ) + lst << str.mid( j, i - j ); + else if ( allowEmptyEntries ) + lst << QString::null; + j = i + sep.length(); + i = str.find( sep, sep.length() > 0 ? j : j+1 ); + } + + int l = str.length() - 1; + if ( str.mid( j, l - j + 1 ).length() > 0 ) + lst << str.mid( j, l - j + 1 ); + else if ( allowEmptyEntries ) + lst << QString::null; + + return lst; +} + +#ifndef QT_NO_REGEXP +/*! + Splits the string \a str into strings wherever the regular + expression \a sep occurs, and returns the list of those strings. + + If \a allowEmptyEntries is TRUE, an empty string is inserted in + the list wherever the separator matches twice without intervening + text. + + For example, if you split the string "a,,b,c" on commas, split() + returns the three-item list "a", "b", "c" if \a allowEmptyEntries + is FALSE (the default), and the four-item list "a", "", "b", "c" + if \a allowEmptyEntries is TRUE. + + If \a sep does not match anywhere in \a str, split() returns a + list consisting of the single string \a str. + + \sa join() QString::section() +*/ + +QStringList QStringList::split( const QRegExp &sep, const QString &str, + bool allowEmptyEntries ) +{ + QStringList lst; + + QRegExp tep = sep; + + int j = 0; + int i = tep.search( str, j ); + + while ( i != -1 ) { + if ( str.mid( j, i - j ).length() > 0 ) + lst << str.mid( j, i - j ); + else if ( allowEmptyEntries ) + lst << QString::null; + if ( tep.matchedLength() == 0 ) + j = i + 1; + else + j = i + tep.matchedLength(); + i = tep.search( str, j ); + } + + int l = str.length() - 1; + if ( str.mid( j, l - j + 1 ).length() > 0 ) + lst << str.mid( j, l - j + 1 ); + else if ( allowEmptyEntries ) + lst << QString::null; + + return lst; +} +#endif + +/*! + Returns a list of all strings containing the substring \a str. + + If \a cs is TRUE, the grep is done case-sensitively; otherwise + case is ignored. +*/ + +QStringList QStringList::grep( const QString &str, bool cs ) const +{ + QStringList res; + for ( QStringList::ConstIterator it = begin(); it != end(); ++it ) + if ( (*it).contains(str, cs) ) + res << *it; + + return res; +} + +#ifndef QT_NO_REGEXP +/*! + \overload + + Returns a list of all the strings that match the regular + expression \a expr. +*/ + +QStringList QStringList::grep( const QRegExp &expr ) const +{ + QStringList res; + for ( QStringList::ConstIterator it = begin(); it != end(); ++it ) + if ( (*it).contains(expr) ) + res << *it; + + return res; +} +#endif + +/*! + Joins the string list into a single string with each element + separated by the string \a sep (which can be empty). + + \sa split() +*/ +QString QStringList::join( const QString &sep ) const +{ + QString res; + bool alredy = FALSE; + for ( QStringList::ConstIterator it = begin(); it != end(); ++it ) { + if ( alredy ) + res += sep; + alredy = TRUE; + res += *it; + } + + return res; +} + +#ifndef QT_NO_DATASTREAM +Q_EXPORT QDataStream &operator>>( QDataStream & s, QStringList& l ) +{ + return s >> (QValueList<QString>&)l; +} + +Q_EXPORT QDataStream &operator<<( QDataStream & s, const QStringList& l ) +{ + return s << (const QValueList<QString>&)l; +} +#endif + +/*! + Converts from an ASCII-QStrList \a ascii to a QStringList (Unicode). +*/ +QStringList QStringList::fromStrList(const QStrList& ascii) +{ + QStringList res; + const char * s; + for ( QStrListIterator it(ascii); (s=it.current()); ++it ) + res << s; + return res; +} + +#endif //QT_NO_STRINGLIST diff --git a/qmake/tools/qtextstream.cpp b/qmake/tools/qtextstream.cpp new file mode 100644 index 0000000..75c6531 --- a/dev/null +++ b/qmake/tools/qtextstream.cpp @@ -0,0 +1,2593 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QTextStream class +** +** Created : 940922 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qtextstream.h" + +#ifndef QT_NO_TEXTSTREAM +#include "qtextcodec.h" +#include "qregexp.h" +#include "qbuffer.h" +#include "qfile.h" +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#if defined(Q_OS_WIN32) +#include <windows.h> +#endif + +/*! + \class QTextStream qtextstream.h + \reentrant + \brief The QTextStream class provides basic functions for reading + and writing text using a QIODevice. + + \ingroup io + \ingroup text + \mainclass + + The text stream class has a functional interface that is very + similar to that of the standard C++ iostream class. + + Qt provides several global functions similar to the ones in iostream: + \table + \header \i Function \i Meaning + \row \i bin \i sets the QTextStream to read/write binary numbers + \row \i oct \i sets the QTextStream to read/write octal numbers + \row \i dec \i sets the QTextStream to read/write decimal numbers + \row \i hex \i sets the QTextStream to read/write hexadecimal numbers + \row \i endl \i forces a line break + \row \i flush \i forces the QIODevice to flush any buffered data + \row \i ws \i eats any available whitespace (on input) + \row \i reset \i resets the QTextStream to its default mode (see reset()) + \row \i qSetW(int) \i sets the \link width() field width \endlink + to the given argument + \row \i qSetFill(int) \i sets the \link fill() fill character + \endlink to the given argument + \row \i qSetPrecision(int) \i sets the \link precision() precision + \endlink to the given argument + \endtable + + \warning By default QTextStream will automatically detect whether + integers in the stream are in decimal, octal, hexadecimal or + binary format when reading from the stream. In particular, a + leading '0' signifies octal, i.e. the sequence "0100" will be + interpreted as 64. + + The QTextStream class reads and writes text; it is not appropriate + for dealing with binary data (but QDataStream is). + + By default, output of Unicode text (i.e. QString) is done using + the local 8-bit encoding. This can be changed using the + setEncoding() method. For input, the QTextStream will auto-detect + standard Unicode "byte order marked" text files; otherwise the + local 8-bit encoding is used. + + The QIODevice is set in the constructor, or later using + setDevice(). If the end of the input is reached atEnd() returns + TRUE. Data can be read into variables of the appropriate type + using the operator>>() overloads, or read in its entirety into a + single string using read(), or read a line at a time using + readLine(). Whitespace can be skipped over using skipWhiteSpace(). + You can set flags for the stream using flags() or setf(). The + stream also supports width(), precision() and fill(); use reset() + to reset the defaults. + + \sa QDataStream +*/ + +/*! + \enum QTextStream::Encoding + + \value Locale + \value Latin1 + \value Unicode + \value UnicodeNetworkOrder + \value UnicodeReverse + \value RawUnicode + \value UnicodeUTF8 + + See setEncoding() for an explanation of the encodings. +*/ + +/* + \class QTSManip + + \brief The QTSManip class is an internal helper class for the + QTextStream. + + It is generally a very bad idea to use this class directly in + application programs. + + \internal + + This class makes it possible to give the QTextStream function objects + with arguments, like this: + \code + QTextStream cout( stdout, IO_WriteOnly ); + cout << setprecision( 8 ); // QTSManip used here! + cout << 3.14159265358979323846; + \endcode + + The setprecision() function returns a QTSManip object. + The QTSManip object contains a pointer to a member function in + QTextStream and an integer argument. + When serializing a QTSManip into a QTextStream, the function + is executed with the argument. +*/ + +/*! \fn QTSManip::QTSManip( QTSMFI m, int a ) + + Constructs a QTSManip object which will call \a m (a member function + in QTextStream which accepts a single int) with argument \a a when + QTSManip::exec() is called. Used internally in e.g. endl: + + \code + s << "some text" << endl << "more text"; + \endcode +*/ + +/*! \fn void QTSManip::exec( QTextStream& s ) + + Calls the member function specified in the constructor, for object + \a s. Used internally in e.g. endl: + + \code + s << "some text" << endl << "more text"; + \endcode +*/ + + +/***************************************************************************** + QTextStream member functions + *****************************************************************************/ + +#if defined(QT_CHECK_STATE) +#undef CHECK_STREAM_PRECOND +#define CHECK_STREAM_PRECOND if ( !dev ) { \ + qWarning( "QTextStream: No device" ); \ + return *this; } +#else +#define CHECK_STREAM_PRECOND +#endif + + +#define I_SHORT 0x0010 +#define I_INT 0x0020 +#define I_LONG 0x0030 +#define I_TYPE_MASK 0x00f0 + +#define I_BASE_2 QTS::bin +#define I_BASE_8 QTS::oct +#define I_BASE_10 QTS::dec +#define I_BASE_16 QTS::hex +#define I_BASE_MASK (QTS::bin | QTS::oct | QTS::dec | QTS::hex) + +#define I_SIGNED 0x0100 +#define I_UNSIGNED 0x0200 +#define I_SIGN_MASK 0x0f00 + + +static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character. +static const uint getline_buf_size = 256; // bufsize used by ts_getline() + +const int QTextStream::basefield = I_BASE_MASK; +const int QTextStream::adjustfield = ( QTextStream::left | + QTextStream::right | + QTextStream::internal ); +const int QTextStream::floatfield = ( QTextStream::scientific | + QTextStream::fixed ); + + +class QTextStreamPrivate { +public: +#ifndef QT_NO_TEXTCODEC + QTextStreamPrivate() + : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { } + ~QTextStreamPrivate() { + delete decoder; + delete encoder; + } + QTextDecoder *decoder; + QTextEncoder *encoder; +#else + QTextStreamPrivate() : sourceType( NotSet ) { } + ~QTextStreamPrivate() { } +#endif + QString ungetcBuf; + + enum SourceType { NotSet, IODevice, String, ByteArray, File }; + SourceType sourceType; +}; + + +// skips whitespace and returns the first non-whitespace character +QChar QTextStream::eat_ws() +{ + QChar c; + do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) ); + return c; +} + +void QTextStream::init() +{ + // ### ungetcBuf = QEOF; + dev = 0; + owndev = FALSE; + mapper = 0; + d = new QTextStreamPrivate; + doUnicodeHeader = TRUE; // autodetect + latin1 = TRUE; // should use locale? + internalOrder = QChar::networkOrdered(); + networkOrder = TRUE; +} + +/*! + Constructs a data stream that has no IO device. +*/ + +QTextStream::QTextStream() +{ + init(); + setEncoding( Locale ); //### + reset(); + d->sourceType = QTextStreamPrivate::NotSet; +} + +/*! + Constructs a text stream that uses the IO device \a iod. +*/ + +QTextStream::QTextStream( QIODevice *iod ) +{ + init(); + setEncoding( Locale ); //### + dev = iod; + reset(); + d->sourceType = QTextStreamPrivate::IODevice; +} + +// TODO: use special-case handling of this case in QTextStream, and +// simplify this class to only deal with QChar or QString data. +class QStringBuffer : public QIODevice { +public: + QStringBuffer( QString* str ); + ~QStringBuffer(); + bool open( int m ); + void close(); + void flush(); + Offset size() const; + Offset at() const; + bool at( Offset pos ); + Q_LONG readBlock( char *p, Q_ULONG len ); + Q_LONG writeBlock( const char *p, Q_ULONG len ); + int getch(); + int putch( int ch ); + int ungetch( int ch ); +protected: + QString* s; + +private: // Disabled copy constructor and operator= + QStringBuffer( const QStringBuffer & ); + QStringBuffer &operator=( const QStringBuffer & ); +}; + + +QStringBuffer::QStringBuffer( QString* str ) +{ + s = str; +} + +QStringBuffer::~QStringBuffer() +{ +} + + +bool QStringBuffer::open( int m ) +{ + if ( !s ) { +#if defined(QT_CHECK_STATE) + qWarning( "QStringBuffer::open: No string" ); +#endif + return FALSE; + } + if ( isOpen() ) { // buffer already open +#if defined(QT_CHECK_STATE) + qWarning( "QStringBuffer::open: Buffer already open" ); +#endif + return FALSE; + } + setMode( m ); + if ( m & IO_Truncate ) { // truncate buffer + s->truncate( 0 ); + } + if ( m & IO_Append ) { // append to end of buffer + ioIndex = s->length()*sizeof(QChar); + } else { + ioIndex = 0; + } + setState( IO_Open ); + setStatus( 0 ); + return TRUE; +} + +void QStringBuffer::close() +{ + if ( isOpen() ) { + setFlags( IO_Direct ); + ioIndex = 0; + } +} + +void QStringBuffer::flush() +{ +} + +QIODevice::Offset QStringBuffer::size() const +{ + return s ? s->length()*sizeof(QChar) : 0; +} + +QIODevice::Offset QStringBuffer::at() const +{ + return ioIndex; +} + +bool QStringBuffer::at( Offset pos ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + qWarning( "QStringBuffer::at: Buffer is not open" ); + return FALSE; + } +#endif + if ( pos >= s->length()*2 ) { +#if defined(QT_CHECK_RANGE) +#if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) + qWarning( "QStringBuffer::at: Index %llu out of range", pos ); +#else + qWarning( "QStringBuffer::at: Index %lu out of range", pos ); +#endif +#endif + return FALSE; + } + ioIndex = pos; + return TRUE; +} + + +Q_LONG QStringBuffer::readBlock( char *p, Q_ULONG len ) +{ +#if defined(QT_CHECK_STATE) + Q_CHECK_PTR( p ); + if ( !isOpen() ) { // buffer not open + qWarning( "QStringBuffer::readBlock: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QStringBuffer::readBlock: Read operation not permitted" ); + return -1; + } +#endif + if ( ioIndex + len > s->length()*sizeof(QChar) ) { + // overflow + if ( (uint)ioIndex >= s->length()*sizeof(QChar) ) { + setStatus( IO_ReadError ); + return -1; + } else { + len = s->length()*2 - (uint)ioIndex; + } + } + memcpy( p, ((const char*)(s->unicode()))+ioIndex, len ); + ioIndex += len; + return len; +} + +Q_LONG QStringBuffer::writeBlock( const char *p, Q_ULONG len ) +{ +#if defined(QT_CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QStringBuffer::writeBlock: Null pointer error" ); +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QStringBuffer::writeBlock: Buffer not open" ); + return -1; + } + if ( !isWritable() ) { // writing not permitted + qWarning( "QStringBuffer::writeBlock: Write operation not permitted" ); + return -1; + } + if ( ioIndex&1 ) { + qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" ); + return -1; + } + if ( len&1 ) { + qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" ); + return -1; + } +#endif + s->replace(ioIndex/2, len/2, (QChar*)p, len/2); + ioIndex += len; + return len; +} + +int QStringBuffer::getch() +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QStringBuffer::getch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QStringBuffer::getch: Read operation not permitted" ); + return -1; + } +#endif + if ( (uint)ioIndex >= s->length()*2 ) { // overflow + setStatus( IO_ReadError ); + return -1; + } + return (int) *( (const char *) s->unicode() + ioIndex++ ); +} + +int QStringBuffer::putch( int ch ) +{ + char c = ch; + if ( writeBlock(&c,1) < 0 ) + return -1; + else + return ch; +} + +int QStringBuffer::ungetch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { // buffer not open + qWarning( "QStringBuffer::ungetch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QStringBuffer::ungetch: Read operation not permitted" ); + return -1; + } +#endif + if ( ch != -1 ) { // something to do with eof + if ( ioIndex ) + ioIndex--; + else + ch = -1; + } + return ch; +} + + +/*! + Constructs a text stream that operates on the Unicode QString, \a + str, through an internal device. The \a filemode argument is + passed to the device's open() function; see \l{QIODevice::mode()}. + + If you set an encoding or codec with setEncoding() or setCodec(), + this setting is ignored for text streams that operate on QString. + + Example: + \code + QString str; + QTextStream ts( &str, IO_WriteOnly ); + ts << "pi = " << 3.14; // str == "pi = 3.14" + \endcode + + Writing data to the text stream will modify the contents of the + string. The string will be expanded when data is written beyond + the end of the string. Note that the string will not be truncated: + \code + QString str = "pi = 3.14"; + QTextStream ts( &str, IO_WriteOnly ); + ts << "2+2 = " << 2+2; // str == "2+2 = 414" + \endcode + + Note that because QString is Unicode, you should not use + readRawBytes() or writeRawBytes() on such a stream. +*/ + +QTextStream::QTextStream( QString* str, int filemode ) +{ + // TODO: optimize for this case as it becomes more common + // (see QStringBuffer above) + init(); + dev = new QStringBuffer( str ); + ((QStringBuffer *)dev)->open( filemode ); + owndev = TRUE; + setEncoding(RawUnicode); + reset(); + d->sourceType = QTextStreamPrivate::String; +} + +/*! \obsolete + + This constructor is equivalent to the constructor taking a QString* + parameter. +*/ + +QTextStream::QTextStream( QString& str, int filemode ) +{ + init(); + dev = new QStringBuffer( &str ); + ((QStringBuffer *)dev)->open( filemode ); + owndev = TRUE; + setEncoding(RawUnicode); + reset(); + d->sourceType = QTextStreamPrivate::String; +} + +/*! + Constructs a text stream that operates on the byte array, \a a, + through an internal QBuffer device. The \a mode argument is passed + to the device's open() function; see \l{QIODevice::mode()}. + + Example: + \code + QByteArray array; + QTextStream ts( array, IO_WriteOnly ); + ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" + \endcode + + Writing data to the text stream will modify the contents of the + array. The array will be expanded when data is written beyond the + end of the string. + + Same example, using a QBuffer: + \code + QByteArray array; + QBuffer buf( array ); + buf.open( IO_WriteOnly ); + QTextStream ts( &buf ); + ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" + buf.close(); + \endcode +*/ + +QTextStream::QTextStream( QByteArray a, int mode ) +{ + init(); + dev = new QBuffer( a ); + ((QBuffer *)dev)->open( mode ); + owndev = TRUE; + setEncoding( Latin1 ); //### Locale??? + reset(); + d->sourceType = QTextStreamPrivate::ByteArray; +} + +/*! + Constructs a text stream that operates on an existing file handle + \a fh through an internal QFile device. The \a mode argument is + passed to the device's open() function; see \l{QIODevice::mode()}. + + Note that if you create a QTextStream \c cout or another name that + is also used for another variable of a different type, some + linkers may confuse the two variables, which will often cause + crashes. +*/ + +QTextStream::QTextStream( FILE *fh, int mode ) +{ + init(); + setEncoding( Locale ); //### + dev = new QFile; + ((QFile *)dev)->open( mode, fh ); + owndev = TRUE; + reset(); + d->sourceType = QTextStreamPrivate::File; +} + +/*! + Destroys the text stream. + + The destructor does not affect the current IO device. +*/ + +QTextStream::~QTextStream() +{ + if ( owndev ) + delete dev; + delete d; +} + +/*! + Positions the read pointer at the first non-whitespace character. +*/ +void QTextStream::skipWhiteSpace() +{ + ts_ungetc( eat_ws() ); +} + + +/*! + Tries to read \a len characters from the stream and stores them in + \a buf. Returns the number of characters really read. + + \warning There will no QEOF appended if the read reaches the end + of the file. EOF is reached when the return value does not equal + \a len. +*/ +uint QTextStream::ts_getbuf( QChar* buf, uint len ) +{ + if( len < 1 ) + return 0; + + uint rnum=0; // the number of QChars really read + + if ( d && d->ungetcBuf.length() ) { + while( rnum < len && rnum < d->ungetcBuf.length() ) { + *buf = d->ungetcBuf.constref( rnum ); + buf++; + rnum++; + } + d->ungetcBuf = d->ungetcBuf.mid( rnum ); + if ( rnum >= len ) + return rnum; + } + + // we use dev->ungetch() for one of the bytes of the unicode + // byte-order mark, but a local unget hack for the other byte: + int ungetHack = EOF; + + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; // only at the top + int c1 = dev->getch(); + if ( c1 == EOF ) + return rnum; + int c2 = dev->getch(); + if ( c1 == 0xfe && c2 == 0xff ) { + mapper = 0; + latin1 = FALSE; + internalOrder = QChar::networkOrdered(); + networkOrder = TRUE; + } else if ( c1 == 0xff && c2 == 0xfe ) { + mapper = 0; + latin1 = FALSE; + internalOrder = !QChar::networkOrdered(); + networkOrder = FALSE; + } else { + if ( c2 != EOF ) { + dev->ungetch( c2 ); + ungetHack = c1; + } else { + /* + A small bug might hide here. If only the first byte + of a file has made it so far, and that first byte + is half of the byte-order mark, then the utfness + will not be detected. + */ + dev->ungetch( c1 ); + } + } + } + +#ifndef QT_NO_TEXTCODEC + if ( mapper ) { + bool shortRead = FALSE; + if ( !d->decoder ) + d->decoder = mapper->makeDecoder(); + while( rnum < len ) { + QString s; + bool readBlock = !( len == 1+rnum ); + for (;;) { + // for efficiency: normally read a whole block + if ( readBlock ) { + // guess buffersize; this may be wrong (too small or too + // big). But we can handle this (either iterate reading + // or use ungetcBuf). + // Note that this might cause problems for codecs where + // one byte can result in >1 Unicode Characters if bytes + // are written to the stream in the meantime (loss of + // synchronicity). + uint rlen = len - rnum; + char *cbuf = new char[ rlen ]; + if ( ungetHack != EOF ) { + rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); + cbuf[0] = (char)ungetHack; + ungetHack = EOF; + } else { + rlen = dev->readBlock( cbuf, rlen ); + } + s += d->decoder->toUnicode( cbuf, rlen ); + delete[] cbuf; + // use buffered reading only for the first time, because we + // have to get the stream synchronous again (this is easier + // with single character reading) + readBlock = FALSE; + } + // get stream (and codec) in sync + int c; + if ( ungetHack == EOF ) { + c = dev->getch(); + } else { + c = ungetHack; + ungetHack = EOF; + } + if ( c == EOF ) { + shortRead = TRUE; + break; + } + char b = c; + uint lengthBefore = s.length(); + s += d->decoder->toUnicode( &b, 1 ); + if ( s.length() > lengthBefore ) + break; // it seems we are in sync now + } + uint i = 0; + uint end = QMIN( len-rnum, s.length() ); + while( i < end ) { + *buf = s.constref(i++); + buf++; + } + rnum += end; + if ( s.length() > i ) + // could be = but append is clearer + d->ungetcBuf.append( s.mid( i ) ); + if ( shortRead ) + return rnum; + } + } else +#endif + if ( latin1 ) { + if ( len == 1+rnum ) { + // use this method for one character because it is more efficient + // (arnt doubts whether it makes a difference, but lets it stand) + int c = (ungetHack == EOF) ? dev->getch() : ungetHack; + if ( c != EOF ) { + *buf = (char)c; + buf++; + rnum++; + } + } else { + if ( ungetHack != EOF ) { + *buf = (char)ungetHack; + buf++; + rnum++; + ungetHack = EOF; + } + char *cbuf = new char[len - rnum]; + while ( !dev->atEnd() && rnum < len ) { + uint rlen = len - rnum; + rlen = dev->readBlock( cbuf, rlen ); + char *it = cbuf; + char *end = cbuf + rlen; + while ( it < end ) { + *buf = *it; + buf++; + it++; + } + rnum += rlen; + } + delete[] cbuf; + } + } else { // UCS-2 or UTF-16 + if ( len == 1+rnum ) { + int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack; + if ( c1 == EOF ) + return rnum; + int c2 = dev->getch(); + if ( c2 == EOF ) + return rnum; + + if ( networkOrder ) { + *buf = QChar( c2, c1 ); + } else { + *buf = QChar( c1, c2 ); + } + buf++; + rnum++; + } else { + char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible + while ( !dev->atEnd() && rnum < len ) { + uint rlen = 2 * ( len-rnum ); + if ( ungetHack != EOF ) { + rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); + cbuf[0] = (char)ungetHack; + ungetHack = EOF; + } else { + rlen = dev->readBlock( cbuf, rlen ); + } + // We can't use an odd number of bytes, so put it back. But + // do it only if we are capable of reading more -- normally + // there should not be an odd number, but the file might be + // truncated or not in UTF-16... + if ( (rlen & 1) == 1 ) + if ( !dev->atEnd() ) + dev->ungetch( cbuf[--rlen] ); + uint i = 0; + if ( networkOrder ) { + while( i < rlen ) { + *buf = QChar( cbuf[i+1], cbuf[i] ); + buf++; + i+=2; + } + } else { + while( i < rlen ) { + *buf = QChar( cbuf[i], cbuf[i+1] ); + buf++; + i+=2; + } + } + rnum += i/2; + } + delete[] cbuf; + } + } + return rnum; +} + +/*! + Tries to read one line, but at most len characters from the stream + and stores them in \a buf. + + Returns the number of characters really read. Newlines are not + stripped. + + There will be a QEOF appended if the read reaches the end of file; + this is different to ts_getbuf(). + + This function works only if a newline (as byte) is also a newline + (as resulting character) since it uses QIODevice::readLine(). So + use it only for such codecs where this is true! + + This function is (almost) a no-op for UTF 16. Don't use it if + doUnicodeHeader is TRUE! +*/ +uint QTextStream::ts_getline( QChar* buf ) +{ + uint rnum=0; // the number of QChars really read + char cbuf[ getline_buf_size+1 ]; + + if ( d && d->ungetcBuf.length() ) { + while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) { + buf[rnum] = d->ungetcBuf.constref(rnum); + rnum++; + } + d->ungetcBuf = d->ungetcBuf.mid( rnum ); + if ( rnum >= getline_buf_size ) + return rnum; + } + +#ifndef QT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->decoder ) + d->decoder = mapper->makeDecoder(); + QString s; + bool readBlock = TRUE; + for (;;) { + // for efficiency: try to read a line + if ( readBlock ) { + int rlen = getline_buf_size - rnum; + rlen = dev->readLine( cbuf, rlen+1 ); + if ( rlen == -1 ) + rlen = 0; + s += d->decoder->toUnicode( cbuf, rlen ); + readBlock = FALSE; + } + if ( dev->atEnd() + || s.at( s.length()-1 ) == '\n' + || s.at( s.length()-1 ) == '\r' + ) { + break; + } else { + // get stream (and codec) in sync + int c; + c = dev->getch(); + if ( c == EOF ) { + break; + } + char b = c; + uint lengthBefore = s.length(); + s += d->decoder->toUnicode( &b, 1 ); + if ( s.length() > lengthBefore ) + break; // it seems we are in sync now + } + } + uint i = 0; + while( rnum < getline_buf_size && i < s.length() ) + buf[rnum++] = s.constref(i++); + if ( s.length() > i ) + // could be = but append is clearer + d->ungetcBuf.append( s.mid( i ) ); + if ( rnum < getline_buf_size && dev->atEnd() ) + buf[rnum++] = QEOF; + } else +#endif + if ( latin1 ) { + int rlen = getline_buf_size - rnum; + rlen = dev->readLine( cbuf, rlen+1 ); + if ( rlen == -1 ) + rlen = 0; + char *end = cbuf+rlen; + char *it = cbuf; + buf +=rnum; + while ( it != end ) { + buf->setCell( *(it++) ); + buf->setRow( 0 ); + buf++; + } + rnum += rlen; + if ( rnum < getline_buf_size && dev->atEnd() ) + buf[1] = QEOF; + } + return rnum; +} + + +/*! + Puts one character into the stream. +*/ +void QTextStream::ts_putc( QChar c ) +{ +#ifndef QT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->encoder ) + d->encoder = mapper->makeEncoder(); + int len = 1; + QString s = c; + QCString block = d->encoder->fromUnicode( s, len ); + dev->writeBlock( block, len ); + } else +#endif + if ( latin1 ) { + if ( c.row() ) + dev->putch( '?' ); // unknown character + else + dev->putch( c.cell() ); + } else { + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + ts_putc( QChar::byteOrderMark ); + } + if ( internalOrder ) { + // this case is needed by QStringBuffer + dev->writeBlock( (char*)&c, sizeof(QChar) ); + } else if ( networkOrder ) { + dev->putch( c.row() ); + dev->putch( c.cell() ); + } else { + dev->putch( c.cell() ); + dev->putch( c.row() ); + } + } +} + +/*! + Puts one character into the stream. +*/ +void QTextStream::ts_putc( int ch ) +{ + ts_putc( QChar((ushort)ch) ); +} + +bool QTextStream::ts_isdigit( QChar c ) +{ + return c.isDigit(); +} + +bool QTextStream::ts_isspace( QChar c ) +{ + return c.isSpace(); +} + +void QTextStream::ts_ungetc( QChar c ) +{ + if ( c.unicode() == 0xffff ) + return; + + d->ungetcBuf.prepend( c ); +} + + + +/*! + Reads \a len bytes from the stream into \a s and returns a + reference to the stream. + + The buffer \a s must be preallocated. + + Note that no encoding is done by this function. + + \warning The behavior of this function is undefined unless the + stream's encoding is set to Unicode or Latin1. + + \sa QIODevice::readBlock() +*/ + +QTextStream &QTextStream::readRawBytes( char *s, uint len ) +{ + dev->readBlock( s, len ); + return *this; +} + +/*! + Writes the \a len bytes from \a s to the stream and returns a + reference to the stream. + + Note that no encoding is done by this function. + + \sa QIODevice::writeBlock() +*/ + +QTextStream &QTextStream::writeRawBytes( const char* s, uint len ) +{ + dev->writeBlock( s, len ); + return *this; +} + + +QTextStream &QTextStream::writeBlock( const char* p, uint len ) +{ + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + if ( !mapper && !latin1 ) + ts_putc( QChar::byteOrderMark ); + } + // QCString and const char * are treated as Latin-1 + if ( !mapper && latin1 ) { + dev->writeBlock( p, len ); + } else if ( !mapper && internalOrder ) { + QChar *u = new QChar[len]; + for ( uint i = 0; i < len; i++ ) + u[i] = p[i]; + dev->writeBlock( (char*)u, len * sizeof(QChar) ); + delete [] u; + } else { + for ( uint i = 0; i < len; i++ ) + ts_putc( (uchar)p[i] ); + } + return *this; +} + +QTextStream &QTextStream::writeBlock( const QChar* p, uint len ) +{ +#ifndef QT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->encoder ) + d->encoder = mapper->makeEncoder(); + QConstString s( p, len ); + int l = len; + QCString block = d->encoder->fromUnicode( s.string(), l ); + dev->writeBlock( block, l ); + } else +#endif + if ( latin1 ) { + char *str = QString::unicodeToAscii( p, len ); + dev->writeBlock( str, len ); + delete [] str; + } else if ( internalOrder ) { + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + ts_putc( QChar::byteOrderMark ); + } + dev->writeBlock( (char*)p, sizeof(QChar)*len ); + } else { + for (uint i=0; i<len; i++) + ts_putc( p[i] ); + } + return *this; +} + +/*! + Resets the text stream. + + \list + \i All flags are set to 0. + \i The field width is set to 0. + \i The fill character is set to ' ' (Space). + \i The precision is set to 6. + \endlist + + \sa setf(), width(), fill(), precision() +*/ + +void QTextStream::reset() +{ + fflags = 0; + fwidth = 0; + fillchar = ' '; + fprec = 6; +} + +/*! + \fn QIODevice *QTextStream::device() const + + Returns the IO device currently set. + + \sa setDevice(), unsetDevice() +*/ + +/*! + Sets the IO device to \a iod. + + \sa device(), unsetDevice() +*/ + +void QTextStream::setDevice( QIODevice *iod ) +{ + if ( owndev ) { + delete dev; + owndev = FALSE; + } + dev = iod; + d->sourceType = QTextStreamPrivate::IODevice; +} + +/*! + Unsets the IO device. Equivalent to setDevice( 0 ). + + \sa device(), setDevice() +*/ + +void QTextStream::unsetDevice() +{ + setDevice( 0 ); + d->sourceType = QTextStreamPrivate::NotSet; +} + +/*! + \fn bool QTextStream::atEnd() const + + Returns TRUE if the IO device has reached the end position (end of + the stream or file) or if there is no IO device set; otherwise + returns FALSE. + + \sa QIODevice::atEnd() +*/ + +/*!\fn bool QTextStream::eof() const + + \obsolete + + This function has been renamed to atEnd(). + + \sa QIODevice::atEnd() +*/ + +/***************************************************************************** + QTextStream read functions + *****************************************************************************/ + + +/*! + \overload + + Reads a char \a c from the stream and returns a reference to the + stream. Note that whitespace is skipped. +*/ + +QTextStream &QTextStream::operator>>( char &c ) +{ + CHECK_STREAM_PRECOND + c = eat_ws(); + return *this; +} + +/*! + Reads a char \a c from the stream and returns a reference to the + stream. Note that whitespace is \e not skipped. +*/ + +QTextStream &QTextStream::operator>>( QChar &c ) +{ + CHECK_STREAM_PRECOND + c = ts_getc(); + return *this; +} + + +ulong QTextStream::input_bin() +{ + ulong val = 0; + QChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( dv == 0 || dv == 1 ) { + val = ( val << 1 ) + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( ch != QEOF ) + ts_ungetc( ch ); + return val; +} + +ulong QTextStream::input_oct() +{ + ulong val = 0; + QChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( dv >= 0 && dv <= 7 ) { + val = ( val << 3 ) + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( dv == 8 || dv == 9 ) { + while ( ts_isdigit(ch) ) + ch = ts_getc(); + } + if ( ch != QEOF ) + ts_ungetc( ch ); + return val; +} + +ulong QTextStream::input_dec() +{ + ulong val = 0; + QChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( ts_isdigit(ch) ) { + val = val * 10 + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( ch != QEOF ) + ts_ungetc( ch ); + return val; +} + +ulong QTextStream::input_hex() +{ + ulong val = 0; + QChar ch = eat_ws(); + char c = ch; + while ( isxdigit((uchar) c) ) { + val <<= 4; + if ( ts_isdigit(c) ) + val += c - '0'; + else + val += 10 + tolower( (uchar) c ) - 'a'; + c = ch = ts_getc(); + } + if ( ch != QEOF ) + ts_ungetc( ch ); + return val; +} + +long QTextStream::input_int() +{ + long val; + QChar ch; + char c; + switch ( flags() & basefield ) { + case bin: + val = (long)input_bin(); + break; + case oct: + val = (long)input_oct(); + break; + case dec: + c = ch = eat_ws(); + if ( ch == QEOF ) { + val = 0; + } else { + if ( !(c == '-' || c == '+') ) + ts_ungetc( ch ); + if ( c == '-' ) { + ulong v = input_dec(); + if ( v ) { // ensure that LONG_MIN can be read + v--; + val = -((long)v) - 1; + } else { + val = 0; + } + } else { + val = (long)input_dec(); + } + } + break; + case hex: + val = (long)input_hex(); + break; + default: + val = 0; + c = ch = eat_ws(); + if ( c == '0' ) { // bin, oct or hex + c = ch = ts_getc(); + if ( tolower((uchar) c) == 'x' ) + val = (long)input_hex(); + else if ( tolower((uchar) c) == 'b' ) + val = (long)input_bin(); + else { // octal + ts_ungetc( ch ); + if ( c >= '0' && c <= '7' ) { + val = (long)input_oct(); + } else { + val = 0; + } + } + } else if ( ts_isdigit(ch) ) { + ts_ungetc( ch ); + val = (long)input_dec(); + } else if ( c == '-' || c == '+' ) { + ulong v = input_dec(); + if ( c == '-' ) { + if ( v ) { // ensure that LONG_MIN can be read + v--; + val = -((long)v) - 1; + } else { + val = 0; + } + } else { + val = (long)v; + } + } + } + return val; +} + +// +// We use a table-driven FSM to parse floating point numbers +// strtod() cannot be used directly since we're reading from a QIODevice +// + +double QTextStream::input_double() +{ + const int Init = 0; // states + const int Sign = 1; + const int Mantissa = 2; + const int Dot = 3; + const int Abscissa = 4; + const int ExpMark = 5; + const int ExpSign = 6; + const int Exponent = 7; + const int Done = 8; + + const int InputSign = 1; // input tokens + const int InputDigit = 2; + const int InputDot = 3; + const int InputExp = 4; + + static const uchar table[8][5] = { + /* None InputSign InputDigit InputDot InputExp */ + { 0, Sign, Mantissa, Dot, 0, }, // Init + { 0, 0, Mantissa, Dot, 0, }, // Sign + { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa + { 0, 0, Abscissa, 0, 0, }, // Dot + { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa + { 0, ExpSign, Exponent, 0, 0, }, // ExpMark + { 0, 0, Exponent, 0, 0, }, // ExpSign + { Done, Done, Exponent, Done, Done } // Exponent + }; + + int state = Init; // parse state + int input; // input token + + char buf[256]; + int i = 0; + QChar c = eat_ws(); + + for (;;) { + + switch ( c ) { + case '+': + case '-': + input = InputSign; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + input = InputDigit; + break; + case '.': + input = InputDot; + break; + case 'e': + case 'E': + input = InputExp; + break; + default: + input = 0; + break; + } + + state = table[state][input]; + + if ( state == 0 || state == Done || i > 250 ) { + if ( i > 250 ) { // ignore rest of digits + do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) ); + } + if ( c != QEOF ) + ts_ungetc( c ); + buf[i] = '\0'; + char *end; + return strtod( buf, &end ); + } + + buf[i++] = c; + c = ts_getc(); + } + +#if !defined(Q_CC_EDG) + return 0.0; +#endif +} + + +/*! + \overload + + Reads a signed \c short integer \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +QTextStream &QTextStream::operator>>( signed short &i ) +{ + CHECK_STREAM_PRECOND + i = (signed short)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c short integer \a i from the stream and + returns a reference to the stream. See flags() for an explanation + of the expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned short &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned short)input_int(); + return *this; +} + + +/*! + \overload + + Reads a signed \c int \a i from the stream and returns a reference + to the stream. See flags() for an explanation of the expected + input format. +*/ + +QTextStream &QTextStream::operator>>( signed int &i ) +{ + CHECK_STREAM_PRECOND + i = (signed int)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned int &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned int)input_int(); + return *this; +} + + +/*! + \overload + + Reads a signed \c long int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +QTextStream &QTextStream::operator>>( signed long &i ) +{ + CHECK_STREAM_PRECOND + i = (signed long)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c long int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned long &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned long)input_int(); + return *this; +} + + +/*! + \overload + + Reads a \c float \a f from the stream and returns a reference to + the stream. See flags() for an explanation of the expected input + format. +*/ + +QTextStream &QTextStream::operator>>( float &f ) +{ + CHECK_STREAM_PRECOND + f = (float)input_double(); + return *this; +} + + +/*! + \overload + + Reads a \c double \a f from the stream and returns a reference to + the stream. See flags() for an explanation of the expected input + format. +*/ + +QTextStream &QTextStream::operator>>( double &f ) +{ + CHECK_STREAM_PRECOND + f = input_double(); + return *this; +} + + +/*! + \overload + + Reads a "word" from the stream into \a s and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +QTextStream &QTextStream::operator>>( char *s ) +{ + CHECK_STREAM_PRECOND + int maxlen = width( 0 ); + QChar c = eat_ws(); + if ( !maxlen ) + maxlen = -1; + while ( c != QEOF ) { + if ( ts_isspace(c) || maxlen-- == 0 ) { + ts_ungetc( c ); + break; + } + *s++ = c; + c = ts_getc(); + } + + *s = '\0'; + return *this; +} + +/*! + \overload + + Reads a "word" from the stream into \a str and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +QTextStream &QTextStream::operator>>( QString &str ) +{ + CHECK_STREAM_PRECOND + str=QString::fromLatin1(""); + QChar c = eat_ws(); + + while ( c != QEOF ) { + if ( ts_isspace(c) ) { + ts_ungetc( c ); + break; + } + str += c; + c = ts_getc(); + } + return *this; +} + +/*! + \overload + + Reads a "word" from the stream into \a str and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +QTextStream &QTextStream::operator>>( QCString &str ) +{ + CHECK_STREAM_PRECOND + QCString *dynbuf = 0; + const int buflen = 256; + char buffer[buflen]; + char *s = buffer; + int i = 0; + QChar c = eat_ws(); + + while ( c != QEOF ) { + if ( ts_isspace(c) ) { + ts_ungetc( c ); + break; + } + if ( i >= buflen-1 ) { + if ( !dynbuf ) { // create dynamic buffer + dynbuf = new QCString(buflen*2); + memcpy( dynbuf->data(), s, i ); // copy old data + } else if ( i >= (int)dynbuf->size()-1 ) { + dynbuf->resize( dynbuf->size()*2 ); + } + s = dynbuf->data(); + } + s[i++] = c; + c = ts_getc(); + } + str.resize( i+1 ); + memcpy( str.data(), s, i ); + delete dynbuf; + return *this; +} + + +/*! + Reads a line from the stream and returns a string containing the + text. + + The returned string does not contain any trailing newline or + carriage return. Note that this is different from + QIODevice::readLine(), which does not strip the newline at the end + of the line. + + On EOF you will get a QString that is null. On reading an empty + line the returned QString is empty but not null. + + \sa QIODevice::readLine() +*/ + +QString QTextStream::readLine() +{ +#if defined(QT_CHECK_STATE) + if ( !dev ) { + qWarning( "QTextStream::readLine: No device" ); + return QString::null; + } +#endif + bool readCharByChar = TRUE; + QString result; +#if 0 + if ( !doUnicodeHeader && ( + (latin1) || + (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8 + ) ) { + readCharByChar = FALSE; + // use optimized read line + QChar c[getline_buf_size]; + int pos = 0; + bool eof = FALSE; + + for (;;) { + pos = ts_getline( c ); + if ( pos == 0 ) { + // something went wrong; try fallback + readCharByChar = TRUE; + //dev->resetStatus(); + break; + } + if ( c[pos-1] == QEOF || c[pos-1] == '\n' ) { + if ( pos>2 && c[pos-1]==QEOF && c[pos-2]=='\n' ) { + result += QString( c, pos-2 ); + } else if ( pos > 1 ) { + result += QString( c, pos-1 ); + } + if ( pos == 1 && c[pos-1] == QEOF ) + eof = TRUE; + break; + } else { + result += QString( c, pos ); + } + } + if ( eof && result.isEmpty() ) + return QString::null; + } +#endif + if ( readCharByChar ) { + // read character by character + const int buf_size = 256; + QChar c[buf_size]; + int pos = 0; + + c[pos] = ts_getc(); + if ( c[pos] == QEOF ) { + return QString::null; + } + + while ( c[pos] != QEOF && c[pos] != '\n' ) { + if ( c[pos] == '\r' ) { // ( handle mac and dos ) + QChar nextc = ts_getc(); + if ( nextc != '\n' ) + ts_ungetc( nextc ); + break; + } + pos++; + if ( pos >= buf_size ) { + result += QString( c, pos ); + pos = 0; + } + c[pos] = ts_getc(); + } + result += QString( c, pos ); + } + + return result; +} + + +/*! + Reads the entire stream and returns a string containing the text. + + \sa QIODevice::readLine() +*/ + +QString QTextStream::read() +{ +#if defined(QT_CHECK_STATE) + if ( !dev ) { + qWarning( "QTextStream::read: No device" ); + return QString::null; + } +#endif + QString result; + const uint bufsize = 512; + QChar buf[bufsize]; + uint i, num, start; + bool skipped_cr = FALSE; + + for (;;) { + num = ts_getbuf(buf,bufsize); + // convert dos (\r\n) and mac (\r) style eol to unix style (\n) + start = 0; + for ( i=0; i<num; i++ ) { + if ( buf[i] == '\r' ) { + // Only skip single cr's preceding lf's + if ( skipped_cr ) { + result += buf[i]; + start++; + } else { + result += QString( &buf[start], i-start ); + start = i+1; + skipped_cr = TRUE; + } + } else { + if ( skipped_cr ) { + if ( buf[i] != '\n' ) { + // Should not have skipped it + result += '\n'; + } + skipped_cr = FALSE; + } + } + } + if ( start < num ) + result += QString( &buf[start], i-start ); + if ( num != bufsize ) // if ( EOF ) + break; + } + return result; +} + + + +/***************************************************************************** + QTextStream write functions + *****************************************************************************/ + +/*! + Writes character \c char to the stream and returns a reference to + the stream. + + The character \a c is assumed to be Latin1 encoded independent of + the Encoding set for the QTextStream. +*/ +QTextStream &QTextStream::operator<<( QChar c ) +{ + CHECK_STREAM_PRECOND + ts_putc( c ); + return *this; +} + +/*! + \overload + + Writes character \a c to the stream and returns a reference to the + stream. +*/ +QTextStream &QTextStream::operator<<( char c ) +{ + CHECK_STREAM_PRECOND + unsigned char uc = (unsigned char) c; + ts_putc( uc ); + return *this; +} + +QTextStream &QTextStream::output_int( int format, ulong n, bool neg ) +{ + static const char hexdigits_lower[] = "0123456789abcdef"; + static const char hexdigits_upper[] = "0123456789ABCDEF"; + CHECK_STREAM_PRECOND + char buf[76]; + register char *p; + int len; + const char *hexdigits; + + switch ( flags() & I_BASE_MASK ) { + + case I_BASE_2: // output binary number + switch ( format & I_TYPE_MASK ) { + case I_SHORT: len=16; break; + case I_INT: len=sizeof(int)*8; break; + case I_LONG: len=32; break; + default: len = 0; + } + p = &buf[74]; // go reverse order + *p = '\0'; + while ( len-- ) { + *--p = (char)(n&1) + '0'; + n >>= 1; + if ( !n ) + break; + } + if ( flags() & showbase ) { // show base + *--p = (flags() & uppercase) ? 'B' : 'b'; + *--p = '0'; + } + break; + + case I_BASE_8: // output octal number + p = &buf[74]; + *p = '\0'; + do { + *--p = (char)(n&7) + '0'; + n >>= 3; + } while ( n ); + if ( flags() & showbase ) + *--p = '0'; + break; + + case I_BASE_16: // output hexadecimal number + p = &buf[74]; + *p = '\0'; + hexdigits = (flags() & uppercase) ? + hexdigits_upper : hexdigits_lower; + do { + *--p = hexdigits[(int)n&0xf]; + n >>= 4; + } while ( n ); + if ( flags() & showbase ) { + *--p = (flags() & uppercase) ? 'X' : 'x'; + *--p = '0'; + } + break; + + default: // decimal base is default + p = &buf[74]; + *p = '\0'; + if ( neg ) + n = (ulong)(-(long)n); + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + if ( neg ) + *--p = '-'; + else if ( flags() & showpos ) + *--p = '+'; + if ( (flags() & internal) && fwidth && !ts_isdigit(*p) ) { + ts_putc( *p ); // special case for internal + ++p; // padding + fwidth--; + return *this << (const char*)p; + } + } + if ( fwidth ) { // adjustment required + if ( !(flags() & left) ) { // but NOT left adjustment + len = qstrlen(p); + int padlen = fwidth - len; + if ( padlen <= 0 ) { // no padding required + writeBlock( p, len ); + } else if ( padlen < (int)(p-buf) ) { // speeds up padding + memset( p-padlen, (char)fillchar, padlen ); + writeBlock( p-padlen, padlen+len ); + } + else // standard padding + *this << (const char*)p; + } + else + *this << (const char*)p; + fwidth = 0; // reset field width + } + else + writeBlock( p, qstrlen(p) ); + return *this; +} + + +/*! + \overload + + Writes a \c short integer \a i to the stream and returns a + reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( signed short i ) +{ + return output_int( I_SHORT | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c short integer \a i to the stream and + returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( unsigned short i ) +{ + return output_int( I_SHORT | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes an \c int \a i to the stream and returns a reference to the + stream. +*/ + +QTextStream &QTextStream::operator<<( signed int i ) +{ + return output_int( I_INT | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c int \a i to the stream and returns a + reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( unsigned int i ) +{ + return output_int( I_INT | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes a \c long \c int \a i to the stream and returns a reference + to the stream. +*/ + +QTextStream &QTextStream::operator<<( signed long i ) +{ + return output_int( I_LONG | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c long \c int \a i to the stream and + returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( unsigned long i ) +{ + return output_int( I_LONG | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes a \c float \a f to the stream and returns a reference to + the stream. +*/ + +QTextStream &QTextStream::operator<<( float f ) +{ + return *this << (double)f; +} + + +/*! + \overload + + Writes a \c double \a f to the stream and returns a reference to + the stream. +*/ + +QTextStream &QTextStream::operator<<( double f ) +{ + CHECK_STREAM_PRECOND + char buf[64]; + char f_char; + char format[16]; + if ( (flags()&floatfield) == fixed ) + f_char = 'f'; + else if ( (flags()&floatfield) == scientific ) + f_char = (flags() & uppercase) ? 'E' : 'e'; + else + f_char = (flags() & uppercase) ? 'G' : 'g'; + register char *fs = format; // generate format string + *fs++ = '%'; // "%.<prec>l<f_char>" + *fs++ = '.'; + int prec = precision(); + if ( prec > 99 ) + prec = 99; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + *fs++ = 'l'; + *fs++ = f_char; + *fs = '\0'; + sprintf( buf, format, f ); // convert to text + if ( fwidth ) // padding + *this << (const char*)buf; + else // just write it + writeBlock( buf, qstrlen(buf) ); + return *this; +} + + +/*! + \overload + + Writes a string to the stream and returns a reference to the + stream. + + The string \a s is assumed to be Latin1 encoded independent of the + Encoding set for the QTextStream. +*/ + +QTextStream &QTextStream::operator<<( const char* s ) +{ + CHECK_STREAM_PRECOND + char padbuf[48]; + uint len = qstrlen( s ); // don't write null terminator + if ( fwidth ) { // field width set + int padlen = fwidth - len; + fwidth = 0; // reset width + if ( padlen > 0 ) { + char *ppad; + if ( padlen > 46 ) { // create extra big fill buffer + ppad = new char[padlen]; + Q_CHECK_PTR( ppad ); + } else { + ppad = padbuf; + } + memset( ppad, (char)fillchar, padlen ); // fill with fillchar + if ( !(flags() & left) ) { + writeBlock( ppad, padlen ); + padlen = 0; + } + writeBlock( s, len ); + if ( padlen ) + writeBlock( ppad, padlen ); + if ( ppad != padbuf ) // delete extra big fill buf + delete[] ppad; + return *this; + } + } + writeBlock( s, len ); + return *this; +} + +/*! + \overload + + Writes \a s to the stream and returns a reference to the stream. + + The string \a s is assumed to be Latin1 encoded independent of the + Encoding set for the QTextStream. +*/ + +QTextStream &QTextStream::operator<<( const QCString & s ) +{ + return operator<<(s.data()); +} + +/*! + \overload + + Writes \a s to the stream and returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( const QString& s ) +{ + if ( !mapper && latin1 ) + return operator<<(s.latin1()); + CHECK_STREAM_PRECOND + QString s1 = s; + if ( fwidth ) { // field width set + if ( !(flags() & left) ) { + s1 = s.rightJustify(fwidth, (char)fillchar); + } else { + s1 = s.leftJustify(fwidth, (char)fillchar); + } + fwidth = 0; // reset width + } + writeBlock( s1.unicode(), s1.length() ); + return *this; +} + + +/*! + \overload + + Writes a pointer to the stream and returns a reference to the + stream. + + The \a ptr is output as an unsigned long hexadecimal integer. +*/ + +QTextStream &QTextStream::operator<<( void *ptr ) +{ + int f = flags(); + setf( hex, basefield ); + setf( showbase ); + unsetf( uppercase ); + output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE ); + flags( f ); + return *this; +} + + +/*! + \fn int QTextStream::flags() const + + Returns the current stream flags. The default value is 0. + + \table + \header \i Flag \i Meaning + \row \i \c skipws \i Not currently used; whitespace always skipped + \row \i \c left \i Numeric fields are left-aligned + \row \i \c right + \i Not currently used (by default, numerics are right-aligned) + \row \i \c internal \i Puts any padding spaces between +/- and value + \row \i \c bin \i Output \e and input only in binary + \row \i \c oct \i Output \e and input only in octal + \row \i \c dec \i Output \e and input only in decimal + \row \i \c hex \i Output \e and input only in hexadecimal + \row \i \c showbase + \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin, + \c oct, or \c hex format + \row \i \c showpoint \i Not currently used + \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x + \row \i \c showpos \i Shows + for positive numeric values + \row \i \c scientific \i Uses scientific notation for floating point values + \row \i \c fixed \i Uses fixed-point notation for floating point values + \endtable + + Note that unless \c bin, \c oct, \c dec, or \c hex is set, the + input base is octal if the value starts with 0, hexadecimal if it + starts with 0x, binary if it starts with 0b, and decimal + otherwise. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::flags( int f ) + + \overload + + Sets the stream flags to \a f. Returns the previous stream flags. + + \sa setf(), unsetf(), flags() +*/ + +/*! + \fn int QTextStream::setf( int bits ) + + Sets the stream flag bits \a bits. Returns the previous stream + flags. + + Equivalent to \c{flags( flags() | bits )}. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::setf( int bits, int mask ) + + \overload + + Sets the stream flag bits \a bits with a bit mask \a mask. Returns + the previous stream flags. + + Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::unsetf( int bits ) + + Clears the stream flag bits \a bits. Returns the previous stream + flags. + + Equivalent to \c{flags( flags() & ~mask )}. + + \sa setf() +*/ + +/*! + \fn int QTextStream::width() const + + Returns the field width. The default value is 0. +*/ + +/*! + \fn int QTextStream::width( int w ) + + \overload + + Sets the field width to \a w. Returns the previous field width. +*/ + +/*! + \fn int QTextStream::fill() const + + Returns the fill character. The default value is ' ' (space). +*/ + +/*! + \overload int QTextStream::fill( int f ) + + Sets the fill character to \a f. Returns the previous fill character. +*/ + +/*! + \fn int QTextStream::precision() const + + Returns the precision. The default value is 6. +*/ + +/*! + \fn int QTextStream::precision( int p ) + + \overload + + Sets the precision to \a p. Returns the previous precision setting. +*/ + + + /***************************************************************************** + QTextStream manipulators + *****************************************************************************/ + +QTextStream &bin( QTextStream &s ) +{ + s.setf(QTS::bin,QTS::basefield); + return s; +} + +QTextStream &oct( QTextStream &s ) +{ + s.setf(QTS::oct,QTS::basefield); + return s; +} + +QTextStream &dec( QTextStream &s ) +{ + s.setf(QTS::dec,QTS::basefield); + return s; +} + +QTextStream &hex( QTextStream &s ) +{ + s.setf(QTS::hex,QTS::basefield); + return s; +} + +QTextStream &endl( QTextStream &s ) +{ + return s << '\n'; +} + +QTextStream &flush( QTextStream &s ) +{ + if ( s.device() ) + s.device()->flush(); + return s; +} + +QTextStream &ws( QTextStream &s ) +{ + s.skipWhiteSpace(); + return s; +} + +QTextStream &reset( QTextStream &s ) +{ + s.reset(); + return s; +} + + +/*! + \class QTextIStream qtextstream.h + \reentrant + \brief The QTextIStream class is a convenience class for input streams. + + \ingroup io + \ingroup text + + This class provides a shorthand for creating simple input + \l{QTextStream}s without having to pass a \e mode argument to the + constructor. + + This class makes it easy, for example, to write things like this: + \code + QString data = "123 456"; + int a, b; + QTextIStream(&data) >> a >> b; + \endcode + + \sa QTextOStream +*/ + +/*! + \fn QTextIStream::QTextIStream( const QString *s ) + + Constructs a stream to read from the string \a s. +*/ +/*! + \fn QTextIStream::QTextIStream( QByteArray ba ) + + Constructs a stream to read from the array \a ba. +*/ +/*! + \fn QTextIStream::QTextIStream( FILE *f ) + + Constructs a stream to read from the file \a f. +*/ + + +/*! + \class QTextOStream + \reentrant + \brief The QTextOStream class is a convenience class for output streams. + + \ingroup io + \ingroup text + + This class provides a shorthand for creating simple output + \l{QTextStream}s without having to pass a \e mode argument to the + constructor. + + This makes it easy for example, to write things like this: + \code + QString result; + QTextOStream(&result) << "pi = " << 3.14; + \endcode +*/ + +/*! + \fn QTextOStream::QTextOStream( QString *s ) + + Constructs a stream to write to string \a s. +*/ +/*! + \fn QTextOStream::QTextOStream( QByteArray ba ) + + Constructs a stream to write to the array \a ba. +*/ +/*! + \fn QTextOStream::QTextOStream( FILE *f ) + + Constructs a stream to write to the file \a f. +*/ + + + +/*! + Sets the encoding of this stream to \a e, where \a e is one of the + following values: + \table + \header \i Encoding \i Meaning + \row \i Locale + \i Uses local file format (Latin1 if locale is not set), but + autodetecting Unicode(utf16) on input. + \row \i Unicode + \i Uses Unicode(utf16) for input and output. Output will be + written in the order most efficient for the current platform + (i.e. the order used internally in QString). + \row \i UnicodeUTF8 + \i Using Unicode(utf8) for input and output. If you use it for + input it will autodetect utf16 and use it instead of utf8. + \row \i Latin1 + \i ISO-8859-1. Will not autodetect utf16. + \row \i UnicodeNetworkOrder + \i Uses network order Unicode(utf16) for input and output. + Useful when reading Unicode data that does not start with the + byte order marker. + \row \i UnicodeReverse + \i Uses reverse network order Unicode(utf16) for input and + output. Useful when reading Unicode data that does not start + with the byte order marker or when writing data that should be + read by buggy Windows applications. + \row \i RawUnicode + \i Like Unicode, but does not write the byte order marker nor + does it auto-detect the byte order. Useful only when writing to + non-persistent storage used by a single process. + \endtable + + \c Locale and all Unicode encodings, except \c RawUnicode, will look + at the first two bytes in an input stream to determine the byte + order. The initial byte order marker will be stripped off before + data is read. + + Note that this function should be called before any data is read to + or written from the stream. + + \sa setCodec() +*/ + +void QTextStream::setEncoding( Encoding e ) +{ + if ( d->sourceType == QTextStreamPrivate::String ) + return; + + switch ( e ) { + case Unicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + networkOrder = QChar::networkOrdered(); + break; + case UnicodeUTF8: +#ifndef QT_NO_TEXTCODEC + mapper = QTextCodec::codecForMib( 106 ); + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + networkOrder = QChar::networkOrdered(); +#else + mapper = 0; + latin1 = TRUE; + doUnicodeHeader = TRUE; +#endif + break; + case UnicodeNetworkOrder: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = QChar::networkOrdered(); + networkOrder = TRUE; + break; + case UnicodeReverse: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = !QChar::networkOrdered(); + networkOrder = FALSE; + break; + case RawUnicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = FALSE; + internalOrder = TRUE; + networkOrder = QChar::networkOrdered(); + break; + case Locale: + latin1 = TRUE; // fallback to Latin-1 +#ifndef QT_NO_TEXTCODEC + mapper = QTextCodec::codecForLocale(); + // optimized Latin-1 processing +#if defined(Q_OS_WIN32) + if ( GetACP() == 1252 ) + mapper = 0; +#endif + if ( mapper && mapper->mibEnum() == 4 ) +#endif + mapper = 0; + + doUnicodeHeader = TRUE; // If it reads as Unicode, accept it + break; + case Latin1: + mapper = 0; + doUnicodeHeader = FALSE; + latin1 = TRUE; + break; + } +} + + +#ifndef QT_NO_TEXTCODEC +/*! + Sets the codec for this stream to \a codec. Will not try to + autodetect Unicode. + + Note that this function should be called before any data is read + to/written from the stream. + + \sa setEncoding(), codec() +*/ + +void QTextStream::setCodec( QTextCodec *codec ) +{ + if ( d->sourceType == QTextStreamPrivate::String ) + return; // QString does not need any codec + mapper = codec; + latin1 = ( codec->mibEnum() == 4 ); + if ( latin1 ) + mapper = 0; + doUnicodeHeader = FALSE; +} + +/*! + Returns the codec actually used for this stream. + + If Unicode is automatically detected in input, a codec with \link + QTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned. + + \sa setCodec() +*/ + +QTextCodec *QTextStream::codec() +{ + if ( mapper ) { + return mapper; + } else { + // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2" + return QTextCodec::codecForMib( latin1 ? 4 : 1000 ); + } +} + +#endif + +#endif // QT_NO_TEXTSTREAM diff --git a/qmake/tools/qucom.cpp b/qmake/tools/qucom.cpp new file mode 100644 index 0000000..6086a79 --- a/dev/null +++ b/qmake/tools/qucom.cpp @@ -0,0 +1,668 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of the QUcom classes +** +** Created : 990101 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "qucom_p.h" + +// Standard types + +// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} +const QUuid TID_QUType_Null( 0xde56510e, 0x4e9f, 0x4b76, 0xa3, 0xc2, 0xd1, 0xe2, 0xef, 0x42, 0xf1, 0xac ); +const QUuid *QUType_Null::uuid() const { return &TID_QUType_Null; } +const char *QUType_Null::desc() const { return "null"; } +bool QUType_Null::canConvertFrom( QUObject *, QUType * ) { return FALSE; } +bool QUType_Null::canConvertTo( QUObject *, QUType * ) { return FALSE; } +bool QUType_Null::convertFrom( QUObject *, QUType * ) { return FALSE; } +bool QUType_Null::convertTo( QUObject *, QUType * ) { return FALSE; } +void QUType_Null::clear( QUObject *) {}; +int QUType_Null::serializeTo( QUObject *, QUBuffer * ) { return 0; } +int QUType_Null::serializeFrom( QUObject *, QUBuffer * ) { return 0; }; +QUType_Null static_QUType_Null; + + +// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} +const QUuid TID_QUType_enum( 0x7ee17b08, 0x5419, 0x47e2, 0x97, 0x76, 0x8e, 0xea, 0x11, 0x2d, 0xca, 0xec ); +QUType_enum static_QUType_enum; +const QUuid *QUType_enum::uuid() const { return &TID_QUType_enum; } +const char *QUType_enum::desc() const { return "enum"; } +void QUType_enum::set( QUObject *o, int v ) +{ + o->payload.i = v; + o->type = this; +} + +bool QUType_enum::canConvertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool QUType_enum::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_int ); +} + +bool QUType_enum::convertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? + ; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool QUType_enum::convertTo( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) { + o->type = &static_QUType_int; + return TRUE; + } + return FALSE; +} + +int QUType_enum::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_enum::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {8AC26448-5AB4-49eb-968C-8F30AB13D732} +const QUuid TID_QUType_ptr( 0x8ac26448, 0x5ab4, 0x49eb, 0x96, 0x8c, 0x8f, 0x30, 0xab, 0x13, 0xd7, 0x32 ); +QUType_ptr static_QUType_ptr; +const QUuid *QUType_ptr::uuid() const { return &TID_QUType_ptr; } +const char *QUType_ptr::desc() const { return "ptr"; } + +void QUType_ptr::set( QUObject *o, const void* v ) +{ + o->payload.ptr = (void*) v; + o->type = this; +} + +bool QUType_ptr::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_ptr::canConvertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +bool QUType_ptr::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_ptr::convertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +int QUType_ptr::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_ptr::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {97A2594D-6496-4402-A11E-55AEF2D4D25C} +const QUuid TID_QUType_iface( 0x97a2594d, 0x6496, 0x4402, 0xa1, 0x1e, 0x55, 0xae, 0xf2, 0xd4, 0xd2, 0x5c ); +QUType_iface static_QUType_iface; +const QUuid *QUType_iface::uuid() const { return &TID_QUType_iface; } +const char *QUType_iface::desc() const { return "UnknownInterface"; } + +void QUType_iface::set( QUObject *o, QUnknownInterface* iface ) +{ + o->payload.iface = iface; + o->type = this; +} + +bool QUType_iface::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_iface::canConvertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +bool QUType_iface::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_iface::convertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +int QUType_iface::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_iface::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} +const QUuid TID_QUType_idisp( 0x2f358164, 0xe28f, 0x4bf4, 0x9f, 0xa9, 0x4e, 0xc, 0xdc, 0xab, 0xa5, 0xb ); +QUType_idisp static_QUType_idisp; +const QUuid *QUType_idisp::uuid() const { return &TID_QUType_idisp; } +const char *QUType_idisp::desc() const { return "DispatchInterface"; } + +void QUType_idisp::set( QUObject *o, QDispatchInterface* idisp ) +{ + o->payload.idisp = idisp; + o->type = this; +} + +bool QUType_idisp::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_idisp::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_iface ); +} + +bool QUType_idisp::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_idisp::convertTo( QUObject *o, QUType *t ) +{ +#ifndef QT_NO_COMPONENT + if ( isEqual( t, &static_QUType_iface ) ) { + o->payload.iface = (QUnknownInterface*)o->payload.idisp; + o->type = &static_QUType_iface; + return TRUE; + } +#endif + return FALSE; +} + +int QUType_idisp::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_idisp::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {CA42115D-13D0-456c-82B5-FC10187F313E} +const QUuid TID_QUType_bool( 0xca42115d, 0x13d0, 0x456c, 0x82, 0xb5, 0xfc, 0x10, 0x18, 0x7f, 0x31, 0x3e ); +QUType_bool static_QUType_bool; +const QUuid *QUType_bool::uuid() const { return &TID_QUType_bool; } +const char *QUType_bool::desc() const { return "bool"; } + +void QUType_bool::set( QUObject *o, bool v ) +{ + o->payload.b = v; + o->type = this; +} + +bool QUType_bool::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_bool::canConvertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +bool QUType_bool::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_bool::convertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +int QUType_bool::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_bool::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} +const QUuid TID_QUType_int( 0x53c1f3be, 0x73c3, 0x4c7d, 0x9e, 0x5, 0xcc, 0xf0, 0x9e, 0xb6, 0x76, 0xb5 ); +QUType_int static_QUType_int; +const QUuid *QUType_int::uuid() const { return &TID_QUType_int; } +const char *QUType_int::desc() const { return "int"; } + +void QUType_int::set( QUObject *o, int v ) +{ + o->payload.i = v; + o->type = this; +} + +bool QUType_int::canConvertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) || + isEqual( t, &static_QUType_float ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool QUType_int::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_double ) || + isEqual( t, &static_QUType_float ); +} + +bool QUType_int::convertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) ) + o->payload.i = (long)o->payload.d; + else if ( isEqual( t, &static_QUType_float ) ) + o->payload.i = (long)o->payload.f; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool QUType_int::convertTo( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = (double)o->payload.i; + o->type = &static_QUType_double; + } else if ( isEqual( t, &static_QUType_float ) ) { + o->payload.f = (float)o->payload.i; + o->type = &static_QUType_float; + } else + return FALSE; + return TRUE; +} + +int QUType_int::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_int::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {5938712A-C496-11D5-8CB2-00C0F03BC0F3} +const QUuid TID_QUType_uint( 0x5938712a, 0xc496, 0x11d5, 0x8c, 0xb2, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3); +QUType_uint static_QUType_uint; +const QUuid *QUType_uint::uuid() const { return &TID_QUType_uint; } +const char *QUType_uint::desc() const { return "uint"; } + +void QUType_uint::set( QUObject *o, uint v ) +{ + o->payload.ui = v; + o->type = this; +} + +bool QUType_uint::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_uint::canConvertTo( QUObject * /*o*/, QUType * /*t*/ ) +{ + return FALSE; +} + +bool QUType_uint::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_uint::convertTo( QUObject * /*o*/, QUType * /*t*/ ) +{ + return FALSE; +} + +int QUType_uint::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_uint::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} +const QUuid TID_QUType_double( 0x2d0974e5, 0xba6, 0x4ec2, 0x88, 0x37, 0xc1, 0x98, 0x97, 0x2c, 0xb4, 0x8c ); +QUType_double static_QUType_double; +const QUuid *QUType_double::uuid() const { return &TID_QUType_double; } +const char *QUType_double::desc() const {return "double"; } + +void QUType_double::set( QUObject *o, double v ) +{ + o->payload.d = v; + o->type = this; +} + +bool QUType_double::canConvertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_float) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool QUType_double::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_float ); +} + +bool QUType_double::convertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) + o->payload.d = (double)o->payload.i; + else if ( isEqual( t, &static_QUType_float ) ) + o->payload.d = (double)o->payload.f; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool QUType_double::convertTo( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) { + o->payload.i = (int) o->payload.d; + o->type = &static_QUType_int; + } else if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = (double) o->payload.f; + o->type = &static_QUType_double; + } else + return FALSE; + return TRUE; +} + +int QUType_double::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_double::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + + +// {544C5175-6993-4486-B04D-CEC4D21BF4B9 } +const QUuid TID_QUType_float( 0x544c5175, 0x6993, 0x4486, 0xb0, 0x4d, 0xce, 0xc4, 0xd2, 0x1b, 0xf4, 0xb9 ); +QUType_float static_QUType_float; +const QUuid *QUType_float::uuid() const { return &TID_QUType_float; } +const char *QUType_float::desc() const {return "float"; } + +void QUType_float::set( QUObject *o, float v ) +{ + o->payload.f = v; + o->type = this; +} + +bool QUType_float::canConvertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_double ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool QUType_float::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_double ); +} + +bool QUType_float::convertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) + o->payload.f = (float)o->payload.i; + else if ( isEqual( t, &static_QUType_double ) ) + o->payload.f = (float)o->payload.d; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool QUType_float::convertTo( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) { + o->payload.i = (int) o->payload.f; + o->type = &static_QUType_int; + } else if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = (double) o->payload.f; + o->type = &static_QUType_double; + } else + return FALSE; + return TRUE; +} + +int QUType_float::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_float::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} +const QUuid TID_QUType_charstar( 0xefcdd1d4, 0x77a3, 0x4b8e, 0x8d, 0x46, 0xdc, 0x14, 0xb8, 0xd3, 0x93, 0xe9 ); +QUType_charstar static_QUType_charstar; +const QUuid *QUType_charstar::uuid() const { return &TID_QUType_charstar; } +const char *QUType_charstar::desc() const { return "char*"; } + +void QUType_charstar::set( QUObject *o, const char* v, bool take ) +{ + if ( take ) { + if ( v ) { + o->payload.charstar.ptr = new char[ strlen(v) + 1 ]; + strcpy( o->payload.charstar.ptr, v ); + } else { + o->payload.charstar.ptr = 0; + } + o->payload.charstar.owner = TRUE; + } else { + o->payload.charstar.ptr = (char*) v; + o->payload.charstar.owner = FALSE; + } + o->type = this; +} + +bool QUType_charstar::canConvertFrom( QUObject *o, QUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool QUType_charstar::canConvertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +bool QUType_charstar::convertFrom( QUObject *o, QUType *t ) +{ + return t->convertTo( o, this ); +} + +bool QUType_charstar::convertTo( QUObject *, QUType * ) +{ + return FALSE; +} + +void QUType_charstar::clear( QUObject *o ) +{ + if ( o->payload.charstar.owner ) + delete [] o->payload.charstar.ptr; + o->payload.charstar.ptr = 0; +} + +int QUType_charstar::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_charstar::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + + +// Qt specific types + +// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} +const QUuid TID_QUType_QString( 0x44c2a547, 0x1e7, 0x4e56, 0x85, 0x59, 0x35, 0xaf, 0x9d, 0x2f, 0x42, 0xb7 ); +QUType_QString static_QUType_QString; +const QUuid *QUType_QString::uuid() const { return &TID_QUType_QString; } +const char *QUType_QString::desc() const { return "QString"; } + +void QUType_QString::set( QUObject *o, const QString& v ) +{ + o->payload.ptr = new QString( v ); + o->type = this; +} + +bool QUType_QString::canConvertFrom( QUObject *o, QUType *t ) +{ + if ( isEqual( t, &static_QUType_charstar ) || + isEqual( t, &static_QUType_double ) || + isEqual( t, &static_QUType_float ) || + isEqual( t, &static_QUType_int ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool QUType_QString::canConvertTo( QUObject * /*o*/, QUType *t ) +{ + return isEqual( t, &static_QUType_charstar ) || + isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_double ) || + isEqual( t, &static_QUType_float ); +} + +bool QUType_QString::convertFrom( QUObject *o, QUType *t ) +{ + QString *str = 0; + if ( isEqual( t, &static_QUType_charstar ) ) + str = new QString( o->payload.charstar.ptr ); + else if ( isEqual( t, &static_QUType_double ) ) + str = new QString( QString::number( o->payload.d ) ); + else if ( isEqual( t, &static_QUType_float ) ) + str = new QString( QString::number( o->payload.f ) ); + else if ( isEqual( t, &static_QUType_int ) ) + str = new QString( QString::number( o->payload.i ) ); + else + return t->convertTo( o, this ); + + o->type->clear( o ); + o->payload.ptr = str; + o->type = this; + return TRUE; +} + +bool QUType_QString::convertTo( QUObject *o, QUType *t ) +{ + QString *str = (QString *)o->payload.ptr; + if ( isEqual( t, &static_QUType_charstar ) ) { + o->payload.charstar.ptr = qstrdup( str->local8Bit().data() ); + o->payload.charstar.owner = TRUE; + o->type = &static_QUType_charstar; + } else if ( isEqual( t, &static_QUType_int ) ) { + o->payload.l = str->toLong(); + o->type = &static_QUType_int; + } else if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = str->toDouble(); + o->type = &static_QUType_double; + } else if ( isEqual( t, &static_QUType_float ) ) { + o->payload.d = str->toFloat(); + o->type = &static_QUType_float; + } else { + return FALSE; + } + delete str; + return TRUE; +} + +int QUType_QString::serializeTo( QUObject *, QUBuffer * ) +{ + return 0; +} + +int QUType_QString::serializeFrom( QUObject *, QUBuffer * ) +{ + return 0; +} + +void QUType_QString::clear( QUObject *o ) +{ + delete (QString*)o->payload.ptr; + o->payload.ptr = 0; +} diff --git a/qmake/tools/quuid.cpp b/qmake/tools/quuid.cpp new file mode 100644 index 0000000..fd99abf --- a/dev/null +++ b/qmake/tools/quuid.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QUuid class +** +** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "quuid.h" + +#include <qdatastream.h> + +/*! + \class QUuid quuid.h + \reentrant + \brief The QUuid class defines a Universally Unique Identifier (UUID). + + \internal + + For objects or declarations that need to be identified uniquely, UUIDs (also known as GUIDs) are widely + used in order to assign a fixed and easy to compare value to this object or declaration. The 128bit value + of an UUID is generated by an algorithm that guarantees a value that is unique in time and space. + + In Qt, UUIDs are wrapped by the QUuid struct which provides convenience functions for comparing and coping + this value. The QUuid struct is used in Qt's component model to identify interfaces. Most platforms provide a tool to + generate new UUIDs (uuidgen, guidgen), and the Qt distribution includes a graphical tool \e quuidgen that generates + the UUIDs in a programmer friendly format. + + \sa QUnknownInterface +*/ + +/*! + \fn QUuid::QUuid() + + Creates the null UUID {00000000-0000-0000-0000-000000000000}. +*/ + +/*! + \fn QUuid::QUuid( uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8 ) + + Creates an UUID with the value specified by the parameters, \a l, \a + w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a b8. + + Example: + \code + // {67C8770B-44F1-410A-AB9A-F9B5446F13EE} + QUuid IID_MyInterface( 0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee ) + \endcode +*/ + +/*! + \fn QUuid::QUuid( const QUuid &orig ) + + Creates a copy of the QUuid \a orig. +*/ +#ifndef QT_NO_QUUID_STRING +/*! + Creates a QUuid object from the string \a text. Right now, the function + can only convert the format {12345678-1234-1234-1234-123456789ABC} and + will create the null UUID when the conversion fails. +*/ +QUuid::QUuid( const QString &text ) +{ + bool ok; + QString temp = text.upper(); + + data1 = temp.mid( 1, 8 ).toULong( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + + data2 = temp.mid( 10, 4 ).toUInt( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + data3 = temp.mid( 15, 4 ).toUInt( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + data4[0] = temp.mid( 20, 2 ).toUInt( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + data4[1] = temp.mid( 22, 2 ).toUInt( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + for ( int i = 2; i<8; i++ ) { + data4[i] = temp.mid( 25 + (i-2)*2, 2 ).toUShort( &ok, 16 ); + if ( !ok ) { + *this = QUuid(); + return; + } + } +} + +/*! + \overload +*/ +QUuid::QUuid( const char *text ) +{ + *this = QUuid( QString(text) ); +} +#endif +/*! + \fn QUuid QUuid::operator=(const QUuid &uuid ) + + Assigns the value of \a uuid to this QUuid object. +*/ + +/*! + \fn bool QUuid::operator==(const QUuid &other) const + + Returns TRUE if this QUuid and the \a other QUuid are identical, otherwise returns FALSE. +*/ + +/*! + \fn bool QUuid::operator!=(const QUuid &other) const + + Returns TRUE if this QUuid and the \a other QUuid are different, otherwise returns FALSE. +*/ +#ifndef QT_NO_QUUID_STRING +/*! + \fn QUuid::operator QString() const + + Returns the string representation of the uuid. + + \sa toString() +*/ + +/*! + QString QUuid::toString() const + + Returns the string representation of the uuid. +*/ +QString QUuid::toString() const +{ + QString result; + + result = "{" + QString::number( data1, 16 ).rightJustify( 8, '0' ) + "-"; + result += QString::number( (int)data2, 16 ).rightJustify( 4, '0' ) + "-"; + result += QString::number( (int)data3, 16 ).rightJustify( 4, '0' ) + "-"; + result += QString::number( (int)data4[0], 16 ).rightJustify( 2, '0' ); + result += QString::number( (int)data4[1], 16 ).rightJustify( 2, '0' ) + "-"; + for ( int i = 2; i < 8; i++ ) + result += QString::number( (int)data4[i], 16 ).rightJustify( 2, '0' ); + + return result + "}"; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \relates QUuid + Writes the \a id to the datastream \a s. +*/ +QDataStream &operator<<( QDataStream &s, const QUuid &id ) +{ + s << (Q_UINT32)id.data1; + s << (Q_UINT16)id.data2; + s << (Q_UINT16)id.data3; + for (int i = 0; i < 8; i++ ) + s << (Q_UINT8)id.data4[i]; + return s; +} + +/*! + \relates QUuid + Reads a universally unique id from from the stream \a s into \a id. +*/ +QDataStream &operator>>( QDataStream &s, QUuid &id ) +{ + Q_UINT32 u32; + Q_UINT16 u16; + Q_UINT8 u8; + s >> u32; + id.data1 = u32; + s >> u16; + id.data2 = u16; + s >> u16; + id.data3 = u16; + for (int i = 0; i < 8; i++ ) { + s >> u8; + id.data4[i] = u8; + } + return s; +} +#endif + +/*! + Returns TRUE if this is the null UUID {00000000-0000-0000-0000-000000000000}, otherwise returns FALSE. +*/ +bool QUuid::isNull() const +{ + return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 && + data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 && + data1 == 0 && data2 == 0 && data3 == 0; +} diff --git a/qmake/tools/qwaitcondition_unix.cpp b/qmake/tools/qwaitcondition_unix.cpp new file mode 100644 index 0000000..99c1014 --- a/dev/null +++ b/qmake/tools/qwaitcondition_unix.cpp @@ -0,0 +1,310 @@ +/**************************************************************************** +** $Id$ +** +** QWaitCondition class for Unix +** +** Created : 20010725 +** +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#if defined(QT_THREAD_SUPPORT) + +#include "qplatformdefs.h" + +typedef pthread_mutex_t Q_MUTEX_T; + +#include "qwaitcondition.h" +#include "qmutex.h" +#include "qmutex_p.h" + +#include <errno.h> +#include <string.h> + + +struct QWaitConditionPrivate { + pthread_cond_t cond; +}; + + +/*! + \class QWaitCondition qwaitcondition.h + \threadsafe + \brief The QWaitCondition class allows waiting/waking for conditions between threads. + + \ingroup thread + \ingroup environment + + QWaitConditions allow a thread to tell other threads that some + sort of condition has been met; one or many threads can block + waiting for a QWaitCondition to set a condition with wakeOne() or + wakeAll(). Use wakeOne() to wake one randomly selected event or + wakeAll() to wake them all. For example, say we have three tasks + that should be performed every time the user presses a key; each + task could be split into a thread, each of which would have a + run() body like this: + + \code + QWaitCondition key_pressed; + + for (;;) { + key_pressed.wait(); // This is a QWaitCondition global variable + // Key was pressed, do something interesting + do_something(); + } + \endcode + + A fourth thread would read key presses and wake the other three + threads up every time it receives one, like this: + + \code + QWaitCondition key_pressed; + + for (;;) { + getchar(); + // Causes any thread in key_pressed.wait() to return from + // that method and continue processing + key_pressed.wakeAll(); + } + \endcode + + Note that the order the three threads are woken up in is + undefined, and that if some or all of the threads are still in + do_something() when the key is pressed, they won't be woken up + (since they're not waiting on the condition variable) and so the + task will not be performed for that key press. This can be + avoided by, for example, doing something like this: + + \code + QMutex mymutex; + QWaitCondition key_pressed; + int mycount=0; + + // Worker thread code + for (;;) { + key_pressed.wait(); // This is a QWaitCondition global variable + mymutex.lock(); + mycount++; + mymutex.unlock(); + do_something(); + mymutex.lock(); + mycount--; + mymutex.unlock(); + } + + // Key reading thread code + for (;;) { + getchar(); + mymutex.lock(); + // Sleep until there are no busy worker threads + while( count > 0 ) { + mymutex.unlock(); + sleep( 1 ); + mymutex.lock(); + } + mymutex.unlock(); + key_pressed.wakeAll(); + } + \endcode + + The mutexes are necessary because the results of two threads + attempting to change the value of the same variable simultaneously + are unpredictable. +*/ + +/*! + Constructs a new event signalling, i.e. wait condition, object. +*/ +QWaitCondition::QWaitCondition() +{ + d = new QWaitConditionPrivate; + + int ret = pthread_cond_init(&d->cond, NULL); + +#ifdef QT_CHECK_RANGE + if (ret) + qWarning( "Wait condition init failure: %s", strerror( ret ) ); +#endif +} + + +/*! + Deletes the event signalling, i.e. wait condition, object. +*/ +QWaitCondition::~QWaitCondition() +{ + int ret = pthread_cond_destroy(&d->cond); + + if (ret) { +#ifdef QT_CHECK_RANGE + qWarning( "Wait condition destroy failure: %s", strerror( ret ) ); +#endif + + // seems we have threads waiting on us, lets wake them up + pthread_cond_broadcast(&d->cond); + } + + delete d; +} + +/*! + This wakes one thread waiting on the QWaitCondition. The thread + that is woken up depends on the operating system's scheduling + policies, and cannot be controlled or predicted. + + \sa wakeAll() +*/ +void QWaitCondition::wakeOne() +{ + int ret = pthread_cond_signal(&d->cond); + +#ifdef QT_CHECK_RANGE + if (ret) + qWarning("Wait condition wakeOne failure: %s", strerror(ret)); +#endif +} + +/*! + This wakes all threads waiting on the QWaitCondition. The order in + which the threads are woken up depends on the operating system's + scheduling policies, and cannot be controlled or predicted. + + \sa wakeOne() +*/ +void QWaitCondition::wakeAll() +{ + int ret = pthread_cond_broadcast(&d->cond); + +#ifdef QT_CHECK_RANGE + if (ret) + qWarning("Wait condition wakeAll failure: %s", strerror(ret)); +#endif +} + +/*! + Wait on the thread event object. The thread calling this will + block until either of these conditions is met: + \list + \i Another thread signals it using wakeOne() or wakeAll(). This + function will return TRUE in this case. + \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + default), then the wait will never timeout (the event must be + signalled). This function will return FALSE if the wait timed + out. + \endlist + + \sa wakeOne(), wakeAll() +*/ +bool QWaitCondition::wait(unsigned long time) +{ + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + + int ret; + if (time != ULONG_MAX) { + struct timeval tv; + gettimeofday(&tv, 0); + + timespec ti; + ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000; + ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 ); + ti.tv_nsec %= 1000000000; + + ret = pthread_cond_timedwait(&d->cond, &mutex, &ti); + } else + ret = pthread_cond_wait(&d->cond, &mutex); + +#ifdef QT_CHECK_RANGE + if (ret && ret != ETIMEDOUT) + qWarning("Wait condition wait failure: %s",strerror(ret)); +#endif + + return (ret == 0); +} + +/*! + \overload + + Release the locked \a mutex and wait on the thread event object. + The \a mutex must be initially locked by the calling thread. If \a + mutex is not in a locked state, this function returns immediately. + If \a mutex is a recursive mutex, this function returns + immediately. The \a mutex will be unlocked, and the calling thread + will block until either of these conditions is met: + \list + \i Another thread signals it using wakeOne() or wakeAll(). This + function will return TRUE in this case. + \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + default), then the wait will never timeout (the event must be + signalled). This function will return FALSE if the wait timed + out. + \endlist + + The mutex will be returned to the same locked state. This function + is provided to allow the atomic transition from the locked state + to the wait state. + + \sa wakeOne(), wakeAll() +*/ +bool QWaitCondition::wait(QMutex *mutex, unsigned long time) +{ + if (! mutex) + return FALSE; + + if (mutex->d->type() == Q_MUTEX_RECURSIVE) { +#ifdef QT_CHECK_RANGE + qWarning("Wait condition warning: using recursive mutexes with\n" + " wait conditions is undefined!"); +#endif + return FALSE; + } + + int ret; + if (time != ULONG_MAX) { + struct timeval tv; + gettimeofday(&tv, 0); + + timespec ti; + ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000; + ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 ); + ti.tv_nsec %= 1000000000; + + ret = pthread_cond_timedwait(&d->cond, &mutex->d->handle, &ti); + } else + ret = pthread_cond_wait(&d->cond, &mutex->d->handle); + +#ifdef QT_CHECK_RANGE + if (ret && ret != ETIMEDOUT) + qWarning("Wait condition wait failure: %s",strerror(ret)); +#endif + + return (ret == 0); +} + +#endif // QT_THREAD_SUPPORT |