diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 2000-10-15 15:32:16 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 2000-10-15 15:32:16 (GMT) |
commit | eb7f0413527724df305245200c56f54ab2853ab7 (patch) | |
tree | 7824ba2a5c9f1fe6ddc8633a13cc7d1e7a6c79a3 | |
parent | 0d0eec1df129221379625a52e5fe8ff6f21f104c (diff) | |
download | Doxygen-eb7f0413527724df305245200c56f54ab2853ab7.zip Doxygen-eb7f0413527724df305245200c56f54ab2853ab7.tar.gz Doxygen-eb7f0413527724df305245200c56f54ab2853ab7.tar.bz2 |
Release-1.2.2-20001015
112 files changed, 45130 insertions, 447 deletions
@@ -1,6 +1,6 @@ -DOXYGEN Version 1.2.2-20001001 +DOXYGEN Version 1.2.2-20001015 Please read the installation section of the manual for instructions. -------- -Dimitri van Heesch (01 October 2000) +Dimitri van Heesch (15 October 2000) diff --git a/Makefile.in b/Makefile.in index 95fc3ae..812c91b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,10 +1,12 @@ all: src/version.cpp configgen doxywizard + cd qtools ; $(MAKE) cd src ; $(MAKE) clean: FORCE cd examples ; $(MAKE) clean cd doc ; $(MAKE) clean + cd qtools ; $(MAKE) clean cd src ; $(MAKE) clean cd addon/configgen ; $(MAKE) clean cd addon/doxywizard ; $(MAKE) clean @@ -13,16 +15,14 @@ clean: FORCE -rm -f objects/*.o distclean: clean - cd examples ; $(MAKE) clean - cd doc ; $(MAKE) clean cd src ; $(MAKE) distclean cd addon/configgen ; $(MAKE) distclean cd addon/doxywizard ; $(MAKE) distclean -rm -f bin/doxy* -rm -f html -rm -f objects/*.o - -rm -f src/Makefile.doxygen src/Makefile.doxytag src/Makefile.doxysearch - -rm -f Makefile src/Makefile examples/Makefile doc/Makefile + -rm -f src/Makefile.doxygen src/Makefile.doxytag src/Makefile.doxysearch qtools/Makefile.qtools + -rm -f Makefile qtools/Makefile src/Makefile examples/Makefile doc/Makefile -rm -f .makeconfig .tmakeconfig -rm -f src/doxygen.pro src/doxytag.pro src/doxysearch.pro -rm -f src/version.cpp @@ -69,7 +69,7 @@ pdf: docs archive: clean tar zcvf dx`date +%y%m%d`.tgz addon tmake doc wintools examples bin objects \ - src configure configure.bin Makefile.in Makefile.win.in INSTALL \ + qtools src configure configure.bin Makefile.in Makefile.win.in INSTALL \ make.bat LANGUAGE.HOWTO LICENSE PLATFORMS VERSION packages src/version.cpp: Makefile diff --git a/Makefile.win.in b/Makefile.win.in index add71f6..4ca50ec 100644 --- a/Makefile.win.in +++ b/Makefile.win.in @@ -1,5 +1,8 @@ all: src\version.cpp set TMAKEPATH=$(TMAKEPATH) + cd qtools + $(MAKE) + cd .. cd src $(MAKE) @@ -1,4 +1,4 @@ -DOXYGEN Version 1.2.2-20001001 +DOXYGEN Version 1.2.2-20001015 Please read INSTALL for compilation instructions. @@ -7,4 +7,4 @@ The latest version of doxygen can be obtained at Enjoy, -Dimitri van Heesch (01 October 2000) +Dimitri van Heesch (15 October 2000) @@ -1 +1 @@ -1.2.2-20001001 +1.2.2-20001015 diff --git a/addon/configgen/configgen.cpp b/addon/configgen/configgen.cpp index 7a11fc0..c9d5a2d 100644 --- a/addon/configgen/configgen.cpp +++ b/addon/configgen/configgen.cpp @@ -1075,6 +1075,14 @@ void init() "tags, which will be replaced by the file and line number from which the \n" "warning originated and the warning text. \n" ); + ConfigString::add("warnLogFile", + "WARN_LOGFILE", + "", + "log file to write warning to", + "The WARN_LOGFILE tag can be used to specify a file to which warning \n" + "and error messages should be written. If left blank the output is written \n" + "to stderr. \n" + ); //----------------------------------------------------------------------------------------------- ConfigInfo::add( "Input","configuration options related to the input files"); //----------------------------------------------------------------------------------------------- @@ -1658,7 +1666,15 @@ void init() 100,30000 ); addDependency("maxDotGraphHeight","haveDotFlag"); - + ConfigBool::add( "generateLegend", + "GENERATE_LEGEND", + "TRUE", + "generate legend page", + "If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will \n" + "generate a legend page explaining the meaning of the various boxes and \n" + "arrows in the dot generated graphs. \n" + ); + addDependency("generateLegend","haveDotFlag"); //----------------------------------------------------------------------------------------------- ConfigInfo::add( "Search","Configuration::addtions related to the search engine "); @@ -218,27 +218,27 @@ if test "$f_plf_auto" = NO; then fi #- check for qt -------------------------------------------------------------- - -echo -n " Checking for Qt..." -if test -z "$QTDIR"; then - echo "QTDIR not set!" - echo - echo "tmake requires the QTDIR environment variable to be set." - echo "check your Qt installation!" - exit 2 -else - if test ! -d "$QTDIR/lib"; then - echo "QTDIR is set, but library directory does not exist!" - exit 2 - fi - if test ! -d "$QTDIR/include"; then - echo "QTDIR is set, but include directory does not exist!" - exit 2 - fi - echo " headers $QTDIR/include," - echo " libraries $QTDIR/lib" -fi - +# +# echo -n " Checking for Qt..." +# if test -z "$QTDIR"; then +# echo "QTDIR not set!" +# echo +# echo "tmake requires the QTDIR environment variable to be set." +# echo "check your Qt installation!" +# exit 2 +# else +# if test ! -d "$QTDIR/lib"; then +# echo "QTDIR is set, but library directory does not exist!" +# exit 2 +# fi +# if test ! -d "$QTDIR/include"; then +# echo "QTDIR is set, but include directory does not exist!" +# exit 2 +# fi +# echo " headers $QTDIR/include," +# echo " libraries $QTDIR/lib" +# fi +# # - check for make ------------------------------------------------------------ echo -n " Checking for GNU make tool... " @@ -268,7 +268,7 @@ echo "using $f_make" # - check for dot ------------------------------------------------------------ -echo -n " Checking for dot... " +echo -n " Checking for dot (part of GraphViz)... " if test "$f_dot" = NO; then dot_dirs="$bin_dirs" dot_prog=NO @@ -374,7 +374,7 @@ TMAKE_CXXFLAGS = -DENGLISH_ONLY EOF fi -f_inmakefiles="Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/configgen/Makefile.in addon/doxywizard/Makefile.in addon/xmlread/Makefile.in" +f_inmakefiles="Makefile.in qtools/Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/configgen/Makefile.in addon/doxywizard/Makefile.in addon/xmlread/Makefile.in" for i in $f_inmakefiles ; do SRC=$i @@ -404,7 +404,7 @@ EOF echo " Created $DST from $SRC..." done -f_inprofiles="src/doxygen.pro.in src/doxytag.pro.in src/doxysearch.pro.in addon/configgen/configgen.pro.in addon/doxywizard/doxywizard.pro.in addon/xmlread/xmlread.pro.in" +f_inprofiles="qtools/qtools.pro.in src/doxygen.pro.in src/doxytag.pro.in src/doxysearch.pro.in addon/configgen/configgen.pro.in addon/doxywizard/doxywizard.pro.in addon/xmlread/xmlread.pro.in" for i in $f_inprofiles ; do SRC=$i diff --git a/doc/config.doc b/doc/config.doc index 9b92688..1d3046f 100644 --- a/doc/config.doc +++ b/doc/config.doc @@ -103,6 +103,7 @@ followed by the descriptions of the tags grouped by category. <li> \refitem cfg_generate_html GENERATE_HTML <li> \refitem cfg_generate_htmlhelp GENERATE_HTMLHELP <li> \refitem cfg_generate_latex GENERATE_LATEX +<li> \refitem cfg_generate_legend GENERATE_LEGEND <li> \refitem cfg_generate_man GENERATE_MAN <li> \refitem cfg_generate_rtf GENERATE_RTF <li> \refitem cfg_generate_tagfile GENERATE_TAGFILE @@ -163,6 +164,7 @@ followed by the descriptions of the tags grouped by category. <li> \refitem cfg_verbatim_headers VERBATIM_HEADERS <li> \refitem cfg_warn_format WARN_FORMAT <li> \refitem cfg_warn_if_undocumented WARN_IF_UNDOCUMENTED +<li> \refitem cfg_warn_logfile WARN_LOGFILE <li> \refitem cfg_warnings WARNINGS \htmlonly </ul> @@ -481,12 +483,19 @@ followed by the descriptions of the tags grouped by category. \anchor cfg_warn_format <dt>\c WARN_FORMAT <dd> \addindex WARN_FORMAT - The WARN_FORMAT tag determines the format of the warning messages that + The \c WARN_FORMAT tag determines the format of the warning messages that doxygen can produce. The string should contain the <code>\$file</code>, <code>\$line</code>, and <code>\$text</code> tags, which will be replaced by the file and line number from which the warning originated and the warning text. +\anchor cfg_warn_logfile +<dt>\c WARN_LOGFILE <dd> + \addindex WARN_LOGFILE + The \c WARN_LOGFILE tag can be used to specify a file to which warning + and error messages should be written. If left blank the output is written + to stderr. + </dl> \subsection config_input Input related options @@ -1061,6 +1070,13 @@ TAGFILES = file1=loc1 "file2 = loc2" ... </pre> the specified constraint. Beware that most browsers cannot cope with very large images. +\anchor cfg_generate_legend <dd> +<dt>\c GENERATE_LEGEND <dd> + \addindex GENERATE_LEGEND + If the \c GENERATE_LEGEND tag is set to \c YES (the default) Doxygen will + generate a legend page explaining the meaning of the various boxes and + arrows in the dot generated graphs. + </dl> \subsection config_search Search engine options \anchor cfg_searchengine diff --git a/doc/install.doc b/doc/install.doc index 2d31184..3b0c6b2 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -337,7 +337,7 @@ Here is what is required: variables (if you did not select to do this automatically during installation). <li>Perl 5.0 or higher for Windows. This can be download from: - http://www.ActiveState.com/pw32 + http://www.ActiveState.com/Products/ActivePerl/ <li>The GNU tools flex, bison and sed. To get these working on Windows you should install the <a href="http://sourceware.cygnus.com/cygwin/">cygwin tools</a> @@ -351,8 +351,8 @@ Here is what is required: the directory they are in to the search path. <li>A professional license of - <A HREF="http://www.trolltech.com/products/qt.html">Qt for Windows</A><br> - \latexonly(see {\tt http://www.trolltech.com/products/qt.html})\endlatexonly. + <A HREF="http://www.trolltech.com/products/qt.html">Qt for Windows</A> + \latexonly\par (see {\tt http://www.trolltech.com/products/qt.html})\endlatexonly. If you do not have that and you can live without the GUI front-end you can also download Qt-1.44 for X11. Doxygen only the depends on diff --git a/doc/starting.doc b/doc/starting.doc index b518838..70dfc50 100644 --- a/doc/starting.doc +++ b/doc/starting.doc @@ -131,7 +131,7 @@ of compiling the generated documentation, \c doxygen writes a \c Makefile into the \c latex directory. By typing \c make in the \c latex directory the dvi file \c refman.dvi will be generated (provided that you have a make tool called -<code>make</code> ofcourse). This file can then be viewed using \c xdvi or +<code>make</code> of course). This file can then be viewed using \c xdvi or converted into a postscript file \c refman.ps by typing <code>make ps</code> (this requires <code>dvips</code>). To put 2 pages on one physical page use <code>make ps_2on1</code> instead. @@ -152,7 +152,7 @@ capabilities of the man page format, so some information \subsection step3 Step 3: Documenting the sources Although documenting the source is presented as step 3, in a new project -this should ofcourse be step 1. Here I assume +this should of course be step 1. Here I assume you already have some code and you want doxygen to generate a nice document describing the API and maybe the internals as well. diff --git a/make.bat b/make.bat deleted file mode 100644 index 67d3a26..0000000 --- a/make.bat +++ /dev/null @@ -1,32 +0,0 @@ -REM make script for Microsoft Visual C++
-
-REM goto OK
-
-if not '%QTDIR%'=='' goto OK
-echo The QTDIR environment variable is not set! See the INSTALL file for more info.
-rem You can also remove the comment from the upper "REM goto OK" line
-rem and set the QTDIR correctly on the line below.
-goto END
-:OK
-
-REM Change the QTDIR setting as appropriate (at the following line)
-if '%QTDIR%'=='' set QTDIR=c:\usr\qt-1.44
-
-REM Generate the batch for compilation from the src subdirectory (make.bat)
-echo set QTDIR=%QTDIR%>src\make.bat
-echo nmake>>src\make.bat
-
-REM use perl to create the config file
-perl wintools\make.pl
-
-type makeconfig Makefile.win.in >Makefile
-type makeconfig src\Makefile.in >src\Makefile
-type makeconfig examples\Makefile.win.in >examples\Makefile
-type makeconfig doc\Makefile.win.in >doc\Makefile
-type src\doxygen.pro.in | sed "s/\$extraopts/release/g" >src\doxygen.pro
-type src\doxytag.pro.in | sed "s/\$extraopts/release/g" >src\doxytag.pro
-type src\doxysearch.pro.in | sed "s/\$extraopts/release/g" >src\doxysearch.pro
-
-nmake
-
-:END
diff --git a/packages/rpm/doxygen.spec b/packages/rpm/doxygen.spec index bb0d2f8..ee917cc 100644 --- a/packages/rpm/doxygen.spec +++ b/packages/rpm/doxygen.spec @@ -1,5 +1,5 @@ Name: doxygen -Version: 1.2.2-20001001 +Version: 1.2.2-20001015 Summary: documentation system for C, C++ and IDL Release: 1 Source0: doxygen-%{version}.src.tar.gz diff --git a/qtools/LICENSE.GPL b/qtools/LICENSE.GPL new file mode 100644 index 0000000..935a2a0 --- /dev/null +++ b/qtools/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 display 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/qtools/LICENSE.QPL b/qtools/LICENSE.QPL new file mode 100644 index 0000000..ecdad6e --- /dev/null +++ b/qtools/LICENSE.QPL @@ -0,0 +1,103 @@ + THE Q PUBLIC LICENSE + version 1.0 + + Copyright (C) 1999-2000 Trolltech AS, Norway. + Everyone is permitted to copy and + distribute this license document. + +The intent of this license is to establish freedom to share and change the +software regulated by this license under the open source model. + +This license applies to any software containing a notice placed by the +copyright holder saying that it may be distributed under the terms of +the Q Public License version 1.0. Such software is herein referred to as +the Software. This license covers modification and distribution of the +Software, use of third-party application programs based on the Software, +and development of free software which uses the Software. + + Granted Rights + +1. You are granted the non-exclusive rights set forth in this license + provided you agree to and comply with any and all conditions in this + license. Whole or partial distribution of the Software, or software + items that link with the Software, in any form signifies acceptance of + this license. + +2. You may copy and distribute the Software in unmodified form provided + that the entire package, including - but not restricted to - copyright, + trademark notices and disclaimers, as released by the initial developer + of the Software, is distributed. + +3. You may make modifications to the Software and distribute your + modifications, in a form that is separate from the Software, such as + patches. The following restrictions apply to modifications: + + a. Modifications must not alter or remove any copyright notices in + the Software. + + b. When modifications to the Software are released under this + license, a non-exclusive royalty-free right is granted to the + initial developer of the Software to distribute your modification + in future versions of the Software provided such versions remain + available under these terms in addition to any other license(s) of + the initial developer. + +4. You may distribute machine-executable forms of the Software or + machine-executable forms of modified versions of the Software, provided + that you meet these restrictions: + + a. You must include this license document in the distribution. + + b. You must ensure that all recipients of the machine-executable forms + are also able to receive the complete machine-readable source code + to the distributed Software, including all modifications, without + any charge beyond the costs of data transfer, and place prominent + notices in the distribution explaining this. + + c. You must ensure that all modifications included in the + machine-executable forms are available under the terms of this + license. + +5. You may use the original or modified versions of the Software to + compile, link and run application programs legally developed by you + or by others. + +6. You may develop application programs, reusable components and other + software items that link with the original or modified versions of the + Software. These items, when distributed, are subject to the following + requirements: + + a. You must ensure that all recipients of machine-executable forms of + these items are also able to receive and use the complete + machine-readable source code to the items without any charge + beyond the costs of data transfer. + + b. You must explicitly license all recipients of your items to use + and re-distribute original and modified versions of the items in + both machine-executable and source code forms. The recipients must + be able to do so without any charges whatsoever, and they must be + able to re-distribute to anyone they choose. + + + c. If the items are not available to the general public, and the + initial developer of the Software requests a copy of the items, + then you must supply one. + + Limitations of Liability + +In no event shall the initial developers or copyright holders be liable +for any damages whatsoever, including - but not restricted to - lost +revenue or profits or other direct, indirect, special, incidental or +consequential damages, even if they have been advised of the possibility +of such damages, except to the extent invariable law, if any, provides +otherwise. + + No Warranty + +The Software and this license document are provided AS IS with NO WARRANTY +OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. + Choice of Law + +This license is governed by the Laws of Norway. Disputes shall be settled +by Oslo City Court. diff --git a/qtools/Makefile.in b/qtools/Makefile.in new file mode 100644 index 0000000..730d6b2 --- /dev/null +++ b/qtools/Makefile.in @@ -0,0 +1,30 @@ +# +# +# +# Copyright (C) 1997-2000 by Dimitri van Heesch. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation under the terms of the GNU General Public License is hereby +# granted. No representations are made about the suitability of this software +# for any purpose. It is provided "as is" without express or implied warranty. +# See the GNU General Public License for more details. +# +# Documents produced by Doxygen are derivative works derived from the +# input used in their production; they are not affected by this license. +# + +all: Makefile.qtools Makefile + $(MAKE) -f Makefile.qtools $@ + +Makefile.qtools: qtools.pro + $(PERL) $(TMAKE) qtools.pro >Makefile.qtools + +tmake: + $(PERL) $(TMAKE) qtools.pro >Makefile.qtools + +clean: Makefile.qtools + $(MAKE) -f Makefile.qtools clean + +distclean: clean + +FORCE: diff --git a/qtools/README b/qtools/README new file mode 100644 index 0000000..1e7fc8d --- /dev/null +++ b/qtools/README @@ -0,0 +1,4 @@ +This directory contains a small subset of Troll-Tech's Qt library +The subset is enough to build the doxygen executable, but lacks many of +the features found in the Qt library. See http://www.trolltech.com +for the full package. diff --git a/qtools/qarray.h b/qtools/qarray.h new file mode 100644 index 0000000..90dcbb7 --- /dev/null +++ b/qtools/qarray.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** +** Definition of QArray 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 QARRAY_H +#define QARRAY_H + +#ifndef QT_H +#include "qgarray.h" +#endif // QT_H + + +template<class type> class Q_EXPORT QArray : public QGArray +{ +public: + typedef type* Iterator; + typedef const type* ConstIterator; + typedef type ValueType; + +protected: + QArray( int, int ) : QGArray( 0, 0 ) {} + +public: + QArray() {} + QArray( int size ) : QGArray(size*sizeof(type)) {} + QArray( const QArray<type> &a ) : QGArray(a) {} + ~QArray() {} + QArray<type> &operator=(const QArray<type> &a) + { return (QArray<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(); } + QArray<type> copy() const + { QArray<type> tmp; return tmp.duplicate(*this); } + QArray<type>& assign( const QArray<type>& a ) + { return (QArray<type>&)QGArray::assign(a); } + QArray<type>& assign( const type *a, uint n ) + { return (QArray<type>&)QGArray::assign((char*)a,n*sizeof(type)); } + QArray<type>& duplicate( const QArray<type>& a ) + { return (QArray<type>&)QGArray::duplicate(a); } + QArray<type>& duplicate( const type *a, uint n ) + { return (QArray<type>&)QGArray::duplicate((char*)a,n*sizeof(type)); } + QArray<type>& setRawData( const type *a, uint n ) + { return (QArray<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)); } + 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 QArray<type> &a ) const { return isEqual(a); } + bool operator!=( const QArray<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(); } +}; + + +#endif // QARRAY_H diff --git a/qtools/qasciidict.h b/qtools/qasciidict.h new file mode 100644 index 0000000..3f2deaf --- /dev/null +++ b/qtools/qasciidict.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** +** 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 Q_EXPORT QAsciiDict : public QGDict +{ +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(); } +private: + void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } +}; + + +template<class type> class Q_EXPORT 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/qtools/qbuffer.cpp b/qtools/qbuffer.cpp new file mode 100644 index 0000000..beed0ba --- /dev/null +++ b/qtools/qbuffer.cpp @@ -0,0 +1,465 @@ +/**************************************************************************** +** +** +** Implementation 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. +** +**********************************************************************/ + +#include "qbuffer.h" +#include <stdlib.h> + +// REVISED: paul +/*! + \class QBuffer qbuffer.h + \brief The QBuffer class is an I/O device that operates on a QByteArray + + \ingroup io + + QBuffer allows reading and writing a memory buffer. It is normally + used together 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 with an + existing byte array. The byte array can also be set with setBuffer(). + Writing to the QBuffer will modify the original byte array, since + 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(). + + The 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 \0 + b.writeBlock( "def", 4 ); // write including \0 + b.close(); + // Now, str == "abcdef" + \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; +} + +/*! + Destructs the buffer. +*/ + +QBuffer::~QBuffer() +{ +} + + +/*! + Replaces the buffer's contents with \a buf. + + This may not be done when 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(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 the mode \a m. Returns TRUE if successful, + otherwise FALSE. The buffer must be opened before use. + + The mode parameter \a m must be a combination of the following flags. + <ul> + <li>\c IO_ReadOnly opens a buffer in read-only mode. + <li>\c IO_WriteOnly opens a buffer in write-only mode. + <li>\c IO_ReadWrite opens a buffer in read/write mode. + <li>\c IO_Append sets the buffer index to the end of the buffer. + <li>\c IO_Truncate truncates the buffer. + </ul> + + \sa close(), isOpen() +*/ + +bool QBuffer::open( int m ) +{ + if ( isOpen() ) { // buffer already open +#if defined(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 int QBuffer::at() const + \reimp +*/ + +/*! + \fn uint QBuffer::size() const + \reimp +*/ + +/*! + \reimp +*/ + +bool QBuffer::at( int pos ) +{ +#if defined(CHECK_STATE) + if ( !isOpen() ) { + qWarning( "QBuffer::at: Buffer is not open" ); + return FALSE; + } +#endif + if ( (uint)pos > a_len ) { +#if defined(CHECK_RANGE) + qWarning( "QBuffer::at: Index %d out of range", pos ); +#endif + return FALSE; + } + ioIndex = pos; + return TRUE; +} + + +/*! + \reimp +*/ + +int QBuffer::readBlock( char *p, uint len ) +{ +#if defined(CHECK_STATE) + CHECK_PTR( p ); + 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 ( (uint)ioIndex + len > a.size() ) { // overflow + if ( (uint)ioIndex >= a.size() ) { + setStatus( IO_ReadError ); + return -1; + } else { + len = a.size() - (uint)ioIndex; + } + } + memcpy( p, a.data()+ioIndex, len ); + ioIndex += len; + return len; +} + +/*! + \reimp + + Writes \a len bytes from \a p into the buffer at the current index, + overwriting any characters there and extending the buffer if necessary. + Returns the number of bytes actually written. + + Returns -1 if a serious error occurred. + + \sa readBlock() +*/ + +int QBuffer::writeBlock( const char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QBuffer::writeBlock: Null pointer error" ); +#endif +#if defined(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 ( (uint)ioIndex + len >= a_len ) { // overflow + uint new_len = a_len + a_inc*(((uint)ioIndex+len-a_len)/a_inc+1); + if ( !a.resize( new_len ) ) { // could not resize +#if defined(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 = (uint)ioIndex + len; + } + memcpy( a.data()+ioIndex, p, len ); + ioIndex += len; + if ( a.shd->len < (uint)ioIndex ) + a.shd->len = (uint)ioIndex; // fake (not alloc'd) length + return len; +} + + +/*! + \reimp +*/ + +int QBuffer::readLine( char *p, uint maxlen ) +{ +#if defined(CHECK_STATE) + CHECK_PTR( p ); + 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; + uint start = (uint)ioIndex; + char *d = a.data() + ioIndex; + maxlen--; // make room for 0-terminator + if ( a.size() - (uint)ioIndex < maxlen ) + maxlen = a.size() - (uint)ioIndex; + while ( maxlen-- ) { + if ( (*p++ = *d++) == '\n' ) + break; + } + *p = '\0'; + ioIndex = d - a.data(); + return (uint)ioIndex - start; +} + + +/*! + \reimp +*/ + +int QBuffer::getch() +{ +#if defined(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 ( (uint)ioIndex+1 > a.size() ) { // overflow + setStatus( IO_ReadError ); + return -1; + } + return uchar(*(a.data()+ioIndex++)); +} + +/*! + \reimp + Writes the character \a ch into the buffer, overwriting + the character at the current index, extending the buffer + if necessary. + + Returns \a ch, or -1 if some error occurred. + + \sa getch(), ungetch() +*/ + +int QBuffer::putch( int ch ) +{ +#if defined(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 ( (uint)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 < (uint)ioIndex ) + a.shd->len = (uint)ioIndex; + } + return ch; +} + +/*! + \reimp +*/ + +int QBuffer::ungetch( int ch ) +{ +#if defined(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/qtools/qbuffer.h b/qtools/qbuffer.h new file mode 100644 index 0000000..9dcd286 --- /dev/null +++ b/qtools/qbuffer.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** +** 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(); + + uint size() const; + int at() const; + bool at( int ); + + int readBlock( char *p, uint ); + int writeBlock( const char *p, uint ); + int readLine( char *p, uint ); + + 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 uint QBuffer::size() const +{ return a.size(); } + +inline int QBuffer::at() const +{ return ioIndex; } + + +#endif // QBUFFER_H diff --git a/qtools/qcollection.cpp b/qtools/qcollection.cpp new file mode 100644 index 0000000..e70b64b --- /dev/null +++ b/qtools/qcollection.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** +** Implementation of base class for all 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 "qcollection.h" + +// NOT REVISED +/*! + \class QCollection qcollection.h + \brief The QCollection class is the base class of all Qt collections. + + \ingroup collection + \ingroup tools + + The QCollection class is an abstract base class for the Qt \link + collection.html collection classes\endlink QDict, QList etc. via QGDict, + QGList etc. + + A QCollection knows only 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. + + \sa \link collection.html Collection Classes\endlink +*/ + + +/*! \enum QCollection::Item + + This type is the generic "item" in a QCollection. +*/ + + +/*! + \fn QCollection::QCollection() + + Constructs a collection. The constructor is protected because + QCollection is an abstract class. +*/ + +/*! + \fn QCollection::QCollection( const QCollection & source ) + + Constructs a copy of \a source with autoDelete() set to FALSE. The + constructor is protected because QCollection is an abstract class. + + Note that if \a source has autoDelete turned on, copying it is a + good way to get memory leaks, reading freed memory, or both. +*/ + +/*! + \fn QCollection::~QCollection() + Destroys the collection. The destructor is protected because QCollection + is an abstract class. +*/ + + +/*! + \fn bool QCollection::autoDelete() const + Returns the setting of the auto-delete option (default is FALSE). + \sa setAutoDelete() +*/ + +/*! + \fn void QCollection::setAutoDelete( bool enable ) + + Sets the auto-delete option of the collection. + + Enabling auto-delete (\e enable is TRUE) will delete objects that + are removed from the collection. This can be useful if the + collection has the only reference to the objects. (Note that the + object can still be copied using the copy constructor - copying such + objects is a good way to get memory leaks, reading freed memory or + both.) + + Disabling auto-delete (\e enable is FALSE) will \e not delete objects + that are removed from the collection. This is useful if the objects + are part of many collections. + + The default setting is FALSE. + + \sa autoDelete() +*/ + + +/*! + \fn virtual uint QCollection::count() const + Returns the number of objects in the collection. +*/ + +/*! + \fn virtual void QCollection::clear() + Removes all objects from the collection. The objects will be deleted + if auto-delete has been enabled. + \sa setAutoDelete() +*/ + + +/*! + Virtual function that creates a copy of an object that is about to + be inserted into the collection. + + The default implementation returns the \e 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() +*/ + +QCollection::Item QCollection::newItem( Item d ) +{ + return d; // just return reference +} + +/*! + Virtual function that deletes an item that is about to be removed from + the collection. + + The default implementation deletes \e d pointer if and only if + auto-delete has been enabled. + + This function is always reimplemented in the collection template + classes. + + \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 + destructed. + + \sa newItem(), setAutoDelete() +*/ + +void QCollection::deleteItem( Item d ) +{ + if ( del_item ) +#if defined(Q_DELETING_VOID_UNDEFINED) + delete (char *)d; // default operation +#else + delete d; // default operation +#endif +} diff --git a/qtools/qcollection.h b/qtools/qcollection.h new file mode 100644 index 0000000..c7ba00f --- /dev/null +++ b/qtools/qcollection.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** +** Definition of base class for all collection classes +** +** Created : 920629 +** +** 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 QCOLLECTION_H +#define QCOLLECTION_H + +#ifndef QT_H +#include "qglobal.h" +#endif // QT_H + + +class QGVector; +class QGList; +class QGDict; + + +class Q_EXPORT QCollection // 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: + QCollection() { del_item = FALSE; } // no deletion of objects + QCollection(const QCollection &) { del_item = FALSE; } + virtual ~QCollection() {} + + bool del_item; // default FALSE + + virtual Item newItem( Item ); // create object + virtual void deleteItem( Item ); // delete object +}; + + +#endif // QCOLLECTION_H diff --git a/qtools/qconfig.h b/qtools/qconfig.h new file mode 100644 index 0000000..fe14e97 --- /dev/null +++ b/qtools/qconfig.h @@ -0,0 +1,8 @@ +// Empty leaves all features enabled. See doc/html/features.html for choices. + +// 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. + +#define QT_DLL // Internal diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp new file mode 100644 index 0000000..77dc386 --- /dev/null +++ b/qtools/qcstring.cpp @@ -0,0 +1,1917 @@ +/**************************************************************************** +** +** +** 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" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <ctype.h> + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +/*! + \fn void *memmove( void *dst, const void *src, uint len ) + \relates QCString + + This function is normally part of the C library. Qt implements + memmove() for platforms that do not have it. + + memmove() copies \e len bytes from \e src into \e dst. The data is + copied correctly even if \e src and \e 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 \e str (using \c new), copies it, and returns + a pointer to the copy. + If \e src is null, it immediately returns 0. +*/ + +char *qstrdup( const char *str ) +{ + if ( !str ) + return 0; + char *dst = new char[strlen(str)+1]; + CHECK_PTR( dst ); + return strcpy( dst, str ); +} + +/*! + \relates QCString + + A safe strncpy() function. + + Copies all characters up to \e len bytes from \e str into \e dst and returns + a pointer to \e dst. Guarantees that \e dst is \0-terminated. + If \e src is null, it immediately returns 0. + + \sa qstrcpy() +*/ + +char *qstrncpy( char *dst, const char *src, uint len ) +{ + if ( !src ) + 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 \e str1 and \e str2. Returns a negative value if \e str1 + is less than \e str2, 0 if \e str1 is equal to \e str2 or a positive + value if \e str1 is greater than \e str2. + + Special case I: Returns 0 if \e str1 and \e str2 are both null. + + Special case II: Returns a random nonzero value if \e str1 is null + or \e str2 is null (but not both). + + \sa qstrncmp(), qstricmp(), qstrnicmp() +*/ + +/*! + \fn int qstrncmp( const char *str1, const char *str2, uint len ) + \relates QCString + + A safe strncmp() function. + + Compares \e str1 and \e str2 up to \e len bytes. + + Returns a negative value if \e str1 is less than \e str2, 0 if \e str1 + is equal to \e str2 or a positive value if \e str1 is greater than \e + str2. + + Special case I: Returns 0 if \e str1 and \e str2 are both null. + + Special case II: Returns a random nonzero value if \e str1 is null + or \e str2 is null (but not both). + + \sa qstrcmp(), qstricmp(), qstrnicmp() +*/ + +/*! + \fn int qstricmp( const char *str1, const char *str2 ) + \relates QCString + + A safe stricmp() function. + + Compares \e str1 and \e str2 ignoring the case. + + Returns a negative value if \e str1 is less than \e str2, 0 if \e str1 + is equal to \e str2 or a positive value if \e str1 is greater than \e + str2. + + Special case I: Returns 0 if \e str1 and \e str2 are both null. + + Special case II: Returns a random nonzero value if \e str1 is null + or \e str2 is null (but not both). + + \sa qstrcmp(), qstrncmp(), qstrnicmp() +*/ + +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 == s1 ? 0 : (int)((long)s2 - (long)s1); + for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ ) + if ( !c ) // strings are equal + break; + return res; +} + +/*! + \fn int strnicmp( const char *str1, const char *str2, uint len ) + \relates QCString + + A safe strnicmp() function. + + Compares \e str1 and \e str2 up to \e len bytes ignoring the case. + + Returns a negative value if \e str1 is less than \e str2, 0 if \e str1 + is equal to \e str2 or a positive value if \e str1 is greater than \e + str2. + + Special case I: Returns 0 if \e str1 and \e str2 are both null. + + Special case II: Returns a random nonzero value if \e str1 is null + or \e str2 is null (but not both). + + \sa qstrcmp(), qstrncmp() qstricmp() +*/ + +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 (int)((long)s2 - (long)s1); + 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 QByteArray + Returns the CRC-16 checksum of \e len bytes starting at \e 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 + 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); +} + + +/***************************************************************************** + QByteArray member functions + *****************************************************************************/ + +// NOT REVISED +/*! \class QByteArray qcstring.h + + \brief The QByteArray class provides an array of bytes. + + \inherit QArray + \ingroup tools + \ingroup shared + + QByteArray is defined as QArray\<char\>. +*/ + + +/***************************************************************************** + QByteArray stream functions + *****************************************************************************/ + +/*! + \relates QByteArray + Writes a byte array to a stream 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 QByteArray + Reads a byte array from a stream 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(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 + + \brief The QCString class provides an abstraction of the classic C + zero-terminated char array (<var>char*</var>). + + \ingroup tools + \ingroup shared + + QCString inherits QByteArray, which is defined as QArray\<char\>. + + Since QCString is a QArray, it uses \e explicit + \link shclass.html sharing\endlink with a reference count. + + You might use QCString for text that is never exposed to the user, + but for text the user sees, you should use QString (which provides + implicit sharing, Unicode and other internationalization support). + + Note that QCString is one of the weaker classes in Qt; its design is + flawed (it tries to behave like a more convenient const char *) and + as a result, algorithms that use QCString heavily all too often + perform badly. For example, append() is O(length()) since it scans + for a null terminator, which makes many algorithms that use QCString + scale even worse. + + Note that for the QCString methods that take a <var>const char *</var> + parameter the results are undefined if the QCString is not + zero-terminated. It is legal for the <var>const char *</var> parameter + to be 0. + + A QCString that has not been assigned to anything is \e null, i.e. both + the length and 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 <var>const char + * 0</var> to QCString gives a null QCString. + + \sa \link shclass.html Shared classes\endlink +*/ + + +/* + Implementation 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. Therefore, if you are giong to perform many QRegExp searches + on one and the same, large QCString, you will get better performance + by converting the QCString to a QString yourself, and do the + searches on that. The results will be of course be identical. +*/ + + + +/*! + \fn QCString::QCString() + Constructs a null string. + \sa isNull() +*/ + +/*! + \fn QCString::QCString( const QCString &s ) + Constructs a shallow copy \e s. + \sa assign() +*/ + +/*! + Constructs a string with room for \e size characters, including the + '\0'-terminator. Makes a null string if \e size == 0. + + If \e 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 \e 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 \e str, that is no more + than \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 the 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; +} + +/*! + \fn QCString &QCString::operator=( const QCString &s ) + Assigns a shallow copy of \e s to this string and returns a reference to + this string. +*/ + +/*! + \fn 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. + 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. + 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 \e 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 \e len bytes, including the + '\0'-terminator. + + A \0-terminator is set at position <code>len - 1</code> unless + <code>len == 0</code>. + + Example: + \code + QCString s = "resize this string"; + s.resize( 7 ); // s == "resize" + \endcode + + \sa truncate() +*/ + +bool QCString::resize( uint len ) +{ + detach(); + if ( !QByteArray::resize(len) ) + return FALSE; + if ( len ) + *(data()+len-1) = '\0'; + return TRUE; +} + + +/*! + Implemented as a call to the native vsprintf() (see your C-library + manual). + + If your 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 natural 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 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 begging for trouble. + Sooner or later someone \e will paste a 3000-character 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 \e len bytes of value \e c, followed by a + '\0'-terminator. + + If \e len is negative, then the current string length is used. + + Returns FALSE is \e len is nonnegative and there is no memory to + resize the string, otherwise TRUE is returned. +*/ + +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 \e c, starting at + position \e index. + + The search is case sensitive if \e cs is TRUE, or case insensitive if \e + cs is FALSE. + + Returns the position of \e c, or -1 if \e c could not be found. +*/ + +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( c ); + while ( *d && tolower(*d) != c ) + d++; + if ( !*d && c ) // not found + d = 0; + } + return d ? (int)(d - data()) : -1; +} + +/*! + Finds the first occurrence of the string \e str, starting at position + \e index. + + The search is case sensitive if \e cs is TRUE, or case insensitive if \e + cs is FALSE. + + Returns the position of \e str, or -1 if \e str could not be found. +*/ + +int QCString::find( const char *str, int index, bool cs ) const +{ + if ( (uint)index >= size() ) // index outside string + return -1; + if ( !str ) // no search string + return -1; + if ( !*str ) // zero-length search string + return index; + register const char *d; + if ( cs ) { // case sensitive + d = strstr( data()+index, str ); + } else { // case insensitive + d = data()+index; + int len = qstrlen( str ); + while ( *d ) { + if ( qstrnicmp(d, str, len) == 0 ) + break; + d++; + } + if ( !*d ) // not found + d = 0; + } + return d ? (int)(d - data()) : -1; +} + +/*! + Finds the first occurrence of the character \e c, starting at + position \e index and searching backwards. + + The search is case sensitive if \e cs is TRUE, or case insensitive if \e + cs is FALSE. + + Returns the position of \e c, or -1 if \e c could not be found. +*/ + +int QCString::findRev( char c, int index, bool cs ) const +{ + const char *b = data(); + const char *d; + if ( index < 0 ) { // neg index ==> start from end + if ( size() == 0 ) + return -1; + if ( cs ) { + d = strrchr( b, c ); + return d ? (int)(d - b) : -1; + } + index = length(); + } else if ( (uint)index >= size() ) { // bad index + return -1; + } + d = b+index; + if ( cs ) { // case sensitive + while ( d >= b && *d != c ) + d--; + } else { // case insensitive + c = tolower( c ); + while ( d >= b && tolower(*d) != c ) + d--; + } + return d >= b ? (int)(d - b) : -1; +} + +/*! + Finds the first occurrence of the string \e str, starting at + position \e index and searching backwards. + + The search is case sensitive if \e cs is TRUE, or case insensitive if \e + cs is FALSE. + + Returns the position of \e str, or -1 if \e str could not be found. +*/ + +int QCString::findRev( const char *str, int index, bool cs ) const +{ + int slen = qstrlen(str); + if ( index < 0 ) // neg index ==> start from end + index = length()-slen; + else if ( (uint)index >= size() ) // bad index + return -1; + else if ( (uint)(index + slen) > length() ) // str would be too long + index = length() - slen; + if ( index < 0 ) + return -1; + + register char *d = data() + index; + if ( cs ) { // case sensitive + for ( int i=index; i>=0; i-- ) + if ( qstrncmp(d--,str,slen)==0 ) + return i; + } else { // case insensitive + for ( int i=index; i>=0; i-- ) + if ( qstrnicmp(d--,str,slen)==0 ) + return i; + } + return -1; +} + + +/*! + Returns the number of times the character \e c occurs in the string. + + The match is case sensitive if \e cs is TRUE, or case insensitive if \e cs + if FALSE. +*/ + +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( c ); + while ( *d ) { + if ( tolower(*d) == c ) + count++; + d++; + } + } + return count; +} + +/*! + Returns the number of times \e str occurs in the string. + + The match is case sensitive if \e cs is TRUE, or case insensitive if \e + cs if FALSE. + + This function counts overlapping substrings, for example, "banana" + contains two occurrences of "ana". + + \sa findRev() +*/ + +int QCString::contains( const char *str, bool cs ) const +{ + int count = 0; + char *d = data(); + if ( !d ) + return 0; + int len = qstrlen( str ); + while ( *d ) { // counts overlapping strings + if ( cs ) { + if ( qstrncmp( d, str, len ) == 0 ) + count++; + } else { + if ( qstrnicmp(d, str, len) == 0 ) + count++; + } + d++; + } + return count; +} + +/*! + Returns a substring that contains the \e len leftmost characters + of the string. + + The whole string is returned if \e 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 \e len rightmost characters + of the string. + + The whole string is returned if \e 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 the \e len characters of this + string, starting at position \e index. + + Returns a null string if the string is empty or \e index is out + of range. Returns the whole string from \e index if \e index+len exceeds + the length of the string. + + Example: + \code + QCString s = "Two pineapples"; + QCString t = s.mid( 4, 4 ); // t == "pine" + \endcode + + \sa left(), right() +*/ + +QCString QCString::mid( uint index, uint len ) const +{ + if ( len == 0xffffffff ) len = length()-index; + uint slen = qstrlen( data() ); + if ( isEmpty() || index >= slen ) { + QCString empty; + return empty; + } else { + 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 \e width (plus '\0') that contains this + string and padded by the \e fill character. + + If the length of the string exceeds \e width and \e truncate is FALSE, + then the returned string is a copy of the string. + If the length of the string exceeds \e width and \e truncate is TRUE, + then the returned string is a left(\e 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 \e width (plus '\0') that contains pad + characters followed by the string. + + If the length of the string exceeds \e width and \e truncate is FALSE, + then the returned string is a copy of the string. + If the length of the string exceeds \e width and \e truncate is TRUE, + then the returned string is a left(\e 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 the string converted to lower case. + + Presently it only handles 7-bit ASCII, or whatever tolower() + handles (if $LC_CTYPE is set, most UNIX systems do the Right Thing). + + Example: + \code + QCString s("TeX"); + QCString t = s.lower(); // t == "tex" + \endcode + + \sa upper() +*/ + +QCString QCString::lower() const +{ + QCString s( data() ); + register char *p = s.data(); + if ( p ) { + while ( *p ) { + *p = tolower(*p); + p++; + } + } + return s; +} + +/*! + Returns a new string that is the string converted to upper case. + + Presently it only handles 7-bit ASCII, or whatever toupper() + handles (if $LC_CTYPE is set, most UNIX systems do the Right Thing). + + Example: + \code + QCString s("TeX"); + QCString t = s.upper(); // t == "TEX" + \endcode + + \sa lower() +*/ + +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 any ASCII code 9, 10, 11, 12, 13 or 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(s[0]) && !isspace(s[reslen-1]) ) + return result; // returns a copy + + s = result.data(); + int start = 0; + int end = reslen - 1; + while ( isspace(s[start]) ) // skip white space from start + start++; + if ( s[start] == '\0' ) { // only white space + result.resize( 1 ); + return result; + } + while ( end && isspace(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 any ASCII code 9, 10, 11, 12, 13 or 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; + while ( TRUE ) { + while ( *from && isspace(*from) ) + from++; + while ( *from && !isspace(*from) ) + *to++ = *from++; + if ( *from ) + *to++ = 0x20; // ' ' + else + break; + } + if ( to > first && *(to-1) == 0x20 ) + to--; + *to = '\0'; + result.resize( (int)((long)to - (long)result.data()) + 1 ); + return result; +} + + +/*! + Insert \e s into the string before position \e index. + + If \e index is beyond the end of the string, the string is extended with + spaces (ASCII 32) to length \e index and \e s is then appended. + + \code + QCString s = "I like fish"; + s.insert( 2, "don't "); // s == "I don't like fish" + s = "x"; + 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; +} + +/*! + Insert \e c into the string at (before) position \e index and returns + a reference to the string. + + If \e index is beyond the end of the string, the string is extended with + spaces (ASCII 32) to length \e index and \e c is then 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 \e len characters starting at position \e index from the + string and returns a reference to the string. + + If \e index is too big, nothing happens. If \e index is valid, but + \e len is too large, the rest of the string is removed. + + \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 \e len characters starting at position \e index from the + string with \e s, and returns a reference to the string. + + If \e index is too big, nothing is deleted and \e s is inserted at the + end of the string. If \e index is valid, but \e len is too large, \e + str replaces the rest of the string. + + \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 *s ) +{ + remove( index, len ); + insert( index, s ); + return *this; +} + + +/*! + Finds the first occurrence of the regular expression \e rx, starting at + position \e index. + + Returns the position of the next match, or -1 if \e rx was not found. +*/ + +int QCString::find( const QRegExp &rx, int index ) const +{ + QString d = QString::fromLatin1( data() ); + return d.find( rx, index ); +} + +/*! + Finds the first occurrence of the regular expression \e rx, starting at + position \e index and searching backwards. + + The search will start from the end of the string if \e index is negative. + + Returns the position of the next match (backwards), or -1 if \e rx was not + found. +*/ + +int QCString::findRev( const QRegExp &rx, int index ) const +{ + QString d = QString::fromLatin1( data() ); + return d.findRev( rx, index ); +} + +/*! + Counts the number of overlapping occurrences of \e 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() +*/ + +int QCString::contains( const QRegExp &rx ) const +{ + QString d = QString::fromLatin1( data() ); + return d.contains( rx ); +} + + +/*! + Replaces every occurrence of \e rx in the string with \e str. + Returns a reference to the string. + + Example: + \code + QString s = "banana"; + s.replace( QRegExp("a.*a"), "" ); // becomes "b" + + QString s = "banana"; + s.replace( QRegExp("^[bn]a"), " " ); // becomes " nana" + + QString s = "banana"; + s.replace( QRegExp("^[bn]a"), "" ); // NOTE! becomes "" + \endcode + +*/ + +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; +} + +/*! + Returns the string converted to a <code>long</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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(*p) ) // skip leading space + p++; + if ( *p == '-' ) { + p++; + neg = 1; + } else if ( *p == '+' ) { + p++; + } + if ( !isdigit(*p) ) + goto bye; + while ( isdigit(*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(*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 <code>unsigned long</code> + value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +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(*p) ) // skip leading space + p++; + if ( *p == '+' ) + p++; + if ( !isdigit(*p) ) + goto bye; + while ( isdigit(*p) ) { + if ( val > max_mult || (val == max_mult && (*p-'0') > 5) ) + goto bye; + val = 10*val + (*p++ - '0'); + } + while ( isspace(*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 <code>short</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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 <code>unsigned short</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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 <code>int</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +int QCString::toInt( bool *ok ) const +{ + return (int)toLong( ok ); +} + +/*! + Returns the string converted to an <code>unsigned int</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +uint QCString::toUInt( bool *ok ) const +{ + return (uint)toULong( ok ); +} + +/*! + Returns the string converted to a <code>double</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no conceivable + errors, and FALSE if the string is not a number at all, or if it has + trailing garbage. +*/ + +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 <code>float</code> value. + + If \e ok is non-null, \e *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +float QCString::toFloat( bool *ok ) const +{ + return (float)toDouble( ok ); +} + + +/*! + Makes a deep copy of \e 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; +} + +/*! + Sets the string to the printed value of \e 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; +} + +/*! + Sets the string to the printed unsigned value of \e 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; +} + +/*! + \fn QCString &QCString::setNum( int n ) + Sets the string to the printed value of \e n and returns a reference + to the string. +*/ + +/*! + \fn QCString &QCString::setNum( uint n ) + Sets the string to the printed unsigned value of \e n and returns a + reference to the string. +*/ + +/*! + \fn QCString &QCString::setNum( short n ) + Sets the string to the printed value of \e n and returns a reference + to the string. +*/ + +/*! + \fn QCString &QCString::setNum( ushort n ) + Sets the string to the printed unsigned value of \e n and returns a + reference to the string. +*/ + +/*! + Sets the string to the printed value of \e n. + + \arg \e f is the format specifier: 'f', 'F', 'e', 'E', 'g', 'G' (same + as sprintf()). + \arg \e prec is the precision. + + Returns a reference to the string. +*/ + +QCString &QCString::setNum( double n, char f, int prec ) +{ +#if defined(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 ); +} + +/*! + \fn QCString &QCString::setNum( float n, char f, int prec ) + Sets the string to the printed value of \e n. + + \arg \e f is the format specifier: 'f', 'F', 'e', 'E', 'g', 'G' (same + as sprintf()). + \arg \e prec is the precision. + + Returns a reference to the string. +*/ + + +/*! + Sets the character at position \e index to \e c and expands the + string if necessary, filling with spaces. + + Returns FALSE if this \e index was out of range and the string could + not be expanded, otherwise 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 \e str to the string and returns a reference to the string. + Equivalent to operator+=(). + */ + +/*! + Appends \e 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; +} + +/*! + Appends \e 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 a string to the stream. + + \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 from the stream. + + \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(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 the two strings are equal, or FALSE if they are different. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator==( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if the two strings are equal, or FALSE if they are different. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator==( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if the two strings are equal, or FALSE if they are different. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator!=( const QCString &s1, const QCString &s2 ) + \relates QCString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator!=( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator!=( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator<( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically less than \e s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \< 0</code>. +*/ + +/*! + \fn bool operator<( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically less than \e s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \< 0</code>. +*/ + +/*! + \fn bool operator<=( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically less than or equal to \e s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \<= 0</code>. +*/ + +/*! + \fn bool operator<=( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically less than or equal to \e s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \<= 0</code>. +*/ + +/*! + \fn bool operator>( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically greater than \e s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \> 0</code>. +*/ + +/*! + \fn bool operator>( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically greater than \e s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \> 0</code>. +*/ + +/*! + \fn bool operator>=( const QCString &s1, const char *s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically greater than or equal to \e s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \>= 0</code>. +*/ + +/*! + \fn bool operator>=( const char *s1, const QCString &s2 ) + \relates QCString + Returns TRUE if \e s1 is alphabetically greater than or equal to \e s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \>= 0</code>. +*/ + +/*! + \fn QCString operator+( const QCString &s1, const QCString &s2 ) + \relates QCString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QCString operator+( const QCString &s1, const char *s2 ) + \relates QCString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QCString operator+( const char *s1, const QCString &s2 ) + \relates QCString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QCString operator+( const QCString &s, char c ) + \relates QCString + Returns the concatenated string of s and c. +*/ + +/*! + \fn QCString operator+( char c, const QCString &s ) + \relates QCString + Returns the concatenated string of c and s. +*/ diff --git a/qtools/qcstring.h b/qtools/qcstring.h new file mode 100644 index 0000000..073a969 --- /dev/null +++ b/qtools/qcstring.h @@ -0,0 +1,399 @@ +/**************************************************************************** +** +** +** Definition of the extended char array operations, +** and QByteArray and QCString classes +** +** 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 QCSTRING_H +#define QCSTRING_H + +#ifndef QT_H +#include "qarray.h" +#endif // QT_H + +#include <string.h> + +#if defined(_OS_SUN_) && defined(_CC_GNU_) +#include <strings.h> +#endif + + +/***************************************************************************** + Fixes and workarounds for some platforms + *****************************************************************************/ + +#if defined(_OS_HPUX_) +// HP-UX has badly defined strstr() etc. +// ### fix in 3.0: change hack_* to qt_hack_* +// by the way HP-UX is probably right, the standard has evolved and +// we'll have to adapt to it +inline char *hack_strstr( const char *s1, const char *s2 ) +{ return (char *)strstr(s1, s2); } +inline char *hack_strchr( const char *s, int c ) +{ return (char *)strchr(s, c); } +inline char *hack_strrchr( const char *s, int c ) +{ return (char *)strrchr(s, c); } +#define strstr(s1,s2) hack_strstr((s1),(s2)) +#define strchr(s,c) hack_strchr((s),(c)) +#define strrchr(s,c) hack_strrchr((s),(c)) +#endif + + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +Q_EXPORT void *qmemmove( void *dst, const void *src, uint len ); + +#if defined(_OS_SUN_) || defined(_CC_OC_) +#define memmove(s1,s2,n) qmemmove((s1),(s2),(n)) +#endif + +Q_EXPORT char *qstrdup( const char * ); + +Q_EXPORT inline uint cstrlen( const char *str ) +{ return strlen(str); } + +Q_EXPORT inline uint qstrlen( const char *str ) +{ return str ? strlen(str) : 0; } + +Q_EXPORT inline char *cstrcpy( char *dst, const char *src ) +{ return strcpy(dst,src); } + +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 cstrcmp( const char *str1, const char *str2 ) +{ return strcmp(str1,str2); } + +Q_EXPORT inline int qstrcmp( const char *str1, const char *str2 ) +{ return (str1 && str2) ? strcmp(str1,str2) : (int)((long)str2 - (long)str1); } + +Q_EXPORT inline int cstrncmp( const char *str1, const char *str2, uint len ) +{ return strncmp(str1,str2,len); } + +Q_EXPORT inline int qstrncmp( const char *str1, const char *str2, uint len ) +{ return (str1 && str2) ? strncmp(str1,str2,len) : + (int)((long)str2 - (long)str1); } + +Q_EXPORT int qstricmp( const char *, const char * ); + +Q_EXPORT int qstrnicmp( const char *, const char *, uint len ); + +// ### TODO for 3.0: these and the cstr* functions should be used if +// !defined(QT_CLEAN_NAMESPACE) +// We want to keep source compatibility for 2.x +// ### TODO for 4.0: completely remove these and the cstr* functions + +#if !defined(QT_GENUINE_STR) + +#undef strlen +#define strlen qstrlen + +#undef strcpy +#define strcpy qstrcpy + +#undef strcmp +#define strcmp qstrcmp + +#undef strncmp +#define strncmp qstrncmp + +#undef stricmp +#define stricmp qstricmp + +#undef strnicmp +#define strnicmp qstrnicmp + +#endif + + +// qChecksum: Internet checksum + +Q_EXPORT Q_UINT16 qChecksum( const char *s, uint len ); + +/***************************************************************************** + QByteArray class + *****************************************************************************/ + +#if defined(Q_TEMPLATEDLL) +template class Q_EXPORT QArray<char>; +#endif +typedef QArray<char> QByteArray; + + +/***************************************************************************** + 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 &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; + int find( const QRegExp &, int index=0 ) const; + int findRev( char c, int index=-1, bool cs=TRUE) const; + int findRev( const char *str, int index=-1, bool cs=TRUE) const; + int findRev( const QRegExp &, int index=-1 ) const; + int contains( char c, bool cs=TRUE ) const; + int contains( const char *str, bool cs=TRUE ) const; + int contains( const QRegExp & ) const; + + 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 * ); + QCString &replace( const QRegExp &, const 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 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 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 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 QCString operator+( const QCString &s1, const QCString &s2 ) +{ + QCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline QCString operator+( const QCString &s1, const char *s2 ) +{ + QCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline QCString operator+( const char *s1, const QCString &s2 ) +{ + QCString tmp( s1 ); + tmp += s2; + return tmp; +} + +Q_EXPORT inline QCString operator+( const QCString &s1, char c2 ) +{ + QCString tmp( s1.data() ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline QCString operator+( char c1, const QCString &s2 ) +{ + QCString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +#endif // QCSTRING_H diff --git a/qtools/qdatastream.cpp b/qtools/qdatastream.cpp new file mode 100644 index 0000000..7f63cbf --- /dev/null +++ b/qtools/qdatastream.cpp @@ -0,0 +1,951 @@ +/**************************************************************************** +** +** +** 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> + +// REVISED: warwick +/*! + \class QDataStream qdatastream.h + + \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 operation system, CPU or byte order. A + stream that is written by a PC under DOS/Windows can be read by a + Sun SPARC running Solaris. + + 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. + + The programmer 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. + + 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 data to a stream): + \code + QFile f( "file.dta" ); + f.open( IO_WriteOnly ); // open file for writing + QDataStream s( &f ); // serialize using f + s << "the answer is"; // serialize string + s << (Q_INT32)42; // serialize integer + \endcode + + Example (read data from a stream): + \code + QFile f( "file.dta" ); + f.open( IO_ReadOnly ); // open file for reading + QDataStream s( &f ); // serialize using f + char *str; + Q_INT32 a; + s >> str >> a; // "the answer is" and 42 + delete str; // delete string + \endcode + + In the last example, if you read into a QString instead of a \c char* + you do not have to delete it. + + Normally, each item written to the stream is written in a fixed binary + format. + For example, a \c char* is written as a 32-bit integer equal to the + length of the string including the NUL byte, followed by all the + characters of the string including the NUL byte. Similarly when + reading a string, 4 bytes are read to create the 32-bit length value, + then that many characters for the string including the NUL. For a complete + description of all Qt types supporting data streaming see \link + datastreamformat.html Format of the QDataStream operators \endlink . + + If you want a "parsing" input stream, see QTextStream. If you just want the + data to be human-readable to aid in debugging, you can set the data + stream into printable data mode with setPrintableData(). The data is + then written slower, in a human readable bloated form that is sufficient + for debugging. + + 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 + // Open the file. + QFile f( "file.xxx" ); + f.open( IO_WriteOnly ); + QDataStream s( &f ); + + // Write a header with a "magic number" and a version + s << 0xa0b0c0d0; + s << 123; + + // Write the data + s << [lots of interesting data] + \endcode + + Then read it in with: + + \code + // Open the file. + QFile f( "file.xxx" ); + f.open( IO_ReadOnly ); + QDataStream s( &f ); + + // Read and check the header + Q_UINT32 magic; + s >> magic; + if ( magic != 0xa0b0c0d0 ) + return XXX_BAD_FILE_FORMAT; + + // Read the version + Q_INT32 version; + s >> version; + if ( version < 100 ) + return XXX_BAD_FILE_TOO_OLD; + if ( version > 123 ) + return XXX_BAD_FILE_TOO_NEW; + if ( version <= 110 ) + s.setVersion(1); + + // Read the data + s >> [lots of interesting data]; + if ( version > 120 ) + s >> [data new in XXX version 1.2]; + s >> [other interesting data]; + \endcode + + \sa QTextStream QVariant +*/ + + +/***************************************************************************** + QDataStream member functions + *****************************************************************************/ + +#if defined(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 = 3; +// 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. + + \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 through an + internal QBuffer device. + + Example: + \code + static char 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 + a.resetRawData( bindata, sizeof(bindata) ); // finished + \endcode + + The QArray::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; +} + +/*! + Destructs 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 constructor. +*/ + +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 + 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 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. + \sa setPrintableData() +*/ + +/*! + \fn void QDataStream::setPrintableData( bool enable ) + Sets or clears the printable data flag. + + If this flag is set, the write functions will generate output that + consists of printable characters (7 bit ASCII). + + We recommend enabling printable data only for debugging purposes + (it is slower and creates larger output). +*/ + + +/*! + \fn int QDataStream::version() const + Returns the version number of the data serialization format. + In Qt 2.1, this number is by default 3. + \sa setVersion() +*/ + +/*! + \fn void QDataStream::setVersion( int v ) + Sets the version number of the data serialization format. + + In order to accomodate for 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. + + For Qt 1.x compatibility, use \a v == 1. + + For Qt 2.0.x compatibility, use \a v == 2 (Not required for reading in + Qt 2.1). + + \sa version() +*/ + +/***************************************************************************** + QDataStream read functions + *****************************************************************************/ + + +static Q_INT32 read_int_ascii( QDataStream *s ) +{ + register int n = 0; + char buf[40]; + while ( TRUE ) { + buf[n] = s->device()->getch(); + if ( buf[n] == '\n' || n > 38 ) // $-terminator + break; + n++; + } + buf[n] = '\0'; + return atol( buf ); +} + + +/*! + \fn QDataStream &QDataStream::operator>>( Q_UINT8 &i ) + Reads an unsigned byte from the stream and returns a reference to + the stream. +*/ + +/*! + Reads a signed byte from 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; +} + + +/*! + \fn QDataStream &QDataStream::operator>>( Q_UINT16 &i ) + Reads an unsigned 16-bit integer from the stream and returns a reference to + the stream. +*/ + +/*! + Reads a signed 16-bit integer from the stream 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; +} + + +/*! + \fn QDataStream &QDataStream::operator>>( Q_UINT32 &i ) + Reads an unsigned 32-bit integer from the stream and returns a reference to + the stream. +*/ + +/*! + Reads a signed 32-bit integer from the stream 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 + register 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; +} + +/*! + \fn QDataStream &QDataStream::operator>>( Q_UINT64 &i ) + Reads an unsigned 64-bit integer from the stream and returns a reference to + the stream, or uses the Q_UINT32 operator if 64 bit is not available. +*/ + +/*! + Reads a signed 64-bit integer from the stream and returns a reference to + the stream, or uses the Q_UINT32 operator if 64 bit is not available. +*/ + +QDataStream &QDataStream::operator>>( Q_INT64 &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_INT64) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[sizeof(Q_INT64)]; + dev->readBlock( b, sizeof(Q_INT64) ); + if ( sizeof(Q_INT64) == 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; +} + +static double read_double_ascii( QDataStream *s ) +{ + register int n = 0; + char buf[80]; + while ( TRUE ) { + buf[n] = s->device()->getch(); + if ( buf[n] == '\n' || n > 78 ) // $-terminator + break; + n++; + } + buf[n] = '\0'; + return atof( buf ); +} + + +/*! + Reads a 32-bit floating point number from 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 + f = (float)read_double_ascii( this ); + } else if ( noswap ) { // no conversion needed + dev->readBlock( (char *)&f, sizeof(float) ); + } else { // swap bytes + register 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; +} + + +/*! + Reads a 64-bit floating point number from 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 + 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; +} + + +/*! + 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 + eventually call delete[] on the value. +*/ + +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 an Q_UINT32 length specifier first, then the + data (\a l bytes). + + \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 + 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. + + \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 + *****************************************************************************/ + + +/*! + \fn QDataStream &QDataStream::operator<<( Q_UINT8 i ) + Writes an unsigned byte to the stream and returns a reference to + the stream. +*/ + +/*! + Writes a signed byte to the stream. +*/ + +QDataStream &QDataStream::operator<<( Q_INT8 i ) +{ + CHECK_STREAM_PRECOND + if ( printable && (i == '\\' || !isprint(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; +} + + +/*! + \fn QDataStream &QDataStream::operator<<( Q_UINT16 i ) + Writes an unsigned 16-bit integer to the stream and returns a reference + to the stream. +*/ + +/*! + Writes a signed 16-bit integer 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; +} + + +/*! + \fn QDataStream &QDataStream::operator<<( Q_UINT32 i ) + Writes an unsigned 32-bit integer to the stream and returns a reference to + the stream. +*/ + +/*! + Writes a signed 32-bit integer 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; +} + +/*! + \fn QDataStream &QDataStream::operator<<( Q_UINT64 i ) + Writes an unsigned 64-bit integer to the stream and returns a reference to + the stream, or uses the Q_UINT32-operator if 64 bit is not available. +*/ + +/*! + Writes a signed 64-bit integer to the stream and returns a reference to + the stream, or calls the Q_INT32-operator if 64 bit is not available. +*/ + +QDataStream &QDataStream::operator<<( Q_INT64 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_INT64) ); + } else { // swap bytes + register uchar *p = (uchar *)(&i); + char b[sizeof(Q_INT64)]; + if ( sizeof(Q_INT64) == 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, sizeof(Q_INT64) ); + } + return *this; +} + +/*! + \fn QDataStream &QDataStream::operator<<( uint i ) + Writes an unsigned integer to the stream as a 32-bit unsigned integer + (Q_UINT32). + Returns a reference to the stream. +*/ + +/*! + \fn QDataStream &QDataStream::operator<<( int i ) + Writes a signed integer to the stream as a 32-bit signed integer (Q_INT32). + Returns a reference to the stream. +*/ + + +/*! + Writes a 32-bit floating point number 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; +} + + +/*! + Writes a 64-bit floating point number 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; +} + + +/*! + 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 an Q_UINT32, followed by \a len bytes from + \a s. + + \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. + + \sa writeBytes(), QIODevice::writeBlock(), readRawBytes() +*/ + +QDataStream &QDataStream::writeRawBytes( const char *s, uint len ) +{ + CHECK_STREAM_PRECOND + if ( printable ) { // write printable + register char *p = (char *)s; + while ( len-- ) + *this << *p++; + } else { // write data char array + dev->writeBlock( s, len ); + } + return *this; +} + +#endif // QT_NO_DATASTREAM diff --git a/qtools/qdatastream.h b/qtools/qdatastream.h new file mode 100644 index 0000000..3d18062 --- /dev/null +++ b/qtools/qdatastream.h @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** +** 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_INT64 &i ); + QDataStream &operator>>( Q_UINT64 &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_INT64 i ); + QDataStream &operator<<( Q_UINT64 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_UINT64 &i ) +{ return *this >> (Q_INT64&)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_UINT64 i ) +{ return *this << (Q_INT64)i; } + + +#endif // QT_NO_DATASTREAM +#endif // QDATASTREAM_H diff --git a/qtools/qdatetime.cpp b/qtools/qdatetime.cpp new file mode 100644 index 0000000..521a022 --- /dev/null +++ b/qtools/qdatetime.cpp @@ -0,0 +1,1434 @@ +/**************************************************************************** +** +** +** 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. +** +**********************************************************************/ + +#define gettimeofday __hide_gettimeofday +#include "qdatetime.h" +#include "qdatastream.h" +#include <stdio.h> +#include <time.h> +#if defined(_OS_WIN32_) +#if defined(_CC_BOOL_DEF_) +#undef bool +#include <windows.h> +#define bool int +#else +#include <windows.h> +#endif +#elif defined(_OS_MSDOS_) +#include <dos.h> +#elif defined(_OS_OS2_) +#include <os2.h> +#elif defined(_OS_UNIX_) +#include <sys/time.h> +#include <unistd.h> +#undef gettimeofday +extern "C" int gettimeofday( struct timeval *, struct timezone * ); +#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}; + +// ##### Localize. + +const char * const QDate::monthNames[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +const char * const QDate::weekdayNames[] ={ + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; + + +/***************************************************************************** + QDate member functions + *****************************************************************************/ + +// REVISED: aavit + +/*! + \class QDate qdatetime.h + \brief The QDate class provides date functions. + + \ingroup time + + 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 a date by adding a number of + days. + + A QDate object is typically created either by giving the year, month + and day numbers explicitly, or by using the static function + currentDate(), which makes a QDate object which contains the + system's clock date. An explicit date can also be set using + setYMD(). + + 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(), dayName(), and monthName() functions. + + QDate provides a full set of operators to compare two QDate + objects. A date is considered smaller than another if it is earlier + than the other. + + The date a given number of days later than a given date can be found + using the addDays() function. Correspondingly, the number of days + between two dates can be found using the daysTo() function. + + The daysInMonth() and daysInYear() functions tell how many days + there are in this date's month and year, respectively. The + isLeapYear() function tells whether this date is in a leap year. + + Note that QDate may not be used for date calculations for dates in + the remote past, i.e. prior to the introduction of the Gregorian + calendar. This calendar was adopted by England Sep. 14. 1752 (hence + this is the earliest valid QDate), and subsequently by most other + western countries, until 1923. + + The end of time is reached around 8000AD, by which time we expect Qt + to be obsolete. + + \sa QTime, QDateTime +*/ + + +/*! + \fn QDate::QDate() + Constructs a null date. Null dates are invalid. + + \sa isNull(), isValid() +*/ + + +/*! + Constructs a date with the year \a y, month \a m and day \a d. + + \a y must be in the range 1752-ca. 8000, \a m must be in the range + 1-12, and \a d must be in the range 1-31. Exception: 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. A null date is invalid. + + \sa isValid() +*/ + + +/*! + Returns TRUE if this date is valid. + + \sa isNull() +*/ + +bool QDate::isValid() const +{ + return jd >= FIRST_DAY; +} + + +/*! + Returns the year (>= 1752) of this date. + + \sa month(), day() +*/ + +int QDate::year() const +{ + int y, m, d; + jul2greg( 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; + jul2greg( 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; + jul2greg( 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+1) % 7) + 6)%7 + 1; +} + +/*! + Returns the day of the year (1..365) for this date. + + \sa day(), dayOfWeek() +*/ + +int QDate::dayOfYear() const +{ + return jd - greg2jul(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; + jul2greg( 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; + jul2greg( jd, y, m, d ); + return leapYear(y) ? 366 : 365; +} + + +/*! + Returns the name of the \a month. + + Month 1 == "Jan", month 2 == "Feb" etc. + + \sa toString(), dayName() +*/ + +QString QDate::monthName( int month ) const +{ +#if defined(CHECK_RANGE) + if ( month < 1 || month > 12 ) { + qWarning( "QDate::monthName: Parameter out ouf range." ); + month = 1; + } +#endif + // ### Remove the fromLatin1 during localization + return QString::fromLatin1(monthNames[month-1]); +} + +/*! + Returns the name of the \a weekday. + + Weekday 1 == "Mon", day 2 == "Tue" etc. + + \sa toString(), monthName() +*/ + +QString QDate::dayName( int weekday ) const +{ +#if defined(CHECK_RANGE) + if ( weekday < 1 || weekday > 7 ) { + qWarning( "QDate::dayName: Parameter out of range." ); + weekday = 1; + } +#endif + // ### Remove the fromLatin1 during localization + return QString::fromLatin1(weekdayNames[weekday-1]); +} + + +/*! + Returns the date as a string. + + The string format is "Sat May 20 1995". This function uses the + dayName() and monthName() functions to generate the string. + + \sa dayName(), monthName() +*/ + +QString QDate::toString() const +{ + int y, m, d; + jul2greg( jd, y, m, d ); + QString buf = dayName(dayOfWeek()); + buf += ' '; + buf += monthName(m); + QString t; + t.sprintf( " %d %d", d, y); + buf += t; + return buf; +} + + +/*! + Sets the year \a y, month \a m and day \a d. + + \a y must be in the range 1752-ca. 8000, \a m must be in the range + 1-12, and \a d must be in the range 1-31. Exception: if \a y is in + the range 0-99, it is interpreted as 1900-1999. + + Returns TRUE if the date is valid, otherwise FALSE. +*/ + +bool QDate::setYMD( int y, int m, int d ) +{ + if ( !isValid(y,m,d) ) { +#if defined(CHECK_RANGE) + qWarning( "QDate::setYMD: Invalid date %04d/%02d/%02d", y, m, d ); +#endif + return FALSE; + } + jd = greg2jul( y, m, d ); +#if defined(DEBUG) + ASSERT( year() == y && month() == m && day() == d ); +#endif + 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 daysTo() +*/ + +QDate QDate::addDays( int ndays ) const +{ + QDate d; + d.jd = jd + ndays; + return d; +} + +/*! + 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, or FALSE if + they are different. +*/ + +/*! + \fn bool QDate::operator!=( const QDate &d ) const + Returns TRUE if this date is different from \a d, or FALSE if + they are equal. +*/ + +/*! + \fn bool QDate::operator<( const QDate &d ) const + Returns TRUE if this date is earlier than \a d, otherwise FALSE. +*/ + +/*! + \fn bool QDate::operator<=( const QDate &d ) const + Returns TRUE if this date is earlier than or equal to \a d, otherwise FALSE. +*/ + +/*! + \fn bool QDate::operator>( const QDate &d ) const + Returns TRUE if this date is later than \a d, otherwise FALSE. +*/ + +/*! + \fn bool QDate::operator>=( const QDate &d ) const + Returns TRUE if this date is later than or equal to \a d, otherwise FALSE. +*/ + + +/*! + Returns the current date, as reported by the system clock. + + \sa QTime::currentTime(), QDateTime::currentDateTime() +*/ + +QDate QDate::currentDate() +{ +#if defined(_OS_WIN32_) + + SYSTEMTIME t; + GetLocalTime( &t ); + QDate d; + d.jd = greg2jul( t.wYear, t.wMonth, t.wDay ); + return d; + +#else + + time_t ltime; + time( <ime ); + tm *t = localtime( <ime ); + QDate d; + d.jd = greg2jul( t->tm_year + 1900, t->tm_mon + 1, t->tm_mday ); + return d; + +#endif +} + +/*! + Returns TRUE if the specified date (year \a y, month \a m and day \a + d) is valid. + + Example: + \code + QDate::isValid( 2002, 5, 17 ); // TRUE; May 17th 2002 is OK. + 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 + + Note that 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. +*/ + +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 jul2greg() +*/ + +uint QDate::greg2jul( 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 greg2jul() +*/ + +void QDate::jul2greg( 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 + + \brief The QTime class provides clock time functions. + + \ingroup time + + A QTime object contains a clock time, i.e. a 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 operates with 24-hour clock format; it has no concept of + AM/PM. It operates with local time; it does not know anything 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 makes a QTime object which + 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. A 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. A null time is valid. + + \sa isValid() +*/ + +/*! + Returns TRUE if the time is valid, or FALSE if the time is invalid. + The time 23:30:55.746 is valid, while 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; +} + + +/*! + Returns the time of this object in a textual format. Milliseconds + are not included. The string format is HH:MM:SS, e.g. 1 second + before midnight would be "23:59:59". +*/ + +QString QTime::toString() const +{ + QString buf; + buf.sprintf( "%.2d:%.2d:%.2d", hour(), minute(), second() ); + return buf; +} + + +/*! + 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 FALSE. + + \sa isValid() +*/ + +bool QTime::setHMS( int h, int m, int s, int ms ) +{ + if ( !isValid(h,m,s,ms) ) { +#if defined(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 ms 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). + + Since QTime measures time within a day and there are 86400 seconds + in a day, the result is 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). + + Since QTime measures time within a day and there are 86400000 + milliseconds in a day, the result is between -86400000 and 86400000. + + \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, or FALSE if they are + different. +*/ + +/*! + \fn bool QTime::operator!=( const QTime &t ) const + + Returns TRUE if this time is different from \a t, or FALSE if they + are equal. +*/ + +/*! + \fn bool QTime::operator<( const QTime &t ) const + + Returns TRUE if this time is earlier than \a t, otherwise FALSE. +*/ + +/*! + \fn bool QTime::operator<=( const QTime &t ) const + + Returns TRUE if this time is earlier than or equal to \a t, + otherwise FALSE. +*/ + +/*! + \fn bool QTime::operator>( const QTime &t ) const + + Returns TRUE if this time is later than \a t, otherwise FALSE. +*/ + +/*! + \fn bool QTime::operator>=( const QTime &t ) const + + Returns TRUE if this time is later than or equal to \a t, otherwise + FALSE. +*/ + + + +/*! + 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() +{ + QTime ct; + currentTime( &ct ); + return ct; +} + +/*! + \internal + + 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 ) +{ + if ( !ct ) { +#if defined(CHECK_NULL) + qWarning( "QTime::currentTime(QTime *): Null pointer not allowed" ); +#endif + return FALSE; + } + +#if defined(_OS_WIN32_) + + SYSTEMTIME t; + GetLocalTime( &t ); + ct->ds = MSECS_PER_HOUR*t.wHour + MSECS_PER_MIN*t.wMinute + + 1000*t.wSecond + t.wMilliseconds; + return (t.wHour == 0 && t.wMinute == 0); + +#elif defined(_OS_OS2_) + + DATETIME t; + DosGetDateTime( &t ); + ct->ds = MSECS_PER_HOUR*t.hours + MSECS_PER_MIN*t.minutes + + 1000*t.seconds + 10*t.hundredths; + return (t.hours == 0 && t.minutes == 0); + +#elif defined(_OS_MSDOS_) + + _dostime_t t; + _dos_gettime( &t ); + ct->ds = MSECS_PER_HOUR*t.hour + MSECS_PER_MIN*t.minute + + t.second*1000 + t.hsecond*10; + return (t.hour== 0 && t.minute == 0); + +#elif defined(_OS_UNIX_) + + struct timeval tv; + gettimeofday( &tv, 0 ); + time_t ltime = tv.tv_sec; + tm *t = localtime( <ime ); + ct->ds = (uint)( MSECS_PER_HOUR*t->tm_hour + MSECS_PER_MIN*t->tm_min + + 1000*t->tm_sec + tv.tv_usec/1000 ); + return (t->tm_hour== 0 && t->tm_min == 0); + +#else + + time_t ltime; // no millisecond resolution!! + ::time( <ime ); + tm *t = localtime( <ime ); + ct->ds = MSECS_PER_HOUR*t->tm_hour + MSECS_PER_MIN*t->tm_min + + 1000*t->tm_sec; + return (t->tm_hour== 0 && t->tm_min == 0); +#endif +} + +/*! + Returns TRUE if the specified time is valid, otherwise 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 # 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, + 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 e.g. when daylight saving 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 e.g. when daylight saving is turned on or off. + + \sa start(), restart() +*/ + +int QTime::elapsed() +{ + int n = msecsTo( currentTime() ); + if ( n < 0 ) // passed midnight + n += 86400*1000; + return n; +} + + +/***************************************************************************** + QDateTime member functions + *****************************************************************************/ + +/*! + \class QDateTime qdatetime.h + \brief The QDateTime class provides date and time functions. + + \ingroup time + + 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 or days. + + A QDateTime object is typically created either by giving a date and + time explicitly, or by using the static function currentTime(), + which makes a QDateTime object which contains the system's clock + time. + + 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. A datetime is considered smaller than another if it is + earlier than the other. + + The datetime a given number of days or seconds later than a given + datetime can be found using the addDays() and addSecs() + functions. Correspondingly, the number of days or seconds between + two times can be found using the daysTo() or secsTo() functions. + + 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 limitations regarding range and resolution mentioned in the + QDate and QTime documentation apply for QDateTime also. + + \sa QDate, QTime +*/ + + +/*! + \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 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. A null date is invalid. + + \sa QDate::isNull(), QTime::isNull() +*/ + +/*! + \fn bool QDateTime::isValid() const + + Returns TRUE if both the date and the time are valid. + + \sa QDate::isValid(), QTime::isValid() +*/ + +/*! + \fn QDate QDateTime::date() const + + Returns the date part of this datetime. + + \sa setDate(), time() +*/ + +/*! + \fn QTime QDateTime::time() const + + Returns the time part of this datetime. + + \sa setTime(), date() +*/ + +/*! + \fn void QDateTime::setDate( const QDate &date ) + + Sets the date part of this datetime. + + \sa date(), setTime() +*/ + +/*! + \fn void QDateTime::setTime( const QTime &time ) + + Sets the time part of this datetime. + + \sa time(), setDate() +*/ + + +/*! + Sets the local date and time given the number of seconds that have passed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + On systems that do not support timezones this function will behave as if + local time were UTC. + + Note that Microsoft Windows supports only a limited range of values for + \a secsSince1Jan1970UTC. +*/ + +void QDateTime::setTime_t( uint secsSince1Jan1970UTC ) +{ + time_t tmp = (time_t) secsSince1Jan1970UTC; + tm *tM = localtime( &tmp ); + if ( !tM ) { + tM = gmtime( &tmp ); + if ( !tM ) { + d.jd = QDate::greg2jul( 1970, 1, 1 ); + t.ds = 0; + return; + } + } + d.jd = QDate::greg2jul( tM->tm_year + 1900, tM->tm_mon + 1, tM->tm_mday ); + t.ds = MSECS_PER_HOUR*tM->tm_hour + MSECS_PER_MIN*tM->tm_min + + 1000*tM->tm_sec; +} + + +/*! + Returns the datetime as a string. + + The string format is "Sat May 20 03:40:13 1998". + + This function uses QDate::dayName(), QDate::monthName(), and + QTime::toString() to generate the string. + +*/ + +QString QDateTime::toString() const +{ + QString buf = d.dayName(d.dayOfWeek()); + buf += ' '; + buf += d.monthName(d.month()); + buf += ' '; + buf += QString().setNum(d.day()); + buf += ' '; + buf += t.toString(); + buf += ' '; + buf += QString().setNum(d.year()); + return buf; +} + +/*! + 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(), addSecs() +*/ + +QDateTime QDateTime::addDays( int ndays ) const +{ + return QDateTime( d.addDays(ndays), 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() +*/ + +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 x( QDate(dt.year(),12,24), QTime(17,00) ); + qDebug( "There are %d seconds to Christmas", dt.secsTo(x) ); + \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, or FALSE if + they are different. + \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, or FALSE if + they are equal. + \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 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 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 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 FALSE. +*/ + +bool QDateTime::operator>=( const QDateTime &dt ) const +{ + if ( d > dt.d ) + return TRUE; + return d == dt.d ? t >= dt.t : FALSE; +} + +/*! + Returns the current datetime, as reported by the system clock. + + \sa QDate::currentDate(), QTime::currentTime() +*/ + +QDateTime QDateTime::currentDateTime() +{ + QDate cd = QDate::currentDate(); + QTime ct; + if ( QTime::currentTime(&ct) ) // too close to midnight? + cd = QDate::currentDate(); // YES! time for some midnight + // voodoo, fetch date again + return QDateTime( cd, ct ); +} + + +/***************************************************************************** + Date/time stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +/*! + \relates QDate + Writes the date to the stream. + + \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. + + \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 a time to the stream. + + \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. + + \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 a datetime to the stream. + + \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. + + \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/qtools/qdatetime.h b/qtools/qdatetime.h new file mode 100644 index 0000000..2479dbf --- /dev/null +++ b/qtools/qdatetime.h @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** +** 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" +#endif // QT_H + + +/***************************************************************************** + QDate class + *****************************************************************************/ + +class Q_EXPORT QDate +{ +public: + QDate() { jd=0; } // set null date + QDate( int y, int m, int d ); // set date + + bool isNull() const { return jd == 0; } + bool isValid() const; // valid date + + int year() const; // 1752.. + int month() const; // 1..12 + int day() const; // 1..31 + int dayOfWeek() const; // 1..7 (monday==1) + int dayOfYear() const; // 1..365 + int daysInMonth() const; // 28..31 + int daysInYear() const; // 365 or 366 + + virtual QString monthName( int month ) const; + virtual QString dayName( int weekday ) const; + + QString toString() const; + + bool setYMD( int y, int m, int d ); + + QDate addDays( int days ) 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 bool isValid( int y, int m, int d ); + static bool leapYear( int year ); + +protected: + static uint greg2jul( int y, int m, int d ); + static void jul2greg( uint jd, int &y, int &m, int &d ); +private: + static const char * const monthNames[]; + static const char * const weekdayNames[]; + 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 + + QString toString() const; + + 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 bool isValid( int h, int m, int s, int ms=0 ); + + void start(); + int restart(); + int elapsed(); + +private: + static bool currentTime( QTime * ); + + 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; } + void setDate( const QDate &date ) { d=date; } + void setTime( const QTime &time ) { t=time; } + void setTime_t( uint secsSince1Jan1970UTC ); + + QString toString() const; + + QDateTime addDays( int days ) 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(); + +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/qtools/qdict.h b/qtools/qdict.h new file mode 100644 index 0000000..3b70336 --- /dev/null +++ b/qtools/qdict.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** +** 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 Q_EXPORT QDict : public QGDict +{ +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(); } +private: + void deleteItem( Item d ); +}; + +#if defined(Q_DELETING_VOID_UNDEFINED) +template<> inline void QDict<void>::deleteItem( Item ) +{ +} +#endif + +template<class type> inline void QDict<type>::deleteItem( QCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + + +template<class type> class Q_EXPORT 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 *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/qtools/qdir.cpp b/qtools/qdir.cpp new file mode 100644 index 0000000..c4b4987 --- /dev/null +++ b/qtools/qdir.cpp @@ -0,0 +1,1207 @@ +/**************************************************************************** +** +** +** Implementation of QDir class +** +** Created : 950427 +** +** 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" + +#include "qdir.h" + +#ifndef QT_NO_DIR +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qregexp.h" +#include "qstringlist.h" +#include <stdlib.h> +#include <ctype.h> + +// NOT REVISED +/*! + \class QDir qdir.h + \brief Traverses directory structures and contents in a + platform-independent way. + + \ingroup io + + A QDir can point to a file using either a relative or an absolute file + path. Absolute file paths begin with the directory separator ('/') or a + drive specification (not applicable to UNIX). 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". You can use the function isRelative() + to check if a QDir is using a relative or an absolute file path. You can + call the function convertToAbs() to convert a relative QDir to an + absolute one. + + The directory "example" under the current directory is checked for existence + in the example below: + + \code + QDir d( "example" ); // "./example" + if ( !d.exists() ) + qWarning( "Cannot find the example directory" ); + \endcode + + If you always use '/' as a directory separator, Qt will translate your + paths to conform to the underlying operating system. + + cd() and cdUp() can be used to navigate the directory tree. Note that the + logical cd and cdUp operations are not performed if the new directory does + not exist. + + Example: + \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 + + To read the contents of a directory you can use the entryList() and + entryInfoList() functions. + + Example: + \code + #include <stdio.h> + #include <qdir.h> + + // + // This program scans the current directory and lists all files + // that are not symbolic links, sorted by size with the smallest files + // first. + // + + 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 ); // create list iterator + QFileInfo *fi; // pointer for traversing + + printf( " BYTES FILENAME\n" ); // print header + while ( (fi=it.current()) ) { // for each file... + printf( "%10li %s\n", fi->size(), fi->fileName().data() ); + ++it; // goto next list element + } + } + \endcode +*/ + + +/*! + Constructs a QDir pointing to the current directory. + \sa currentDirPath() +*/ + +QDir::QDir() +{ + dPath = QString::fromLatin1("."); + init(); +} + +/*! + Constructs a QDir. + + \arg \e path is the directory. + \arg \e nameFilter is the file name filter. + \arg \e sortSpec is the sort specification, which describes how to + sort the files in the directory. + \arg \e filterSpec is the filter specification, which describes how + to filter the files in the directory. + + Most of these arguments (except \e path) have optional values. + + Example: + \code + // lists all files in /tmp + + QDir d( "/tmp" ); + for ( int i=0; i<d.count(); i++ ) + printf( "%s\n", d[i] ); + \endcode + + If \e path is "" or null, the directory is set to "." (the current + directory). If \e nameFilter is "" or null, it is set to "*" (all + files). + + No check is made to ensure that the directory exists. + + \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 given directory. + \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); +} + +/*! + Destructs the QDir and cleans up. +*/ + +QDir::~QDir() +{ + if ( fList ) + delete fList; + if ( fiList ) + delete fiList; +} + + +/*! + Sets the path of the directory. The path is cleaned of redundant ".", ".." + and 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 ('/') or a drive specification (not + applicable to UNIX). + 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". You can use the function isRelative() to check if a QDir + is using a relative or an absolute file path. You can call the function + convertToAbs() to convert a relative QDir to an absolute one. + + \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 (a path that starts with '/') path, 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 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. the root directory) a null string 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 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 \e fileName will not be removed (see + cleanDirPath()). + + If \e acceptAbsPath is TRUE a \e fileName starting with a separator + ('/') will be returned without change. + If \e acceptAbsPath is FALSE an absolute path will be appended to + the directory path. + + \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 NOT check if + the file actually exists in the directory. Redundant multiple separators + or "." and ".." directories in \e fileName will NOT be removed (see + cleanDirPath()). + + If \e acceptAbsPath is TRUE a \e fileName starting with a separator + ('/') will be returned without change. + if \e acceptAbsPath is FALSE an absolute path will be appended to + the directory path. + + \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; +} + + +/*! + Converts the '/' separators in \a pathName to system native + separators. Returns the translated string. + + On Windows, convertSeparators("c:/winnt/system32") returns + "c:\winnt\system32". + + No conversion is done on UNIX. +*/ + +QString QDir::convertSeparators( const QString &pathName ) +{ + QString n( pathName ); +#if defined(_OS_FATFS_) || defined(_OS_OS2EMX_) + for ( int i=0; i<(int)n.length(); i++ ) { + if ( n[i] == '/' ) + n[i] = '\\'; + } +#endif + return n; +} + + +/*! + Changes directory by descending into the given directory. Returns + TRUE if the new directory exists and is readable. Note that the logical + cd operation is NOT performed if the new directory does not exist. + + If \e acceptAbsPath is TRUE a path starting with a separator ('/') + will cd to the absolute directory, if \e acceptAbsPath is FALSE + any number of separators at the beginning of \e dirName will be removed. + + Example: + \code + QDir d = QDir::home(); // now points to home directory + if ( !d.cd("c++") ) { // now points to "c++" under home directory if OK + QFileInfo fi( d, "c++" ); + if ( fi.exists() ) { + if ( fi.isDir() ) + qWarning( "Cannot cd into \"%s\".", (char*)d.absFilePath("c++") ); + else + qWarning( "Cannot create directory \"%s\"\n" + "A file named \"c++\" already exists in \"%s\"", + (const char *)d.absFilePath("c++"), + (const char *)d.path() ); + return; + } else { + qWarning( "Creating directory \"%s\"", + (const char *) d.absFilePath("c++") ); + if ( !d.mkdir( "c++" ) ) { + qWarning("Could not create directory \"%s\"", + (const char *)d.absFilePath("c++") ); + return; + } + } + } + \endcode + + 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 += '/'; + 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 the path followed to arrive + at the current directory. + + Returns TRUE if the new directory exists and is readable. 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() + \sa setNameFilter() +*/ + +/*! + Sets the name filter used by entryList() and entryInfoList(). + + The name filter is a wildcarding filter that understands "*" and "?" + wildcards, You may specify several filter entries separated by a " " or a ";". If + you want entryList() and entryInfoList() to list all files ending with + ".cpp" and all files ending with ".h", you simply call + dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h") + + \sa nameFilter() +*/ + +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() + \sa setFilter() +*/ + +/*! \enum QDir::FilterSpec + + This enum describes how QDir is to select what entries in a + directory to return. The filter value is specified by or-ing + together values from the following list: <ul> + + <li> \c Dirs - List directories only + <li> \c Files - List files only + + <li> \c Drives - List disk drives (does nothing under unix) + <li> \c NoSymLinks - Do not list symbolic links (where they exist) + <li> \c Readable - List files for which the application has read access. + <li> \c Writable - List files for which the application has write access. + <li> \c Executable - List files for which the application has execute access + <li> \c Modified - Only list files that have been modified (does nothing + under unix) + <li> \c Hidden - List hidden files (on unix, files starting with a .) + <li> \c System - List system files (does nothing under unix) + </ul> + + 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(). The filter is used + to specify the kind of files that should be returned by entryList() and + entryInfoList(). + \sa nameFilter() +*/ + +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() +*/ + +/*! \enum QDir::SortSpec + + This enum describes how QDir is to sort entries in a directory when + it returns a list of them. The sort value is specified by or-ing + together values from the following list: <ul> + + <li> \c Name - sort by name + <li> \c Time - sort by time (modification time) + <li> \c Size - sort by file size + <li> \c Unsorted - do not sort + + <li> \c DirsFirst - put all directories first in the list + <li> \c Reversed - reverse the sort order + <li> \c IgnoreCase - sort case-insensitively + + </ul> + + You can only specify one of the first four. If you specify both \c + DirsFirst and \c Reversed, directories are still put first but the + list is otherwise reversed. +*/ + +// ### Unsorted+DirsFirst ? Unsorted+Reversed? + +/*! + Sets the sorting order used by entryList() and entryInfoList(). + + The \e sortSpec is specified by or-ing values from the enum + SortSpec. The different values are: + + One of these: + <dl compact> + <dt>Name<dd> Sort by name (alphabetical order). + <dt>Time<dd> Sort by time (most recent first). + <dt>Size<dd> Sort by size (largest first). + <dt>Unsorted<dd> Use the operating system order (UNIX does NOT sort + alphabetically). + + ORed with zero or more of these: + + <dt>DirsFirst<dd> Always put directory names first. + <dt>Reversed<dd> Reverse sort order. + <dt>IgnoreCase<dd> Ignore case when sorting by name. + </dl> +*/ + +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 \e enable is TRUE, all directories will be listed (even if they do not + match the filter or the name filter), otherwise only matched directories + will be listed. + + \bug Currently, directories that do not match the filter will not be + included (the name filter will be ignored as expected). + + \sa matchAllDirs() +*/ + +void QDir::setMatchAllDirs( bool enable ) +{ + if ( (bool)allDirs == enable ) + return; + allDirs = enable; + dirty = TRUE; +} + + +/*! + Returns the number of files that was found. + Equivalent to entryList().count(). + \sa operator[](), entryList() +*/ + +uint QDir::count() const +{ + return entryList().count(); +} + +/*! + Returns the file name at position \e index in the list of found file + names. + Equivalent to entryList().at(index). + + Returns null if the \e 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; +} + + +/*! + 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; +} + +/*! + 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; +} + + + +/*! + Returns a list of the names of all files and directories in the directory + indicated by the setSorting(), setFilter() and setNameFilter() + specifications. + + The the filter and sorting specifications can be overridden using the + \e filterSpec and \e sortSpec arguments. + + Returns an empty list if the directory is unreadable or does not exist. + + \sa entryInfoList(), setNameFilter(), setSorting(), setFilter(), + encodedEntryList() +*/ + +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 files and directories in the directory + indicated by the setSorting(), setFilter() and setNameFilter() + specifications. + + The the filter and sorting specifications can be overridden using the + \e nameFilter, \e filterSpec and \e sortSpec arguments. + + Returns and empty list if the directory is unreadable or does not exist. + + \sa entryInfoList(), setNameFilter(), setSorting(), setFilter(), + encodedEntryList() +*/ + +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) ) + return *that->fList; + else + return QStringList(); +} + +/*! + Returns a list of QFileInfo objects for all files and directories in + the directory pointed to using the setSorting(), setFilter() and + setNameFilter() specifications. + + The the filter and sorting specifications can be overridden using the + \e filterSpec and \e 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 will + need to 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 files and directories in + the directory pointed to using the setSorting(), setFilter() and + setNameFilter() specifications. + + The the filter and sorting specifications can be overridden using the + \e nameFilter, \e filterSpec and \e 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 will + need to 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; +} + +/*! + Returns TRUE if the directory exists. (If a file with the same + name is found this function will of course 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, + FALSE if the path is absolute (e.g. under UNIX a path is relative if it + does not start with a '/'). + + According to Einstein this function should always return TRUE. + + \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 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; +} + +/*! + Sets the directory path to be the given 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 the \e d and this dir have different path or + different sort/filter settings, otherwise FALSE. +*/ + +/*! + Returns TRUE if the \e d and this dir have the same path and all sort + and filter settings are equal, otherwise FALSE. +*/ + +bool QDir::operator==( const QDir &d ) const +{ + return dPath == d.dPath && + nameFilt == d.nameFilt && + allDirs == d.allDirs && + filtS == d.filtS && + sortS == d.sortS; +} + + +/*! + Removes a file. + + If \e acceptAbsPath is TRUE a path starting with a separator ('/') + will remove the file with the absolute path, if \e acceptAbsPath is FALSE + any number of separators at the beginning of \e fileName will be removed. + + Returns TRUE if successful, otherwise FALSE. +*/ + +bool QDir::remove( const QString &fileName, bool acceptAbsPath ) +{ + if ( fileName.isEmpty() ) { +#if defined(CHECK_NULL) + qWarning( "QDir::remove: Empty or null file name" ); +#endif + return FALSE; + } + QString p = filePath( fileName, acceptAbsPath ); + return QFile::remove( p ); +} + +/*! + Checks for existence of a file. + + If \e acceptAbsPaths is TRUE a path starting with a separator ('/') + will check the file with the absolute path, if \e acceptAbsPath is FALSE + any number of separators at the beginning of \e name will be removed. + + Returns TRUE if the file exists, otherwise FALSE. + + \sa QFileInfo::exists(), QFile::exists() +*/ + +bool QDir::exists( const QString &name, bool acceptAbsPath ) +{ + if ( name.isEmpty() ) { +#if defined(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 and '\' under + MS-DOS, Windows NT and OS/2. + + 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(_OS_UNIX_) + return '/'; +#elif defined (_OS_FATFS_) + return '\\'; +#elif defined (_OS_MAC_) + return ':'; +#else + return '/'; +#endif +} + +/*! + Returns the current directory. + \sa currentDirPath(), QDir::QDir() +*/ + +QDir QDir::current() +{ + return QDir( currentDirPath() ); +} + +/*! + Returns the home directory. + \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 for the user's home directory, + \sa home() +*/ + +QStringList qt_makeFilterList( const QString &filter ) +{ + if ( filter.isEmpty() ) + return QStringList(); + + int i = filter.find( ' ', 0 ); + QChar sep( ' ' ); + if ( i == -1 ) { + if ( filter.find( ';', 0 ) != -1 ) { + sep = QChar( ';' ); + i = filter.find( sep, 0 ); + } + } + + QStringList lst = QStringList::split( sep, filter ); + QStringList lst2; + QStringList::Iterator it = lst.begin(); + + for ( ; it != lst.end(); ++it ) { + QString s = *it; + if ( s[ (int)s.length() - 1 ] == ';' ) + s.remove( s.length() - 1, 1 ); + lst2 << s; + } + return lst2; +} + +/*! + Returns TRUE if the \e fileName matches one of the wildcards in the list \e filters. + \sa QRegExp +*/ + +bool QDir::match( const QStringList &filters, const QString &fileName ) +{ + QStringList::ConstIterator sit = filters.begin(); + bool matched = FALSE; + for ( ; sit != filters.end(); ++sit ) { + QRegExp regexp( *sit, FALSE, TRUE ); + if ( regexp.match( fileName ) != -1 ) { + matched = TRUE; + break; + } + } + + return matched; +} + +/*! + Returns TRUE if the \e fileName matches the wildcard \e filter. + \a Filter may also contain multiple wildcards separated by spaces or + semicolons. + \sa QRegExp +*/ + +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 "." or ".." found in the path. + + Symbolic links are kept. This function does not return the + canonical path, but rather the most simplified version of the input. + "../stuff" becomes "stuff", "stuff/../nonsense" becomes "nonsense" + and "\\stuff\\more\\..\\nonsense" becomes "\\stuff\\nonsense". + + \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(_OS_FATFS_) || defined(_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 + +int qt_cmp_si( const void *n1, const void *n2 ) +{ + 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/qtools/qdir.h b/qtools/qdir.h new file mode 100644 index 0000000..dd74271 --- /dev/null +++ b/qtools/qdir.h @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** +** Definition of QDir class +** +** Created : 950427 +** +** 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 QDIR_H +#define QDIR_H + +#ifndef QT_H +#include "qstrlist.h" +#include "qfileinfo.h" +#endif // QT_H + +#ifndef QT_NO_DIR +typedef QList<QFileInfo> QFileInfoList; +typedef QListIterator<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: + 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/qtools/qdir_unix.cpp b/qtools/qdir_unix.cpp new file mode 100644 index 0000000..3b12de9 --- /dev/null +++ b/qtools/qdir_unix.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** +** Implementation of QDirclass +** +** Created : 950628 +** +** 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 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 "qglobal.h" + +#include "qdir.h" +#ifndef QT_NO_DIR + +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qregexp.h" +#include "qstringlist.h" +#include <stdlib.h> +#include <ctype.h> + +extern QStringList qt_makeFilterList( const QString &filter ); + +extern int qt_cmp_si_sortSpec; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +extern int qt_cmp_si( const void *, const void * ); + +#if defined(Q_C_CALLBACKS) +} +#endif + + +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]; + char tmp[PATH_MAX]; + GETCWD( cur, PATH_MAX ); + if ( CHDIR(QFile::encodeName(dPath)) >= 0 ) { + GETCWD( tmp, PATH_MAX ); + r = QFile::decodeName(tmp); + } + CHDIR( cur ); + + slashify( r ); + return r; +} + +bool QDir::mkdir( const QString &dirName, bool acceptAbsPath ) const +{ + return MKDIR( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ) + == 0; +} + +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(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; + + STATBUF st; + if ( STAT( ".", &st ) == 0 ) { + char currentName[PATH_MAX]; + if ( GETCWD( currentName, PATH_MAX ) != 0 ) + result = QFile::decodeName(currentName); +#if defined(DEBUG) + if ( result.isNull() ) + qWarning( "QDir::currentDirPath: getcwd() failed" ); +#endif + } else { +#if defined(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; + CHECK_PTR( fList ); + fiList = new QFileInfoList; + 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; + +#if defined(_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 ) { +#if defined(CHECK_NULL) + qWarning( "QDir::readDirEntries: Cannot read the directory: %s", + QFile::encodeName(dPath).data() ); +#endif + return FALSE; + } + + 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()) ) { + 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(CHECK_NULL) + qWarning( "QDir::readDirEntries: Cannot close the directory: %s", + dPath.local8Bit().data() ); +#endif + } + + // Sort... + 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 ) { + 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/qtools/qdir_win32.cpp b/qtools/qdir_win32.cpp new file mode 100644 index 0000000..70c3563 --- /dev/null +++ b/qtools/qdir_win32.cpp @@ -0,0 +1,406 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + * Based on qdir_unix.cpp + * + * Copyright (C) 1992-2000 Trolltech AS. + */ + + +#include "qglobal.h" + +#include "qdir.h" +#ifndef QT_NO_DIR + + +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qregexp.h" +#include "qstringlist.h" +#include <stdlib.h> +#include <ctype.h> +#if defined(_OS_WIN32_) +#if defined(_CC_BOOL_DEF_) +#undef bool +#include <windows.h> +#define bool int +#else +#include <windows.h> +#endif +#endif +#if defined(_OS_OS2EMX_) +extern Q_UINT32 DosQueryCurrentDisk(Q_UINT32*,Q_UINT32*); +#define NO_ERROR 0 +#endif + +extern QStringList qt_makeFilterList( const QString &filter ); + +extern int qt_cmp_si_sortSpec; + +#if defined(Q_C_CALLBACKS) +extern "C" { +#endif + +extern int qt_cmp_si( const void *, const void * ); + +#if defined(Q_C_CALLBACKS) +} +#endif + + +void QDir::slashify( QString& n ) +{ + for ( int i=0; i<(int)n.length(); i++ ) + { + if ( n[i] == '\\' ) + n[i] = '/'; + } +} + +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]; + char tmp[PATH_MAX]; + GETCWD( cur, PATH_MAX ); + if ( CHDIR(QFile::encodeName(dPath)) >= 0 ) { + 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(__CYGWIN32_) + return MKDIR( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ) + == 0; +#else + return MKDIR( QFile::encodeName(filePath(dirName,acceptAbsPath)) ) == 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 ) == 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(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; + + STATBUF st; + if ( STAT( ".", &st ) == 0 ) { + char currentName[PATH_MAX]; + if ( GETCWD( currentName, PATH_MAX ) != 0 ) + result = QFile::decodeName(currentName); +#if defined(DEBUG) + if ( result.isNull() ) + qWarning( "QDir::currentDirPath: getcwd() failed" ); +#endif + } else { +#if defined(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; + int i = 0; + if ( isalpha(path[0]) && path[1] == ':' ) // drive, e.g. a: + i = 2; + return path[i] != '/' && path[i] != '\\'; +} + +#undef IS_SUBDIR +#undef IS_RDONLY +#undef IS_ARCH +#undef IS_HIDDEN +#undef IS_SYSTEM +#undef FF_GETFIRST +#undef FF_GETNEXT +#undef FF_ERROR + +#if defined(_OS_WIN32_) +#define IS_SUBDIR FILE_ATTRIBUTE_DIRECTORY +#define IS_RDONLY FILE_ATTRIBUTE_READONLY +#define IS_ARCH FILE_ATTRIBUTE_ARCHIVE +#define IS_HIDDEN FILE_ATTRIBUTE_HIDDEN +#define IS_SYSTEM FILE_ATTRIBUTE_SYSTEM +#define FF_GETFIRST FindFirstFile +#define FF_GETNEXT FindNextFile +#define FF_ERROR INVALID_HANDLE_VALUE +#else +#define IS_SUBDIR _A_SUBDIR +#define IS_RDONLY _A_RDONLY +#define IS_ARCH _A_ARCH +#define IS_HIDDEN _A_HIDDEN +#define IS_SYSTEM _A_SYSTEM +#define FF_GETFIRST _findfirst +#define FF_GETNEXT _findnext +#define FF_ERROR -1 +#endif + + +bool QDir::readDirEntries( const QString &nameFilter, + int filterSpec, int sortSpec ) +{ + int i; + if ( !fList ) { + fList = new QStringList; + CHECK_PTR( fList ); + fiList = new QFileInfoList; + 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; + // show hidden files if the user asks explicitly for e.g. .* + if ( !doHidden && !nameFilter.isEmpty() && nameFilter[0] == '.' ) + doHidden = TRUE; + bool doModified = (filterSpec & Modified) != 0; + bool doSystem = (filterSpec & System) != 0; + + QRegExp wc( nameFilter, FALSE, TRUE ); // wild card, case insensitive + bool first = TRUE; + QString p = dPath.copy(); + int plen = p.length(); +#if defined(_OS_WIN32_) + HANDLE ff; + WIN32_FIND_DATA finfo; +#else + long ff; + _finddata_t finfo; +#endif + QFileInfo fi; + if ( plen == 0 ) + { +#if defined(CHECK_NULL) + warning( "QDir::readDirEntries: No directory name specified" ); +#endif + return FALSE; + } + if ( p.at(plen-1) != '/' && p.at(plen-1) != '\\' ) + p += '/'; + p += "*.*"; + + ff = FF_GETFIRST( p.data(), &finfo ); + if ( ff == FF_ERROR ) + { +#if defined(DEBUG) + warning( "QDir::readDirEntries: Cannot read the directory: %s", + (const char *)dPath ); +#endif + return FALSE; + } + + while ( TRUE ) + { + if ( first ) + first = FALSE; + else + { +#if defined(_OS_WIN32_) + if ( !FF_GETNEXT(ff,&finfo) ) + break; +#else + if ( FF_GETNEXT(ff,&finfo) == -1 ) + break; +#endif + } +#if defined(_OS_WIN32_) + int attrib = finfo.dwFileAttributes; +#else + int attrib = finfo.attrib; +#endif + bool isDir = (attrib & IS_SUBDIR) != 0; + bool isFile = !isDir; + bool isSymLink = FALSE; + bool isReadable = TRUE; + bool isWritable = (attrib & IS_RDONLY) == 0; + bool isExecable = FALSE; + bool isModified = (attrib & IS_ARCH) != 0; + bool isHidden = (attrib & IS_HIDDEN) != 0; + bool isSystem = (attrib & IS_SYSTEM) != 0; + +#if defined(_OS_WIN32_) + const char *fname = finfo.cFileName; +#else + const char *fname = finfo.name; +#endif + if ( wc.match(fname) == -1 && !(allDirs && isDir) ) + continue; + + QString name = fname; + if ( doExecable ) + { + QString ext = name.right(4).lower(); + if ( ext == ".exe" || ext == ".com" || ext == ".bat" || + ext == ".pif" || ext == ".cmd" ) + isExecable = TRUE; + } + + if ( (doDirs && isDir) || (doFiles && isFile) ) + { + if ( noSymLinks && isSymLink ) + continue; + if ( (filterSpec & RWEMask) != 0 ) + if ( (doReadable && !isReadable) || + (doWritable && !isWritable) || + (doExecable && !isExecable) ) + continue; + if ( doModified && !isModified ) + continue; + if ( !doHidden && isHidden ) + continue; + if ( !doSystem && isSystem ) + continue; + fi.setFile( *this, name ); + fiList->append( new QFileInfo( fi ) ); + } + } +#if defined(_OS_WIN32_) + FindClose( ff ); +#else + _findclose( ff ); +#endif + + // Sort... + 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 ) { + knownMemoryLeak = new QFileInfoList; + +#if defined(_OS_WIN32_) + Q_UINT32 driveBits = (Q_UINT32) GetLogicalDrives() & 0x3ffffff; +#elif defined(_OS_OS2EMX_) + Q_UINT32 driveBits, cur; + if (DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR) + exit(1); + driveBits &= 0x3ffffff; +#endif + char driveName[4]; + qstrcpy( driveName, "a:/" ); + while( driveBits ) { + if ( driveBits & 1 ) + knownMemoryLeak->append( new QFileInfo( driveName ) ); + driveName[0]++; + driveBits = driveBits >> 1; + } + } + + return knownMemoryLeak; +} +#endif //QT_NO_DIR diff --git a/qtools/qfeatures.h b/qtools/qfeatures.h new file mode 100644 index 0000000..5f6f663 --- /dev/null +++ b/qtools/qfeatures.h @@ -0,0 +1,671 @@ +/**************************************************************************** +** +** +** Global feature selection +** +** Created : 000417 +** +** 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 QFEATURES_H +#define QFEATURES_H + +/*! \page features....html + ... +*/ + +#include <qconfig.h> + + +// Data structures +/*! + QStringList +*/ +//#define QT_NO_STRINGLIST + +// File I/O +#if defined(QT_NO_STRINGLIST) + /*! + QDir + */ +# define QT_NO_DIR +#endif + +/*! + QTextStream +*/ +//#define QT_NO_TEXTSTREAM +/*! + QDataStream +*/ +//#define QT_NO_DATASTREAM + +// Images +/*! + BMP image I/O + <p>The Windows Bitmap (BMP) image format is common on MS-Windows. + <p>This is an uncompressed image format + offering few advantages over PNG or JPEG. +*/ +#if defined(QT_NO_DATASTREAM) +# define QT_NO_IMAGEIO_BMP +#endif +/*! + PPM image I/O + <p>The Portable PixMap (PPM) image format is common on Unix. + <p>This is an uncompressed image format + offering few advantages over PNG or JPEG. +*/ +//#define QT_NO_IMAGEIO_PPM +/*! + XBM image I/O + <p>The X11 BitMap (XBM) image format is common on X11. + <p>This is an uncompressed monochrome image format. + Qt uses this format for some internal images (eg. mouse cursors). +*/ +//#define QT_NO_IMAGEIO_XBM +/*! + XPM image I/O + <p>The X11 PixMap (XPM) image format is common on X11. + <p>This is an uncompressed image format. + XPM images have the small advantage that they can be trivially + included in source files as they are C code. + Qt uses this format for some internal images (eg. QMessageBox icons). +*/ +#if defined(QT_NO_TEXTSTREAM) +# define QT_NO_IMAGEIO_XPM +#endif +/*! + PNG image I/O + <p>The Portable Network Graphics (PNG) is a compressed image format. + <p>See <a href=http://www.libpng.org/pub/png/>The PNG Home Site</a> for + details of the format. +*/ +//#define QT_NO_IMAGEIO_PNG +/*! + MNG image I/O + <p>The Multiple-image Network Graphics (MNG) is a compressed animation format. + <p>See <a href=http://www.libpng.org/pub/mng/>The MNG Home Site</a> for + details of the format. +*/ +//#define QT_NO_IMAGEIO_MNG +/*! + JPEG image I/O + <p>The Joint Photographic Experts Group (JPEG) is a compressed lossy image format that gives high compression + for real-world and photo-realistic images. +*/ +//#define QT_NO_IMAGEIO_JPEG + +/*! + Asynchronous I/O + <p>Allows push-driven data processing. +*/ +//#define QT_NO_ASYNC_IO +/*! + Asynchronous image I/O + <p>Allows push-driven images. +*/ +//#define QT_NO_ASYNC_IMAGE_IO +#if defined(QT_NO_ASYNC_IO) || defined(QT_NO_ASYNC_IMAGE_IO) + /*! + Animated images + <p>This includes animated GIFs. + <p><b>Note: this currently also requires <tt>QT_BUILTIN_GIF_READER</tt> to + be defined when building Qt.</b> + */ +# define QT_NO_MOVIE +#endif + +// Fonts +/*! + TrueType font files + <p>Scalable font format common on MS-Windows and becoming common on Unix. + <p>Only supported on Qt/Embedded. +*/ +//#define QT_NO_TRUETYPE +/*! + BDF font files + <p>The Bitmap Distribution Format (BDF) font file format, common + on Unix. + <p>Only supported on Qt/Embedded. +*/ +#if defined(QT_NO_TEXTSTREAM) || defined(QT_NO_STRINGLIST) +# define QT_NO_BDF +#endif +/*! + QFontDatabase +*/ +#if defined(QT_NO_STRINGLIST) +# define QT_NO_FONTDATABASE +#endif + +// Internationalization + +/*! + QObject::tr() +*/ +#if defined(QT_NO_DATASTREAM) +# define QT_NO_TRANSLATION +#endif + +/*! + QTextCodec class and subclasses +*/ +//#define QT_NO_TEXTCODEC + +#if defined(QT_NO_TEXTCODEC) + /*! + QTextCodec classes + <p>This includes some large conversion tables. + */ +# define QT_NO_CODECS +#endif +#if defined(QT_LITE_UNICODE) + /*! + Unicode property tables + <p>These include some large tables. + */ +# define QT_NO_UNICODETABLES +#endif + +// MIME-typed data +/*! + MIME +*/ +#if defined(QT_NO_DIR) +# define QT_NO_MIME +#endif +#if defined(QT_NO_MIME) || defined(QT_NO_TEXTSTREAM) + /*! + RichText (HTML) display + */ +# define QT_NO_RICHTEXT +#endif + +//XML + +#if defined(QT_NO_STRINGLIST) +# define QT_NO_XML +#endif + +/*! Document Object Model */ +#if defined(QT_NO_XML) ||defined(QT_NO_MIME) +# define QT_NO_DOM +#endif + +// Sound +/*! + QSound +*/ +//#define QT_NO_SOUND + +// Scripting +/*! + Properties +*/ +#if defined(QT_NO_STRINGLIST) +# define QT_NO_PROPERTIES +#endif + +// Qt/Embedded-specific +/*! + Visible cursor +*/ +//#define QT_NO_QWS_CURSOR +/*! + Alpha-blended cursor +*/ +//#define QT_NO_QWS_ALPHA_CURSOR +/*! + Mach64 acceleration +*/ +#define QT_NO_QWS_MACH64 +/*! + Voodoo3 acceleration +*/ +#define QT_NO_QWS_VOODOO3 +/*! + Matrox MGA acceleration (Millennium/Millennium II/Mystique/G200/G400) +*/ +#define QT_NO_QWS_MATROX +/*! + Virtual frame buffer +*/ +//#define QT_NO_QWS_VFB +/*! + Remote frame buffer (VNC) +*/ +#define QT_NO_QWS_VNC +/*! + 1-bit monochrome +*/ +//#define QT_NO_QWS_DEPTH_1 +/*! + 4-bit VGA + Not yet implemented +*/ +#define QT_NO_QWS_VGA_16 +/*! + 8-bit grayscale +*/ +#define QT_NO_QWS_DEPTH_8GRAYSCALE +/*! + 8-bit color +*/ +//#define QT_NO_QWS_DEPTH_8 +/*! + 15-bit color +*/ +#define QT_NO_QWS_DEPTH_15 +/*! + 16-bit color +*/ +//#define QT_NO_QWS_DEPTH_16 +/*! + 32-bit color +*/ +//#define QT_NO_QWS_DEPTH_32 + +/*! + Window manager +*/ +//#define QT_NO_QWS_MANAGER + +/*! + Saving of fonts +*/ +#define QT_NO_QWS_SAVEFONTS + +/*! + Favour code size over graphics speed + <p>Smaller, slower code will be used for drawing operations. + <p>Only supported on Qt/Embedded. +*/ +//#define QT_NO_QWS_GFX_SPEED + +/*! + Qt/Embedded window system properties. +*/ +//#define QT_NO_QWS_PROPERTIES + +#if defined(QT_NO_QWS_PROPERTIES) || defined(QT_NO_MIME) && !defined(_WS_QWS_) +/*! Cut and paste */ +# define QT_NO_CLIPBOARD +#endif + +#if defined(QT_NO_MIME) || defined(QT_NO_QWS_PROPERTIES) + /*! + Drag and drop + */ +# define QT_NO_DRAGANDDROP +#endif + +#if defined(QT_NO_CLIPBOARD) || defined(QT_NO_MIME) || defined(_WS_QWS_) + /*! + Cut and paste of complex data types (non-text) + Not yet implemented for QWS. + */ +# define QT_NO_MIMECLIPBOARD +#endif + + +/*! + Drawing utility functions +*/ +//#define QT_NO_DRAWUTIL +/*! + TrueColor QImage +*/ +//#define QT_NO_IMAGE_TRUECOLOR +/*! + Smooth QImage scaling +*/ +//#define QT_NO_IMAGE_SMOOTHSCALE +/*! + Image file text strings +*/ +#if defined(QT_NO_STRINGLIST) +# define QT_NO_IMAGE_TEXT +#endif + +#if defined(QT_NO_IMAGE_TRUECOLOR) + /*! + 16-bit QImage + */ +# define QT_NO_IMAGE_16_BIT +#endif +#if defined(QT_NO_QWS_CURSOR) && defined(_WS_QWS_) + /*! + Cursors + */ +# define QT_NO_CURSOR +#endif + + + +// Networking +/*! + DNS +*/ +//#define QT_NO_DNS +/*! + Network file access +*/ +#if defined(QT_NO_DIR) || defined(QT_NO_STRINGLIST) +# define QT_NO_NETWORKPROTOCOL +#endif +#if defined(QT_NO_NETWORKPROTOCOL) || defined(QT_NO_DNS) + /*! + FTP file access + */ +# define QT_NO_NETWORKPROTOCOL_FTP + /*! + HTTP file access + */ +# define QT_NO_NETWORKPROTOCOL_HTTP +#endif + +// Painting +/*! + Named colors +*/ +//#define QT_NO_COLORNAMES +/*! + Scaling and rotation +*/ +//#define QT_NO_TRANSFORMATIONS + +// Printing +/*! + Printing +*/ +#if defined(QT_NO_TEXTSTREAM) +# define QT_NO_PRINTER +#endif + +// Metafiles +/*! + QPicture +*/ +#if defined(QT_NO_DATASTREAM) +# define QT_NO_PICTURE +#endif + +// Layout +/*! + Automatic widget layout +*/ +//#define QT_NO_LAYOUT + +// Widgets +/*! + QStyle +*/ +//#define QT_NO_STYLE + + +#if defined QT_NO_IMAGE_SMOOTHSCALE +/*! + QIconSet +*/ +# define QT_NO_ICONSET +#endif +/*! + QDialog +*/ +//#define QT_NO_DIALOG +/*! + QSemiModal +*/ +//#define QT_NO_SEMIMODAL +/*! + QFrame +*/ +//#define QT_NO_FRAME + +#if defined(QT_NO_FRAME) ||defined(QT_NO_PALETTE) || defined(QT_NO_STYLE) ||defined(QT_NO_DRAWUTIL) + /*! + Basic widgets: QLAbel, QPushbutton, ... + */ +# define QT_NO_SIMPLEWIDGETS +#endif + +#if defined(QT_NO_SIMPLEWIDGETS) + /*! + QLabel + */ +# define QT_NO_LABEL + /*! + QPushButton (not implemented). + */ +# define QT_NO_PUSHBUTTON + /*! + QLineEdit (not implemented). + */ +# define QT_NO_LINEEDIT +#endif +#if defined(QT_NO_ICONSET) || defined(QT_NO_IMAGE_SMOOTHSCALE) || defined(QT_NO_SIMPLEWIDGETS) + /*! + Pre-defined complex widgets + */ +# define QT_NO_COMPLEXWIDGETS +#endif +#if defined(QT_NO_COMPLEXWIDGETS) || defined(QT_NO_RICHTEXT) + /*! + QTextView + */ +# define QT_NO_TEXTVIEW +#endif +#if defined(QT_NO_TEXTVIEW) + /*! + QTextBrowser + */ +# define QT_NO_TEXTBROWSER +#endif + +#if defined(QT_NO_STYLE) + /*! + Windows style + */ +# define QT_NO_STYLE_WINDOWS + /*! + Motif style + */ +# define QT_NO_STYLE_MOTIF +#endif + +#if defined(QT_NO_STYLE_MOTIF) +# define QT_NO_STYLE_MOTIFPLUS +#endif + + +#if defined(QT_NO_COMPLEXWIDGETS) || defined(QT_NO_STRINGLIST) + /*! + QListBox + */ +# define QT_NO_LISTBOX +#endif + +#if defined(QT_NO_COMPLEXWIDGETS) + /*! + QAccel + */ +# define QT_NO_ACCEL + + /*! + QSizeGrip + */ +# define QT_NO_SIZEGRIP + /*! + QHeader + */ +# define QT_NO_HEADER + /*! + QMenuBar + */ +# define QT_NO_MENUBAR + /*! + QCanvas + */ +# define QT_NO_CANVAS + /*! + QDial + */ +# define QT_NO_DIAL + /*! + QWorkSpace + */ +# define QT_NO_WORKSPACE + /*! + QLCDNumber + */ +# define QT_NO_LCDNUMBER + /*! + QAction + */ +# define QT_NO_ACTION + /*! + QTable + */ +# define QT_NO_TABLE +#endif +#if defined(QT_NO_LISTBOX) || defined(QT_NO_COMPLEXWIDGETS) + /*! + QComboBox + */ +# define QT_NO_COMBOBOX +#endif +#if defined(QT_NO_COMPLEXWIDGETS) + /*! + QIconView + */ +# define QT_NO_ICONVIEW +#endif +#if defined(QT_NO_HEADER) + /*! + QListView + */ +# define QT_NO_LISTVIEW +#endif +#if defined(QT_NO_COMPLEXWIDGETS) || defined(QT_NO_DIALOG) + /*! + Built-in dialogs + */ +# define QT_NO_DIALOGS +#endif + +#if defined(QT_NO_STYLE_WINDOWS) + /*! + Compact Windows style + */ +# define QT_NO_STYLE_COMPACT +#endif + +#if defined(QT_NO_STYLE_MOTIF) + /*! + CDE style + */ +# define QT_NO_STYLE_CDE + /*! + SGI style + */ +# define QT_NO_STYLE_SGI +#endif +#if defined(QT_NO_STYLE_WINDOWS) + /*! + Platinum style + */ +# define QT_NO_STYLE_PLATINUM +#endif + +#if defined(QT_NO_DIALOGS) + /*! + QColorDialog + */ +# define QT_NO_COLORDIALOG + /*! + QMessageBox + */ +# define QT_NO_MESSAGEBOX + /*! + QTabDialog + */ +# define QT_NO_TABDIALOG + /*! + QWizard + */ +# define QT_NO_WIZARD +#endif + +#if defined(QT_NO_DIALOGS) || defined(QT_NO_LISTVIEW) || defined(QT_NO_NETWORKPROTOCOL) || defined(QT_NO_COMBOBOX) || defined(QT_NO_DIR) || defined(QT_NO_MESSAGEBOX) + /*! + QFileDialog + */ +# define QT_NO_FILEDIALOG +#endif + +#if defined(QT_NO_DIALOGS) || defined(QT_NO_FONTDATABASE) || defined(QT_NO_COMBOBOX) + /*! + QFontDialog + */ +# define QT_NO_FONTDIALOG +#endif + +#if defined(QT_NO_DIALOGS) || defined(QT_NO_LISTVIEW) || defined(QT_NO_PRINTER) || defined(QT_NO_COMBOBOX) || defined(QT_NO_DIR) + /*! + QPrintDialog + */ +# define QT_NO_PRINTDIALOG +#endif + +#if defined(QT_NO_DIALOGS) || defined(QT_NO_SEMIMODAL) + /*! + QProgressDialog + */ +# define QT_NO_PROGRESSDIALOG +#endif +#if defined(QT_NO_DIALOGS) || defined(QT_NO_COMBOBOX) + /*! + QInputDialog + */ +# define QT_NO_INPUTDIALOG +#endif + +#if defined(QT_NO_STRINGLIST) + // Desktop features + /*! Session management support */ +# define QT_NO_SESSIONMANAGER +#endif + +/*! Special widget effects (fading, scrolling) */ +//#define QT_NO_EFFECTS + +#endif // QFEATURES_H diff --git a/qtools/qfile.cpp b/qtools/qfile.cpp new file mode 100644 index 0000000..2222b5b --- /dev/null +++ b/qtools/qfile.cpp @@ -0,0 +1,550 @@ +/**************************************************************************** +** +** +** Implementation of QFile 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. +** +**********************************************************************/ + +#include "qglobal.h" +#if defined(_OS_WIN32_) +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#endif +#endif + +#include "qfile.h" +#include "qfiledefs_p.h" + +extern bool qt_file_access( const QString& fn, int t ); + +// NOT REVISED +/*! + \class QFile qfile.h + \brief The QFile class is an I/O device that operates on files. + + \ingroup io + + QFile is an I/O device for reading and writing binary and text files. A + QFile may be used by itself (readBlock and writeBlock) or by more + conveniently using QDataStream or QTextStream. + + 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 + QFile f("file.txt"); + if ( f.open(IO_ReadOnly) ) { // file opened successfully + QTextStream t( &f ); // use a text stream + QString s; + int n = 1; + while ( !t.eof() ) { // until end of file... + s = t.readLine(); // line of text excluding '\n' + printf( "%3d: %s\n", n++, (const char *)s ); + } + f.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. + + \sa QDataStream, QTextStream +*/ + + +/*! + Constructs a QFile with no name. +*/ + +QFile::QFile() +{ + init(); +} + +/*! + Constructs a QFile with a file name \e name. + \sa setName() +*/ + +QFile::QFile( const QString &name ) + : fn(name) +{ + init(); +} + + +/*! + Destructs 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. The name can include an absolute directory + path or it can be a name or a path relative to the current directory. + + Do not call this function if the file has already been opened. + + Note that if the name is relative QFile does not associate it with the + current directory. If you change directory before calling open(), open + uses the new current directory. + + Example: + \code + QFile f; + QDir::setCurrent( "/tmp" ); + f.setName( "readme.txt" ); + QDir::setCurrent( "/home" ); + f.open( IO_ReadOnly ); // opens "/home/readme.txt" under UNIX + \endcode + + Also 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(CHECK_STATE) + qWarning( "QFile::setName: File is open" ); +#endif + close(); + } + fn = name; +} + +/*! + Returns TRUE if this file exists, otherwise FALSE. + \sa name() +*/ + +bool QFile::exists() const +{ + return qt_file_access( fn, F_OK ); +} + +/*! + Returns TRUE if the file given by \e fileName exists, otherwise 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 FALSE. + + The file is closed before it is removed. +*/ + +bool QFile::remove() +{ + close(); + return remove( fn ); +} + +#if defined(_OS_MAC_) || defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_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 +} + +/*! + Returns TRUE if the end of file has been reached, otherwise FALSE. + \sa size() +*/ + +bool QFile::atEnd() const +{ + if ( !isOpen() ) { +#if defined(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 until end-of-line is reached, or up to \a + maxlen bytes, and returns the number of bytes read, or -1 in case of + error. The terminating newline is not stripped. + + This function is efficient only for buffered files. Avoid + readLine() for files that have been opened with the \c IO_Raw + flag. + + \sa readBlock(), QTextStream::readLine() +*/ + +int QFile::readLine( char *p, uint maxlen ) +{ + if ( maxlen == 0 ) // application bug? + return 0; +#if defined(CHECK_STATE) + 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 + int 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 ); + ioIndex += nread; + } else { + nread = -1; + setStatus(IO_ReadError); + } + } + return nread; +} + + +/*! + Reads a line of text. + + Reads bytes from the file until end-of-line is reached, or up to \a + maxlen bytes, and returns the number of bytes read, or -1 in case of + error. The terminating newline is not stripped. + + This function is efficient only for buffered files. Avoid + 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() +*/ + +int QFile::readLine( QString& s, uint maxlen ) +{ + QByteArray ba(maxlen); + int 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(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 ) + ioIndex++; + else + setStatus(IO_ReadError); + } + return ch; +} + +/*! + \fn int QFile::writeBlock( const QByteArray& data ) + \reimp + \internal + Should be removed in 3.0 +*/ + +/*! + Writes the character \e ch to the file. + + Returns \e ch, or -1 if some error occurred. + + \sa getch(), ungetch() +*/ + +int QFile::putch( int ch ) +{ +#if defined(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 ) { + ioIndex++; + if ( ioIndex > length ) // update file length + length = ioIndex; + } else { + setStatus(IO_WriteError); + } + } + return ch; +} + +/*! + Puts the character \e 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 \e ch, or -1 if some error occurred. + + \sa getch(), putch() +*/ + +int QFile::ungetch( int ch ) +{ +#if defined(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 ) + 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 filesystem + with Qt, you can use Unicode filenames. On Unix, these filenames + are converted to an 8-bit encoding. If you want to do your own + file I/O on Unix, you should convert the filename using this + function. On Windows NT, Unicode filenames are supported directly + in the filesystem and this function should be avoided. On Windows 95, + non-Latin1 locales are not supported at this time. + + By default, this function converts to the local 8-bit encoding + determined by the user's locale. This is sufficient for + filenames that the user chooses. Filenames 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 in filenames in UTF-8, etc., but beware that such filenames + 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(). +*/ + +/*! + Sets the function for encoding Unicode filenames. + 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(). + + \sa setDecodingFunction() +*/ +QString QFile::decodeName( const QCString &localFileName ) +{ + return (*decoder)(localFileName); +} + +/*! + \enum QFile::DecoderFn + + This is used by QFile::setDecodingFunction(). +*/ + +/*! + Sets the function for decoding 8-bit filenames. + The default uses the locale-specific 8-bit encoding. + + \sa encodeName(), decodeName() +*/ + +void QFile::setDecodingFunction( DecoderFn f ) +{ + decoder = f; +} diff --git a/qtools/qfile.h b/qtools/qfile.h new file mode 100644 index 0000000..4ef0685 --- /dev/null +++ b/qtools/qfile.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** +** Definition of QFile 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 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(); + + uint size() const; + int at() const; + bool at( int ); + bool atEnd() const; + + int readBlock( char *data, uint len ); + int writeBlock( const char *data, uint len ); + int writeBlock( const QByteArray& data ) + { return QIODevice::writeBlock(data); } + int readLine( char *data, uint maxlen ); + int readLine( QString &, uint maxlen ); + + int getch(); + int putch( int ); + int ungetch( int ); + + int handle() const; + +protected: + QString fn; + FILE *fh; + int fd; + int 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 int QFile::at() const +{ return ioIndex; } + + +#endif // QFILE_H diff --git a/qtools/qfile_unix.cpp b/qtools/qfile_unix.cpp new file mode 100644 index 0000000..5c27988 --- /dev/null +++ b/qtools/qfile_unix.cpp @@ -0,0 +1,601 @@ +/**************************************************************************** +** +** +** Implementation of QFileInfo class +** +** Created : 950628 +** +** 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 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 "qglobal.h" + +#include "qfile.h" +#include "qfiledefs_p.h" + +bool qt_file_access( const QString& fn, int t ) +{ + if ( fn.isEmpty() ) + return FALSE; + return ACCESS( QFile::encodeName(fn), t ) == 0; +} + +/*! + Removes the file \a fileName. + Returns TRUE if successful, otherwise FALSE. +*/ + +bool QFile::remove( const QString &fileName ) +{ + if ( fileName.isEmpty() ) { +#if defined(CHECK_NULL) + qWarning( "QFile::remove: Empty or null file name" ); +#endif + return FALSE; + } + return unlink( QFile::encodeName(fileName) ) == 0; + // unlink more common in UNIX +} + +#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 \e m. + Returns TRUE if successful, otherwise FALSE. + + The mode parameter \e m must be a combination of the following flags: + <ul> + <li>\c IO_Raw specified raw (non-buffered) file access. + <li>\c IO_ReadOnly opens the file in read-only mode. + <li>\c IO_WriteOnly opens the file in write-only mode (and truncates). + <li>\c IO_ReadWrite opens the file in read/write mode, equivalent to + \c (IO_ReadOnly|IO_WriteOnly). + <li>\c IO_Append opens the file in 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. + <li>\c IO_Truncate truncates the file. + <li>\c IO_Translate enables carriage returns and linefeed translation + for text files under MS-DOS, Windows and OS/2. + </ul> + + The raw access mode is best when I/O is block-operated using 4kB block size + or greater. Buffered access works better when reading small portions of + data at a time. + + <strong>Important:</strong> When working with buffered files, data may + not be written to the file at once. Call \link flush() flush\endlink + to make sure the data is really written. + + \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. + + 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" ); + QFile f2( "readme.txt" ); + f1.open( IO_Raw | IO_ReadWrite | IO_Append ); + f2.open( IO_ReadOnly | IO_Translate ); + \endcode + + \sa name(), close(), isOpen(), flush() +*/ + +bool QFile::open( int m ) +{ + if ( isOpen() ) { // file already open +#if defined(CHECK_STATE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + if ( fn.isNull() ) { // no file name defined +#if defined(CHECK_NULL) + qWarning( "QFile::open: No file name specified" ); +#endif + return FALSE; + } + init(); // reset params + setMode( m ); + if ( !(isReadable() || isWritable()) ) { +#if defined(CHECK_RANGE) + qWarning( "QFile::open: File access not specified" ); +#endif + return FALSE; + } + bool ok = TRUE; + STATBUF st; + if ( isRaw() ) { // raw file I/O + int oflags = OPEN_RDONLY; + if ( isReadable() && isWritable() ) + oflags = OPEN_RDWR; + else if ( isWritable() ) + oflags = OPEN_WRONLY; + if ( flags() & IO_Append ) { // append to end of file? + if ( flags() & IO_Truncate ) + oflags |= (OPEN_CREAT | OPEN_TRUNC); + else + oflags |= (OPEN_APPEND | OPEN_CREAT); + setFlags( flags() | IO_WriteOnly ); // append implies write + } else if ( isWritable() ) { // create/trunc if writable + if ( flags() & IO_Truncate ) + oflags |= (OPEN_CREAT | OPEN_TRUNC); + else + oflags |= OPEN_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 = 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 + while (1) { // 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 & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = (flags() & IO_Append) == 0 ? 0 : length; + } else { + length = (int)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; + } + } + } + } else { + init(); + if ( errno == EMFILE ) // no more file handles/descrs + setStatus( IO_ResourceError ); + else + setStatus( IO_OpenError ); + } + return ok; +} + +/*! + Opens a file in the mode \e m using an existing file handle \e 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 \e 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(CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m &~IO_Raw ); + setState( IO_Open ); + fh = f; + ext_f = TRUE; + STATBUF st; + FSTAT( FILENO(fh), &st ); + ioIndex = (int)ftell( fh ); + if ( (st.st_mode & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + } else { + length = (int)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; + } + } + } + return TRUE; +} + +/*! + Opens a file in the mode \e m using an existing file descriptor \e f. + Returns TRUE if successful, otherwise FALSE. + + When a QFile is opened using this function, close() does not actually + close the file. + + \warning If \e 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(CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m |IO_Raw ); + setState( IO_Open ); + fd = f; + ext_f = TRUE; + STATBUF st; + FSTAT( fd, &st ); + ioIndex = (int)LSEEK(fd, 0, SEEK_CUR); + if ( (st.st_mode & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + } else { + length = (int)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; + } + } + } + return TRUE; +} + +/*! + Returns the file size. + \sa at() +*/ + +uint QFile::size() const +{ + STATBUF st; + if ( isOpen() ) { + FSTAT( fh ? FILENO(fh) : fd, &st ); + } else { + STAT( QFile::encodeName(fn), &st ); + } + return st.st_size; +} + +/*! + \fn int QFile::at() const + Returns the file index. + \sa size() +*/ + +/*! + Sets the file index to \e pos. Returns TRUE if successful, otherwise 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 + + \warning The result is undefined if the file was \link open() opened\endlink + using the \c IO_Append specifier. + + \sa size(), open() +*/ + +bool QFile::at( int pos ) +{ + if ( !isOpen() ) { +#if defined(CHECK_STATE) + qWarning( "QFile::at: File is not open" ); +#endif + return FALSE; + } + bool ok; + if ( isRaw() ) { // raw file + pos = (int)LSEEK(fd, pos, SEEK_SET); + ok = pos != -1; + } else { // buffered file + ok = fseek(fh, pos, SEEK_SET) == 0; + } + if ( ok ) + ioIndex = pos; +#if defined(CHECK_RANGE) + else + qWarning( "QFile::at: Cannot set file position %d", pos ); +#endif + return ok; +} + +/*! + Reads at most \e len bytes from the file into \e p and returns the + number of bytes actually read. + + Returns -1 if a serious error occurred. + + \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. + + \sa writeBlock() +*/ + +int QFile::readBlock( char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( !p ) + qWarning( "QFile::readBlock: Null pointer error" ); +#endif +#if defined(CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::readBlock: File not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QFile::readBlock: Read operation not permitted" ); + return -1; + } +#endif + int nread; // number of bytes read + if ( isRaw() ) { // raw file + nread = READ( fd, p, len ); + if ( len && nread <= 0 ) { + nread = 0; + setStatus(IO_ReadError); + } + } else { // buffered file + nread = fread( p, 1, len, fh ); + if ( (uint)nread != len ) { + if ( ferror( fh ) || nread==0 ) + setStatus(IO_ReadError); + } + } + ioIndex += nread; + return nread; +} + +/*! \overload int writeBlock( const QByteArray& data ) +*/ + +/*! \reimp + + Writes \e len bytes from \e 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() +*/ + +int QFile::writeBlock( const char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QFile::writeBlock: Null pointer error" ); +#endif +#if defined(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 + int nwritten; // number of bytes written + if ( isRaw() ) // raw file + nwritten = WRITE( fd, p, len ); + else // buffered file + nwritten = fwrite( p, 1, len, fh ); + if ( nwritten != (int)len ) { // write error + if ( errno == ENOSPC ) // disk is full + setStatus( IO_ResourceError ); + else + setStatus( IO_WriteError ); + if ( isRaw() ) // recalc file position + ioIndex = (int)LSEEK( fd, 0, SEEK_CUR ); + else + ioIndex = fseek( fh, 0, SEEK_CUR ); + } else { + 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/qtools/qfile_win32.cpp b/qtools/qfile_win32.cpp new file mode 100644 index 0000000..5272365 --- /dev/null +++ b/qtools/qfile_win32.cpp @@ -0,0 +1,582 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + * Based on qfile_unix.cpp + * + * Copyright (C) 1992-2000 Trolltech AS. + */ + +#include "qglobal.h" + +#include "qfile.h" +#include "qfiledefs_p.h" + +bool qt_file_access( const QString& fn, int t ) +{ + if ( fn.isEmpty() ) + return FALSE; + return ACCESS( QFile::encodeName(fn), t ) == 0; +} + +/*! + Removes the file \a fileName. + Returns TRUE if successful, otherwise FALSE. +*/ + +bool QFile::remove( const QString &fileName ) +{ + if ( fileName.isEmpty() ) { +#if defined(CHECK_NULL) + qWarning( "QFile::remove: Empty or null file name" ); +#endif + return FALSE; + } + return ::remove( QFile::encodeName(fileName) ) == 0; + // unlink more common in UNIX +} + +#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 \e m. + Returns TRUE if successful, otherwise FALSE. + + The mode parameter \e m must be a combination of the following flags: + <ul> + <li>\c IO_Raw specified raw (non-buffered) file access. + <li>\c IO_ReadOnly opens the file in read-only mode. + <li>\c IO_WriteOnly opens the file in write-only mode (and truncates). + <li>\c IO_ReadWrite opens the file in read/write mode, equivalent to + \c (IO_ReadOnly|IO_WriteOnly). + <li>\c IO_Append opens the file in 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. + <li>\c IO_Truncate truncates the file. + <li>\c IO_Translate enables carriage returns and linefeed translation + for text files under MS-DOS, Windows and OS/2. + </ul> + + The raw access mode is best when I/O is block-operated using 4kB block size + or greater. Buffered access works better when reading small portions of + data at a time. + + <strong>Important:</strong> When working with buffered files, data may + not be written to the file at once. Call \link flush() flush\endlink + to make sure the data is really written. + + \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. + + 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" ); + QFile f2( "readme.txt" ); + f1.open( IO_Raw | IO_ReadWrite | IO_Append ); + f2.open( IO_ReadOnly | IO_Translate ); + \endcode + + \sa name(), close(), isOpen(), flush() +*/ + +bool QFile::open( int m ) +{ + if ( isOpen() ) { // file already open +#if defined(CHECK_STATE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + if ( fn.isNull() ) { // no file name defined +#if defined(CHECK_NULL) + qWarning( "QFile::open: No file name specified" ); +#endif + return FALSE; + } + init(); // reset params + setMode( m ); + if ( !(isReadable() || isWritable()) ) { +#if defined(CHECK_RANGE) + qWarning( "QFile::open: File access not specified" ); +#endif + return FALSE; + } + bool ok = TRUE; + STATBUF st; + if ( isRaw() ) { // raw file I/O + int oflags = OPEN_RDONLY; + if ( isReadable() && isWritable() ) + oflags = OPEN_RDWR; + else if ( isWritable() ) + oflags = OPEN_WRONLY; + if ( flags() & IO_Append ) { // append to end of file? + if ( flags() & IO_Truncate ) + oflags |= (OPEN_CREAT | OPEN_TRUNC); + else + oflags |= (OPEN_APPEND | OPEN_CREAT); + setFlags( flags() | IO_WriteOnly ); // append implies write + } else if ( isWritable() ) { // create/trunc if writable + if ( flags() & IO_Truncate ) + oflags |= (OPEN_CREAT | OPEN_TRUNC); + else + oflags |= OPEN_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 = 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 ( isTranslated() ) + strcat( perm2, "t" ); + else + strcat( perm2, "b" ); + while (1) { // 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 & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + ioIndex = (flags() & IO_Append) == 0 ? 0 : length; + } else { + length = (int)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; + } + } + } + } else { + init(); + if ( errno == EMFILE ) // no more file handles/descrs + setStatus( IO_ResourceError ); + else + setStatus( IO_OpenError ); + } + return ok; +} + +/*! + Opens a file in the mode \e m using an existing file handle \e 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 \e 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(CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m &~IO_Raw ); + setState( IO_Open ); + fh = f; + ext_f = TRUE; + STATBUF st; + FSTAT( FILENO(fh), &st ); + ioIndex = (int)ftell( fh ); + if ( (st.st_mode & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + } else { + length = (int)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; + } + } + } + return TRUE; +} + +/*! + Opens a file in the mode \e m using an existing file descriptor \e f. + Returns TRUE if successful, otherwise FALSE. + + When a QFile is opened using this function, close() does not actually + close the file. + + \warning If \e 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(CHECK_RANGE) + qWarning( "QFile::open: File already open" ); +#endif + return FALSE; + } + init(); + setMode( m |IO_Raw ); + setState( IO_Open ); + fd = f; + ext_f = TRUE; + STATBUF st; + FSTAT( fd, &st ); + ioIndex = (int)LSEEK(fd, 0, SEEK_CUR); + if ( (st.st_mode & STAT_MASK) != STAT_REG ) { + // non-seekable + setType( IO_Sequential ); + length = INT_MAX; + } else { + length = (int)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; + } + } + } + return TRUE; +} + +/*! + Returns the file size. + \sa at() +*/ + +uint QFile::size() const +{ + STATBUF st; + if ( isOpen() ) { + FSTAT( fh ? FILENO(fh) : fd, &st ); + } else { + STAT( QFile::encodeName(fn), &st ); + } + return st.st_size; +} + +/*! + \fn int QFile::at() const + Returns the file index. + \sa size() +*/ + +/*! + Sets the file index to \e pos. Returns TRUE if successful, otherwise 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 + + \warning The result is undefined if the file was \link open() opened\endlink + using the \c IO_Append specifier. + + \sa size(), open() +*/ + +bool QFile::at( int pos ) +{ + if ( !isOpen() ) { +#if defined(CHECK_STATE) + qWarning( "QFile::at: File is not open" ); +#endif + return FALSE; + } + bool ok; + if ( isRaw() ) { // raw file + pos = (int)LSEEK(fd, pos, SEEK_SET); + ok = pos != -1; + } else { // buffered file + ok = fseek(fh, pos, SEEK_SET) == 0; + } + if ( ok ) + ioIndex = pos; +#if defined(CHECK_RANGE) + else + qWarning( "QFile::at: Cannot set file position %d", pos ); +#endif + return ok; +} + +/*! + Reads at most \e len bytes from the file into \e p and returns the + number of bytes actually read. + + Returns -1 if a serious error occurred. + + \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. + + \sa writeBlock() +*/ + +int QFile::readBlock( char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( !p ) + qWarning( "QFile::readBlock: Null pointer error" ); +#endif +#if defined(CHECK_STATE) + if ( !isOpen() ) { // file not open + qWarning( "QFile::readBlock: File not open" ); + return -1; + } + if ( !isReadable() ) { // reading not permitted + qWarning( "QFile::readBlock: Read operation not permitted" ); + return -1; + } +#endif + int nread; // number of bytes read + if ( isRaw() ) { // raw file + nread = READ( fd, p, len ); + if ( len && nread <= 0 ) { + nread = 0; + setStatus(IO_ReadError); + } + } else { // buffered file + nread = fread( p, 1, len, fh ); + if ( (uint)nread != len ) { + if ( ferror( fh ) || nread==0 ) + setStatus(IO_ReadError); + } + } + ioIndex += nread; + return nread; +} + +/*! \overload int writeBlock( const QByteArray& data ) +*/ + +/*! \reimp + + Writes \e len bytes from \e 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() +*/ + +int QFile::writeBlock( const char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QFile::writeBlock: Null pointer error" ); +#endif +#if defined(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 + int nwritten; // number of bytes written + if ( isRaw() ) // raw file + nwritten = WRITE( fd, p, len ); + else // buffered file + nwritten = fwrite( p, 1, len, fh ); + if ( nwritten != (int)len ) { // write error + if ( errno == ENOSPC ) // disk is full + setStatus( IO_ResourceError ); + else + setStatus( IO_WriteError ); + if ( isRaw() ) // recalc file position + ioIndex = (int)LSEEK( fd, 0, SEEK_CUR ); + else + ioIndex = fseek( fh, 0, SEEK_CUR ); + } else { + 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/qtools/qfiledefs_p.h b/qtools/qfiledefs_p.h new file mode 100644 index 0000000..4a1a154 --- /dev/null +++ b/qtools/qfiledefs_p.h @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** +** Common macros and system include files for QFile, QFileInfo and QDir. +** +** 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 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 qfile.cpp, qfileinfo.cpp and qdir.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// + + +#if defined(_CC_MWERKS_) +# include <stdlib.h> +# include <stat.h> +#elif !defined(_OS_MAC_) +# include <sys/types.h> +# include <sys/stat.h> +#endif +#include <fcntl.h> +#include <errno.h> +#if defined(_OS_UNIX_) +# include <dirent.h> +# include <unistd.h> +#endif +#if defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_OS_OS2_) +# define _OS_FATFS_ +# if defined(__CYGWIN32__) +# include <dirent.h> +# include <unistd.h> +# if !defined(_OS_UNIX_) +# define _OS_UNIX_ +# endif +# else +# include <io.h> +# if !defined(_CC_MWERKS_) +# include <dos.h> +# endif +# include <direct.h> +# endif +#endif +#include <limits.h> + + +#if !defined(PATH_MAX) +#if defined( MAXPATHLEN ) +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + + +#undef STATBUF +#undef STAT +#undef STAT_REG +#undef STAT_DIR +#undef STAT_LNK +#undef STAT_MASK +#undef FILENO +#undef OPEN +#undef CLOSE +#undef LSEEK +#undef READ +#undef WRITE +#undef ACCESS +#undef GETCWD +#undef CHDIR +#undef MKDIR +#undef RMDIR +#undef OPEN_RDONLY +#undef OPEN_WRONLY +#undef OPEN_CREAT +#undef OPEN_TRUNC +#undef OPEN_APPEND +#undef OPEN_TEXT +#undef OPEN_BINARY + + +#if defined(_CC_MSVC_) || defined(_CC_SYM_) + +# define STATBUF struct _stat // non-ANSI defs +# define STATBUF4TSTAT struct _stat // non-ANSI defs +# define STAT ::_stat +# define FSTAT ::_fstat +# define STAT_REG _S_IFREG +# define STAT_DIR _S_IFDIR +# define STAT_MASK _S_IFMT +# if defined(_S_IFLNK) +# define STAT_LNK _S_IFLNK +# endif +# define FILENO _fileno +# define OPEN ::_open +# define CLOSE ::_close +# define LSEEK ::_lseek +# define READ ::_read +# define WRITE ::_write +# define ACCESS ::_access +# define GETCWD ::_getcwd +# define CHDIR ::_chdir +# define MKDIR ::_mkdir +# define RMDIR ::_rmdir +# define OPEN_RDONLY _O_RDONLY +# define OPEN_WRONLY _O_WRONLY +# define OPEN_RDWR _O_RDWR +# define OPEN_CREAT _O_CREAT +# define OPEN_TRUNC _O_TRUNC +# define OPEN_APPEND _O_APPEND +# if defined(O_TEXT) +# define OPEN_TEXT _O_TEXT +# define OPEN_BINARY _O_BINARY +# endif + +#elif defined(_CC_BOR_) && __BORLANDC__ >= 0x550 + +# define STATBUF struct stat // non-ANSI defs +# define STATBUF4TSTAT struct _stat // non-ANSI defs +# define STAT ::stat +# define FSTAT ::fstat +# define STAT_REG _S_IFREG +# define STAT_DIR _S_IFDIR +# define STAT_MASK _S_IFMT +# if defined(_S_IFLNK) +# define STAT_LNK _S_IFLNK +# endif +# define FILENO _fileno +# define OPEN ::open +# define CLOSE ::_close +# define LSEEK ::_lseek +# define READ ::_read +# define WRITE ::_write +# define ACCESS ::_access +# define GETCWD ::_getcwd +# define CHDIR ::chdir +# define MKDIR ::_mkdir +# define RMDIR ::_rmdir +# define OPEN_RDONLY _O_RDONLY +# define OPEN_WRONLY _O_WRONLY +# define OPEN_RDWR _O_RDWR +# define OPEN_CREAT _O_CREAT +# define OPEN_TRUNC _O_TRUNC +# define OPEN_APPEND _O_APPEND +# if defined(O_TEXT) +# define OPEN_TEXT _O_TEXT +# define OPEN_BINARY _O_BINARY +# endif + +#else // all other systems + +# define STATBUF struct stat +# define STATBUF4TSTAT struct stat +# define STAT ::stat +# define FSTAT ::fstat +# define STAT_REG S_IFREG +# define STAT_DIR S_IFDIR +# define STAT_MASK S_IFMT +# if defined(S_IFLNK) +# define STAT_LNK S_IFLNK +# endif +# define FILENO fileno +# define OPEN ::open +# define CLOSE ::close +# define LSEEK ::lseek +# define READ ::read +# define WRITE ::write +# define ACCESS ::access +# if defined(_OS_OS2EMX_) +# define GETCWD ::_getcwd2 +# define CHDIR ::_chdir2 +# else +# define GETCWD ::getcwd +# define CHDIR ::chdir +# endif +# define MKDIR ::mkdir +# define RMDIR ::rmdir +# define OPEN_RDONLY O_RDONLY +# define OPEN_WRONLY O_WRONLY +# define OPEN_RDWR O_RDWR +# define OPEN_CREAT O_CREAT +# define OPEN_TRUNC O_TRUNC +# define OPEN_APPEND O_APPEND +# if defined(O_TEXT) +# define OPEN_TEXT O_TEXT +# define OPEN_BINARY O_BINARY +# endif +#endif + +#if defined(_CC_MWERKS_) +#undef mkdir +#undef MKDIR +#define MKDIR _mkdir +#undef rmdir +#undef RMDIR +#define RMDIR _rmdir +#endif + + +#if defined(_OS_FATFS_) +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + +#if defined(_OS_MAC_) +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + +struct QFileInfoCache +{ + STATBUF st; + bool isSymLink; +}; + +#endif diff --git a/qtools/qfileinfo.cpp b/qtools/qfileinfo.cpp new file mode 100644 index 0000000..5053b76 --- /dev/null +++ b/qtools/qfileinfo.cpp @@ -0,0 +1,458 @@ +/**************************************************************************** +** +** +** Implementation of QFileInfo class +** +** Created : 950628 +** +** 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" + +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qdatetime.h" +#include "qdir.h" + +extern bool qt_file_access( const QString& fn, int t ); + +// NOT REVISED +/*! + \class QFileInfo qfileinfo.h + \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 a + symbolic link. Its size and last modified/read times are also available. + + To speed up performance QFileInfo caches information about the file. Since + 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 would rather like a QFileInfo to access the file system + every time you request information from it, you can call the function + setCaching( FALSE ). + + A QFileInfo can point to a file using either a relative or an absolute + file path. Absolute file paths begin with the directory separator + ('/') or a drive specification (not applicable to UNIX). + 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". You can use the function isRelative() to check if a QFileInfo + is using a relative or an absolute file path. You can call the function + convertToAbs() to convert a relative QFileInfo to an absolute one. + + If you need to read and traverse directories, see the QDir class. +*/ + + +/*! + Constructs a new empty QFileInfo. +*/ + +QFileInfo::QFileInfo() +{ + fic = 0; + cache = TRUE; +} + +/*! + Constructs a new QFileInfo that gives information about the given file. + The string given can be an absolute or a relative file path. + + \sa bool setFile(QString ), isRelative(), QDir::setCurrent(), + QDir::isRelativePath() +*/ + +QFileInfo::QFileInfo( const QString &file ) +{ + fn = file; + slashify( fn ); + fic = 0; + cache = TRUE; +} + +/*! + Constructs a new QFileInfo that gives information about \e file. + + If the file has a relative path, the QFileInfo will also have one. + + \sa isRelative() +*/ + +QFileInfo::QFileInfo( const QFile &file ) +{ + fn = file.name(); + slashify( fn ); + fic = 0; + cache = TRUE; +} + +/*! + Constructs a new QFileInfo that gives information about the file + named \e fileName in the directory \e d. + + If the directory has a relative path, the QFileInfo will also have one. + + \sa isRelative() +*/ +#ifndef QT_NO_DIR +QFileInfo::QFileInfo( const QDir &d, const QString &fileName ) +{ + fn = d.filePath( fileName ); + slashify( fn ); + fic = 0; + cache = TRUE; +} +#endif +/*! + Constructs a new QFileInfo that is a copy of \e fi. +*/ + +QFileInfo::QFileInfo( const QFileInfo &fi ) +{ + fn = fi.fn; + if ( fi.fic ) { + fic = new QFileInfoCache; + *fic = *fi.fic; + } else { + fic = 0; + } + cache = fi.cache; +} + +/*! + Destructs the QFileInfo. +*/ + +QFileInfo::~QFileInfo() +{ + delete fic; +} + + +/*! + Makes a copy of \e 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; + CHECK_PTR( fic ); + } + *fic = *fi.fic; + } + cache = fi.cache; + return *this; +} + + +/*! + Sets the file to obtain information about. + + The string given can be an absolute or a relative file path. Absolute file + paths begin with the directory separator (e.g. '/' under UNIX) or a drive + specification (not applicable to UNIX). Relative file names begin with a + directory name or a file name and specify a path relative to the current + directory. + + Example: + \code + #include <qfileinfo.h> + #include <qdir.h> + + void test() + { + QString absolute = "/liver/aorta"; + QString relative = "liver/aorta"; + QFileInfo fi1( absolute ); + QFileInfo fi2( relative ); + + QDir::setCurrent( QDir::rootDirPath() ); + // fi1 and fi2 now point to the same file + + QDir::setCurrent( "/tmp" ); + // fi1 now points to "/liver/aorta", + // while fi2 points to "/tmp/liver/aorta" + } + \endcode + + \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath() +*/ + +void QFileInfo::setFile( const QString &file ) +{ + fn = file; + slashify( fn ); + delete fic; + fic = 0; +} + +/*! + Sets the file to obtain information about. + + If the file has a relative path, the QFileInfo will also have one. + + \sa isRelative() +*/ + +void QFileInfo::setFile( const QFile &file ) +{ + fn = file.name(); + slashify( fn ); + delete fic; + fic = 0; +} + +/*! + Sets the file to obtains information about to \e fileName in the + directory \e d. + + If the directory has a relative path, the QFileInfo will also have one. + + \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 pointed to exists, otherwise FALSE. +*/ + +bool QFileInfo::exists() const +{ + return qt_file_access( fn, F_OK ); +} + +/*! + Refresh the information about the file, i.e. read 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. + \sa setCaching(), refresh() +*/ + +/*! + Enables caching of file information if \e enable is TRUE, or disables it + if \e enable is FALSE. + + When caching is enabled, QFileInfo reads the file information the first + time + + 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 name, i.e. the file name including the path (which can be + absolute or relative). + + \sa isRelative(), absFilePath() +*/ + +QString QFileInfo::filePath() const +{ + return fn; +} + +/*! + Returns the base name of the file. + + The base name consists of all characters in the file name up to (but not + including) the first '.' character. The path is not included. + + Example: + \code + QFileInfo fi( "/tmp/abdomen.lower" ); + QString base = fi.baseName(); // base = "abdomen" + \endcode + + \sa fileName(), extension() +*/ + +QString QFileInfo::baseName() const +{ + QString tmp = fileName(); + int pos = tmp.find( '.' ); + if ( pos == -1 ) + return tmp; + else + return tmp.left( pos ); +} + +/*! + Returns the extension name of the file. + + 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. For a file named "archive.tar.gz" this + returns "tar.gz". + + If \a complete is FALSE, extension() returns the string of all + characters in the file name after (but not including) the last '.' + character. For a file named "archive.tar.gz" this returns "gz". + + Example: + \code + QFileInfo fi( "lex.yy.c" ); + QString ext = fi.extension(); // ext = "yy.c" + QString ext = fi.extension( FALSE ); // ext = "c" + \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 directory path of the file. + + If the QFileInfo is relative and \e 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. + \sa isWritable(), isExecutable(), permission() +*/ + +bool QFileInfo::isReadable() const +{ + return qt_file_access( fn, R_OK ); +} + +/*! + Returns TRUE if the file is writable. + \sa isReadable(), isExecutable(), permission() +*/ + +bool QFileInfo::isWritable() const +{ + return qt_file_access( fn, W_OK ); +} + +/*! + Returns TRUE if the file is executable. + \sa isReadable(), isWritable(), permission() +*/ + +bool QFileInfo::isExecutable() const +{ + return qt_file_access( fn, X_OK ); +} + + +/*! + Returns TRUE if the file path name is relative to the current directory, + FALSE if the path is absolute (e.g. under UNIX a path is relative if it + does not start with a '/'). + + According to Einstein this function should always return TRUE. +*/ +#ifndef QT_NO_DIR +bool QFileInfo::isRelative() const +{ + return QDir::isRelativePath( fn ); +} + +/*! + Converts the file path name 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 diff --git a/qtools/qfileinfo.h b/qtools/qfileinfo.h new file mode 100644 index 0000000..76ef8c2 --- /dev/null +++ b/qtools/qfileinfo.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** +** Definition of QFileInfo class +** +** Created : 950628 +** +** 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 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 // file information class +{ +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() 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; + +#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; + + uint size() 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; +}; + + +inline bool QFileInfo::caching() const +{ + return cache; +} + + +#endif // QFILEINFO_H diff --git a/qtools/qfileinfo_unix.cpp b/qtools/qfileinfo_unix.cpp new file mode 100644 index 0000000..5a8fe04 --- /dev/null +++ b/qtools/qfileinfo_unix.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** +** Implementation of QFileInfo class +** +** Created : 950628 +** +** 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 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 "qglobal.h" + +#if defined(_OS_SUN_) +#define readlink _qt_hide_readlink +#endif + +#include <pwd.h> +#include <grp.h> + +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qdatetime.h" +#include "qdir.h" + +#if defined(_OS_SUN_) +#undef readlink +extern "C" int readlink( const char *, void *, uint ); +#endif + + +void QFileInfo::slashify( QString& ) +{ + return; +} + + +void QFileInfo::makeAbs( QString & ) +{ + return; +} + +extern bool qt_file_access( const QString& fn, int t ); + +/*! + Returns TRUE if we are pointing to a real file. + \sa isDir(), isSymLink() +*/ +bool QFileInfo::isFile() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & STAT_MASK) == STAT_REG : FALSE; +} + +/*! + Returns TRUE if we are pointing to a directory or a symbolic link to + a directory. + \sa isFile(), isSymLink() +*/ + +bool QFileInfo::isDir() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & STAT_MASK) == STAT_DIR : FALSE; +} + +/*! + Returns TRUE if we are pointing to a symbolic link. + \sa isFile(), isDir(), readLink() +*/ + +bool QFileInfo::isSymLink() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? fic->isSymLink : FALSE; +} + + +/*! + Returns the name a symlink points to, or a null QString if the + object does not refer to 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(_OS_UNIX_) && !defined(_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 systems where files do not have owners this function returns 0. + + Note that this function can be time-consuming under UNIX. (in the order + of milliseconds on a 486 DX2/66 running Linux). + + \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 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 the file belongs to. + + On systems where files do not have groups this function always + returns 0. + + Note that this function can be time-consuming under UNIX (in the order of + milliseconds on a 486 DX2/66 running Linux). + + \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 systems where files do not have groups this function always + returns ((uind) -2). + + \sa group(), owner(), ownerId() +*/ + +uint QFileInfo::groupId() const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) + return fic->st.st_gid; + return nobodyID; +} + + +/*! + \fn bool QFileInfo::permission( int permissionSpec ) const + + Tests for file permissions. The \e permissionSpec argument can be several + flags of type 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/tonsils" ); + if ( fi.permission( QFileInfo::WriteUser | QFileInfo::ReadGroup ) ) + qWarning( "Tonsils can be changed by me, and the group can read them."); + if ( fi.permission( QFileInfo::WriteGroup | QFileInfo::WriteOther ) ) + qWarning( "Danger! Tonsils can be changed by the group or others!" ); + \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(CHECK_NULL) + qWarning( "QFileInfo::permission: permissionSpec is 0" ); +#endif + return TRUE; + } + } else { + return FALSE; + } +} + +/*! + Returns the file size in bytes, or 0 if the file does not exist if the size + cannot be fetched. +*/ + +uint QFileInfo::size() const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) + return (uint)fic->st.st_size; + else + return 0; +} + + +/*! + Returns the date and time when the file was last modified. + \sa 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 systems that do not support last read times, the modification time is + returned. + + \sa lastModified() +*/ + +QDateTime QFileInfo::lastRead() const +{ + QDateTime dt; + if ( !fic || !cache ) + doStat(); + if ( fic ) + dt.setTime_t( fic->st.st_atime ); + return dt; +} + + +void QFileInfo::doStat() const +{ + QFileInfo *that = ((QFileInfo*)this); // mutable function + if ( !that->fic ) + that->fic = new QFileInfoCache; + STATBUF *b = &that->fic->st; + that->fic->isSymLink = FALSE; + +#if defined(_OS_UNIX_) && defined(S_IFLNK) + if ( ::lstat(QFile::encodeName(fn),b) == 0 ) { + if ( S_ISLNK( b->st_mode ) ) + that->fic->isSymLink = TRUE; + else + return; + } +#endif + int r; + + r = STAT( QFile::encodeName(fn), b ); + + if ( r != 0 ) { + delete that->fic; + that->fic = 0; + } +} + +/*! + Returns the directory path of the file. + + If \e absPath is TRUE an absolute path is always 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, the file path is not included. + + Example: + \code + QFileInfo fi( "/tmp/abdomen.lower" ); + QString name = fi.fileName(); // name = "abdomen.lower" + \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); + } +} + +/*! + Returns the absolute path name. + + The absolute path name is the file name including the absolute path. If + the QFileInfo is absolute (i.e. not relative) this function will return + the same string as filePath(). + + Note that this function can be time-consuming under UNIX. (in the order + of milliseconds on a 486 DX2/66 running Linux). + + \sa isRelative(), filePath() +*/ +#ifndef QT_NO_DIR +QString QFileInfo::absFilePath() const +{ + if ( QDir::isRelativePath(fn) ) { + QString tmp = QDir::currentDirPath(); + tmp += '/'; + tmp += fn; + makeAbs( tmp ); + return QDir::cleanDirPath( tmp ); + } else { + QString tmp = fn; + makeAbs( tmp ); + return QDir::cleanDirPath( tmp ); + } + +} +#endif diff --git a/qtools/qfileinfo_win32.cpp b/qtools/qfileinfo_win32.cpp new file mode 100644 index 0000000..47b8491 --- /dev/null +++ b/qtools/qfileinfo_win32.cpp @@ -0,0 +1,334 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + * Based on qfileinfo_unix.cpp + * + * Copyright (C) 1992-2000 Trolltech AS. + */ + +#include "qglobal.h" + +#include "qfileinfo.h" +#include "qfiledefs_p.h" +#include "qdatetime.h" +#include "qdir.h" + +void QFileInfo::slashify( QString& n ) +{ + for ( int i=0; i<(int)n.length(); i++ ) + { + if ( n[i] == '\\' ) + n[i] = '/'; + } +} + +void QFileInfo::makeAbs( QString & ) +{ + // TODO: what to do here? + return; +} + +extern bool qt_file_access( const QString& fn, int t ); + +/*! + Returns TRUE if we are pointing to a real file. + \sa isDir(), isSymLink() +*/ +bool QFileInfo::isFile() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & STAT_MASK) == STAT_REG : FALSE; +} + +/*! + Returns TRUE if we are pointing to a directory or a symbolic link to + a directory. + \sa isFile(), isSymLink() +*/ + +bool QFileInfo::isDir() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? (fic->st.st_mode & STAT_MASK) == STAT_DIR : FALSE; +} + +/*! + Returns TRUE if we are pointing to a symbolic link. + \sa isFile(), isDir(), readLink() +*/ + +bool QFileInfo::isSymLink() const +{ + if ( !fic || !cache ) + doStat(); + return fic ? fic->isSymLink : FALSE; +} + + +/*! + Returns the name a symlink points to, or a null QString if the + object does not refer to 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; + return r; +} + +static const uint nobodyID = (uint) -2; + +/*! + Returns the owner of the file. + + On systems where files do not have owners this function returns + a null string. + + Note that this function can be time-consuming under UNIX. (in the order + of milliseconds on a 486 DX2/66 running Linux). + + \sa ownerId(), group(), groupId() +*/ + +QString QFileInfo::owner() const +{ + return QString::null; +} + +/*! + Returns the id of the owner of the file. + + On systems where files do not have owners this function returns ((uint) -2). + + \sa owner(), group(), groupId() +*/ + +uint QFileInfo::ownerId() const +{ + return (uint)-2; +} + +/*! + Returns the group the file belongs to. + + On systems where files do not have groups this function always + returns 0. + + Note that this function can be time-consuming under UNIX (in the order of + milliseconds on a 486 DX2/66 running Linux). + + \sa groupId(), owner(), ownerId() +*/ + +QString QFileInfo::group() const +{ + return QString::null; +} + +/*! + Returns the id of the group the file belongs to. + + On systems where files do not have groups this function always + returns ((uind) -2). + + \sa group(), owner(), ownerId() +*/ + +uint QFileInfo::groupId() const +{ + return (uint)-2; +} + + +/*! + \fn bool QFileInfo::permission( int permissionSpec ) const + + Tests for file permissions. The \e permissionSpec argument can be several + flags of type 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/tonsils" ); + if ( fi.permission( QFileInfo::WriteUser | QFileInfo::ReadGroup ) ) + qWarning( "Tonsils can be changed by me, and the group can read them."); + if ( fi.permission( QFileInfo::WriteGroup | QFileInfo::WriteOther ) ) + qWarning( "Danger! Tonsils can be changed by the group or others!" ); + \endcode + + \sa isReadable(), isWritable(), isExecutable() +*/ + +bool QFileInfo::permission( int permissionSpec ) const +{ + return TRUE; +} + +/*! + Returns the file size in bytes, or 0 if the file does not exist if the size + cannot be fetched. +*/ + +uint QFileInfo::size() const +{ + if ( !fic || !cache ) + doStat(); + if ( fic ) + return (uint)fic->st.st_size; + else + return 0; +} + + +/*! + Returns the date and time when the file was last modified. + \sa 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 systems that do not support last read times, the modification time is + returned. + + \sa lastModified() +*/ + +QDateTime QFileInfo::lastRead() const +{ + QDateTime dt; + if ( !fic || !cache ) + doStat(); + if ( fic ) + dt.setTime_t( fic->st.st_atime ); + return dt; +} + + +void QFileInfo::doStat() const +{ + QFileInfo *that = ((QFileInfo*)this); // mutable function + if ( !that->fic ) + that->fic = new QFileInfoCache; + STATBUF *b = &that->fic->st; + that->fic->isSymLink = FALSE; + + int r; + + r = STAT( QFile::encodeName(fn), b ); + + if ( r != 0 ) { + delete that->fic; + that->fic = 0; + } +} + +/*! + Returns the directory path of the file. + + If \e absPath is TRUE an absolute path is always 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, the file path is not included. + + Example: + \code + QFileInfo fi( "/tmp/abdomen.lower" ); + QString name = fi.fileName(); // name = "abdomen.lower" + \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); + } +} + +/*! + Returns the absolute path name. + + The absolute path name is the file name including the absolute path. If + the QFileInfo is absolute (i.e. not relative) this function will return + the same string as filePath(). + + Note that this function can be time-consuming under UNIX. (in the order + of milliseconds on a 486 DX2/66 running Linux). + + \sa isRelative(), filePath() +*/ +#ifndef QT_NO_DIR +QString QFileInfo::absFilePath() const +{ + if ( QDir::isRelativePath(fn) ) { + QString tmp = QDir::currentDirPath(); + tmp += '/'; + tmp += fn; + makeAbs( tmp ); + return QDir::cleanDirPath( tmp ); + } else { + QString tmp = fn; + makeAbs( tmp ); + return QDir::cleanDirPath( tmp ); + } + +} +#endif diff --git a/qtools/qgarray.cpp b/qtools/qgarray.cpp new file mode 100644 index 0000000..efc9de0 --- /dev/null +++ b/qtools/qgarray.cpp @@ -0,0 +1,747 @@ +/**************************************************************************** +** +** +** 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. +** +**********************************************************************/ + +#define QGARRAY_CPP +#include "qgarray.h" +#include "qstring.h" +#include <stdlib.h> + +#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 + + +// NOT REVISED +/*! + \class QShared qshared.h + \brief The QShared struct is internally used for implementing shared classes. + + 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 + \brief The QGArray class is an internal class for implementing the QArray class. + + QGArray is a strictly internal class that acts as base class for the + QArray template array. + + It contains an array of bytes and has no notion of an array element. +*/ + + +/*! + \internal + Constructs a null array. +*/ + +QGArray::QGArray() +{ + shd = newData(); + CHECK_PTR( shd ); +} + +/*! + \internal + 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 ) +{ +} + +/*! + \internal + Constructs an array with room for \e size bytes. +*/ + +QGArray::QGArray( int size ) +{ + if ( size < 0 ) { +#if defined(CHECK_RANGE) + qWarning( "QGArray: Cannot allocate array with negative length" ); +#endif + size = 0; + } + shd = newData(); + CHECK_PTR( shd ); + if ( size == 0 ) // zero length + return; + shd->data = NEW(char,size); + CHECK_PTR( shd->data ); + shd->len = size; +} + +/*! + \internal + Constructs a shallow copy of \e a. +*/ + +QGArray::QGArray( const QGArray &a ) +{ + shd = a.shd; + shd->ref(); +} + +/*! + \internal + 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 ); + } +} + + +/*! + \fn QGArray &QGArray::operator=( const QGArray &a ) + \internal + Assigns a shallow copy of \e a to this array and returns a reference to + this array. Equivalent to assign(). +*/ + +/*! + \fn void QGArray::detach() + \internal + Detaches this array from shared array data. +*/ + +/*! + \fn char *QGArray::data() const + \internal + Returns a pointer to the actual array data. +*/ + +/*! + \fn uint QGArray::nrefs() const + \internal + Returns the reference count. +*/ + +/*! + \fn uint QGArray::size() const + \internal + Returns the size of the array, in bytes. +*/ + + +/*! + \internal + Returns TRUE if this array is equal to \e 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; +} + + +/*! + \internal + Resizes the array to \e 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); + } + CHECK_PTR( shd->data ); + if ( !shd->data ) // no memory + return FALSE; + shd->len = newsize; + return TRUE; +} + +/*! + \internal + Fills the array with the repeated occurrences of \e d, which is + \e sz bytes long. + If \e len is specified as different from -1, then the array will be + resized to \e len*sz before it is filled. + + Returns TRUE if successful, or FALSE if the memory cannot be allocated + (only when \e 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; +} + +/*! + \internal + Shallow copy. Dereference the current array and references the data + contained in \e 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; +} + +/*! + \internal + Shallow copy. Dereference the current array and references the + array data \e d, which contains \e len bytes. + Returns a reference to this array. + + Do not delete \e 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(); + CHECK_PTR( shd ); + } else { + if ( shd->data ) + DELETE(shd->data); + } + shd->data = (char *)d; + shd->len = len; + return *this; +} + +/*! + \internal + Deep copy. Dereference the current array and obtains a copy of the data + contained in \e 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(); + CHECK_PTR( n ); + if ( (n->len=shd->len) ) { + n->data = NEW(char,n->len); + 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(); + 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); + 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; +} + +/*! + \internal + Deep copy. Dereferences the current array and obtains a copy of the + array data \e 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); + CHECK_PTR( data ); + memcpy( data, d, len ); + } + if ( shd->count > 1 ) { // detach + shd->count--; + shd = newData(); + CHECK_PTR( shd ); + } else { // just a single reference + if ( shd->data ) + DELETE(shd->data); + } + shd->data = data; + shd->len = len; + return *this; +} + +/*! + \internal + Resizes this array to \e len bytes and copies the \e len bytes at + address \e 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 + \internal + 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 ) + \internal + Sets the shared array block to \e 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. +*/ + + +/*! + \internal + Sets raw data and returns a reference to the array. + + Dereferences the current array and sets the new array data to \e d and + the new array size to \e 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 set QArray 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; +} + +/*! + \internal + Resets raw data. + + The arguments must be the data and length 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(CHECK_STATE) + qWarning( "QGArray::resetRawData: Inconsistent arguments" ); +#endif + return; + } + shd->data = 0; + shd->len = 0; +} + + +/*! + \internal + Finds the first occurrence of \e d in the array from position \e index, + where \e sz is the size of the \e d element. + + Note that \e index is given in units of \e 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(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; +} + +/*! + \internal + Returns the number of occurrences of \e d in the array, where \e sz is + the size of the \e 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 + +static int cmp_arr( const void *n1, const void *n2 ) +{ + return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) + : (int)((long)n1 - (long)n2); + // Qt 3.0: Add a virtual compareItems() method and call that instead +} + +#if defined(Q_C_CALLBACKS) +} +#endif + +/*! + \internal + + Sort the array. +*/ + +void QGArray::sort( uint sz ) +{ + int numItems = size() / sz; + if ( numItems < 2 ) + return; + cmp_item_size = sz; + qsort( shd->data, numItems, sz, cmp_arr ); +} + +/*! + \internal + + Binary search; assumes sorted array +*/ + +int QGArray::bsearch( const char *d, uint sz ) const +{ + int numItems = size() / sz; + if ( !numItems ) + return -1; + 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 + \internal + Returns a pointer to the byte at offset \e index in the array. +*/ + +/*! + \internal + Expand the array if necessary, and copies (the first part of) its + contents from the \e index*zx bytes at \e 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; +} + + +/*! + \internal + Prints a warning message if at() or [] is given a bad index. +*/ + +void QGArray::msg_index( uint index ) +{ +#if defined(CHECK_RANGE) + qWarning( "QGArray::at: Absolute index %d out of range", index ); +#else + Q_UNUSED( index ) +#endif +} + + +/*! + \internal + Returns a new shared array block. +*/ + +QGArray::array_data * QGArray::newData() +{ + return new array_data; +} + + +/*! + \internal + Deletes the shared array block. +*/ + +void QGArray::deleteData( array_data *p ) +{ + delete p; + p = 0; +} diff --git a/qtools/qgarray.h b/qtools/qgarray.h new file mode 100644 index 0000000..12c463b --- /dev/null +++ b/qtools/qgarray.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** +** 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); } + + 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(CHECK_RANGE) + if ( index >= size() ) { + msg_index( index ); + index = 0; + } +#endif + return &shd->data[index]; +} + + +#endif // QGARRAY_H diff --git a/qtools/qgdict.cpp b/qtools/qgdict.cpp new file mode 100644 index 0000000..c3b2f74 --- /dev/null +++ b/qtools/qgdict.cpp @@ -0,0 +1,1215 @@ +/**************************************************************************** +** +** +** 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 "qlist.h" +#include "qstring.h" +#include "qdatastream.h" +#include <ctype.h> + + +// NOT REVISED +/*! + \class QGDict qgdict.h + \brief The QGDict class is an internal class for implementing QDict template classes. + + 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. + <ul> + <li> read() reads a collection/dictionary item from a QDataStream. + <li> write() writes a collection/dictionary item to a QDataStream. + </ul> + 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 QList<QGDictIterator> +{ +public: + QGDItList() : QList<QGDictIterator>() {} + QGDItList( const QGDItList &list ) : QList<QGDictIterator>(list) {} + ~QGDItList() { clear(); } + QGDItList &operator=(const QGDItList &list) + { return (QGDItList&)QList<QGDictIterator>::operator=(list); } +}; + + +/***************************************************************************** + Default implementation of special and virtual functions + *****************************************************************************/ + +/*! + \internal + Returns the hash key for \e key, when key is a string. +*/ + +int QGDict::hashKeyString( const QString &key ) +{ +#if defined(CHECK_NULL) + if ( key.isNull() ) + qWarning( "QGDict::hashStringKey: 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; +} + +/*! + \internal + Returns the hash key for \a key, which is a C string. +*/ + +int QGDict::hashKeyAscii( const char *key ) +{ +#if defined(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(*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 + +/*! + Reads a collection/dictionary item from the stream \e s and returns a + reference to the stream. + + The default implementation sets \e item to 0. + + \sa write() +*/ + +QDataStream& QGDict::read( QDataStream &s, QCollection::Item &item ) +{ + item = 0; + return s; +} + +/*! + Writes a collection/dictionary item to the stream \e s and returns a + reference to the stream. + + \sa read() +*/ + +QDataStream& QGDict::write( QDataStream &s, QCollection::Item ) const +{ + return s; +} +#endif //QT_NO_DATASTREAM + +/***************************************************************************** + QGDict member functions + *****************************************************************************/ + +/*! + \internal + Constructs a dictionary. +*/ + +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 + 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; + } +} + + +/*! + \internal + Constructs a copy of \e dict. +*/ + +QGDict::QGDict( const QGDict & dict ) + : QCollection( 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; + } +} + + +/*! + \internal + 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; +} + + +/*! + \internal + Assigns \e dict to this dictionary. +*/ + +QGDict &QGDict::operator=( const QGDict &dict ) +{ + 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 QCollection::Item QGDictIterator::get() const + + \internal +*/ + + +/*! \fn QString QGDictIterator::getKeyString() const + + \internal +*/ + + +/*! \fn const char * QGDictIterator::getKeyAscii() const + + \internal +*/ + + +/*! \fn void * QGDictIterator::getKeyPtr() const + + \internal +*/ + + +/*! \fn long QGDictIterator::getKeyInt() const + + \internal +*/ + + +/*! + \fn uint QGDict::count() const + \internal + Returns the number of items in the dictionary. +*/ + +/*! + \fn uint QGDict::size() const + \internal + Returns the size of the hash array. +*/ + + +/*! + \internal + The do-it-all function; op is one of op_find, op_insert, op_replace +*/ + +QCollection::Item QGDict::look_string( const QString &key, QCollection::Item d, int op ) +{ + QStringBucket *n; + int index = hashKeyString(key) % vlen; + if ( op == op_find ) { // find + if ( cases ) { + for ( n=(QStringBucket*)vec[index]; n; + n=(QStringBucket*)n->getNext() ) { + if ( key == n->getKey() ) + return n->getData(); // item found + } + } else { + QString k = key.lower(); + for ( n=(QStringBucket*)vec[index]; n; + n=(QStringBucket*)n->getNext() ) { + if ( k == n->getKey().lower() ) + return n->getData(); // item found + } + } + 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]); + CHECK_PTR( n ); +#if defined(CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! \internal */ + +QCollection::Item QGDict::look_ascii( const char *key, QCollection::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]); + CHECK_PTR( n ); +#if defined(CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QAsciiDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! \internal */ + +QCollection::Item QGDict::look_int( long key, QCollection::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]); + CHECK_PTR( n ); +#if defined(CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QIntDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! \internal */ + +QCollection::Item QGDict::look_ptr( void *key, QCollection::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]); + CHECK_PTR( n ); +#if defined(CHECK_NULL) + if ( n->getData() == 0 ) + qWarning( "QPtrDict: Cannot insert null item" ); +#endif + vec[index] = n; + numItems++; + return n->getData(); +} + + +/*! + \internal + Changes the size of the hashtable. + 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]; + 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(); + } + } +} + +/*! + \internal + 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, QCollection::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, QCollection::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, QCollection::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, QCollection::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; +} + + +/*! + \internal + Removes the item with the specified key. If item is non-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, QCollection::Item item ) +{ + QStringBucket *n = unlink_string( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + return TRUE; + } else { + return FALSE; + } +} + + +/*! \internal */ + +bool QGDict::remove_ascii( const char *key, QCollection::Item item ) +{ + QAsciiBucket *n = unlink_ascii( key, item ); + if ( n ) { + if ( copyk ) + delete [] (char *)n->getKey(); + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + + +/*! \internal */ + +bool QGDict::remove_int( long key, QCollection::Item item ) +{ + QIntBucket *n = unlink_int( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + + +/*! \internal */ + +bool QGDict::remove_ptr( void *key, QCollection::Item item ) +{ + QPtrBucket *n = unlink_ptr( key, item ); + if ( n ) { + deleteItem( n->getData() ); + delete n; + } + return n != 0; +} + + +/*! \internal */ + +QCollection::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; +} + + +/*! \internal */ + +QCollection::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; +} + + +/*! \internal */ + +QCollection::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; +} + + +/*! \internal */ + +QCollection::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; +} + + +/*! + \internal + 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(); + } + } +} + + +/*! + \internal + Outputs debug statistics. +*/ + +void QGDict::statistics() const +{ +#if defined(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 // 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(_CC_DEC_) && defined(__alpha) && (__DECCXX_VER >= 50190001) +#pragma message disable narrowptr +#endif + +/*! + \internal + Reads a dictionary from the stream \e 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; +} + +/*! + \internal + Writes the dictionary to the stream \e 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 + \brief An internal class for implementing QDictIterator and QIntDictIterator. + + QGDictIterator is a strictly internal class that does the heavy work for + QDictIterator and QIntDictIterator. +*/ + +/*! + \internal + Constructs an iterator that operates on the dictionary \e 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 + CHECK_PTR( dict->iterators ); + } + dict->iterators->append( this ); // attach iterator to dict +} + +/*! + \internal + Constructs a copy of the iterator \e 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 +} + +/*! + \internal + Assigns a copy of the iterator \e 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; +} + +/*! + \internal + Destroys the iterator. +*/ + +QGDictIterator::~QGDictIterator() +{ + if ( dict ) // detach iterator from dict + dict->iterators->removeRef( this ); +} + + +/*! + \internal + Sets the iterator to point to the first item in the dictionary. +*/ + +QCollection::Item QGDictIterator::toFirst() +{ + if ( !dict ) { +#if defined(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(); +} + + +/*! + \internal + Moves to the next item (postfix). +*/ + +QCollection::Item QGDictIterator::operator()() +{ + if ( !dict ) { +#if defined(CHECK_NULL) + qWarning( "QGDictIterator::operator(): Dictionary has been deleted" ); +#endif + return 0; + } + if ( !curNode ) + return 0; + QCollection::Item d = curNode->getData(); + this->operator++(); + return d; +} + +/*! + \internal + Moves to the next item (prefix). +*/ + +QCollection::Item QGDictIterator::operator++() +{ + if ( !dict ) { +#if defined(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(); +} + +/*! + \internal + Moves \e jumps positions forward. +*/ + +QCollection::Item QGDictIterator::operator+=( uint jumps ) +{ + while ( curNode && jumps-- ) + operator++(); + return curNode ? curNode->getData() : 0; +} diff --git a/qtools/qgdict.h b/qtools/qgdict.h new file mode 100644 index 0000000..6243364 --- /dev/null +++ b/qtools/qgdict.h @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** +** 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 "qcollection.h" +#include "qstring.h" +#endif // QT_H + +class QGDictIterator; +class QGDItList; + + +class QBaseBucket // internal dict node +{ +public: + QCollection::Item getData() { return data; } + QCollection::Item setData( QCollection::Item d ) { return data = d; } + QBaseBucket *getNext() { return next; } + void setNext( QBaseBucket *n) { next = n; } +protected: + QBaseBucket( QCollection::Item d, QBaseBucket *n ) : data(d), next(n) {} + QCollection::Item data; + QBaseBucket *next; +}; + +class QStringBucket : public QBaseBucket +{ +public: + QStringBucket( const QString &k, QCollection::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, QCollection::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, QCollection::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, QCollection::Item d, QBaseBucket *n ) + : QBaseBucket(d,n), key(k) {} + void *getKey() const { return key; } +private: + void *key; +}; + + +class Q_EXPORT QGDict : public QCollection // generic dictionary class +{ +public: + uint count() const { return numItems; } + uint size() const { return vlen; } + QCollection::Item look_string( const QString& key, QCollection::Item, + int ); + QCollection::Item look_ascii( const char *key, QCollection::Item, int ); + QCollection::Item look_int( long key, QCollection::Item, int ); + QCollection::Item look_ptr( void *key, QCollection::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, QCollection::Item item=0 ); + bool remove_ascii( const char *key, QCollection::Item item=0 ); + bool remove_int( long key, QCollection::Item item=0 ); + bool remove_ptr( void *key, QCollection::Item item=0 ); + QCollection::Item take_string( const QString &key ); + QCollection::Item take_ascii( const char *key ); + QCollection::Item take_int( long key ); + QCollection::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 &, QCollection::Item & ); + virtual QDataStream &write( QDataStream &, QCollection::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 &, + QCollection::Item item = 0 ); + QAsciiBucket *unlink_ascii( const char *, QCollection::Item item = 0 ); + QIntBucket *unlink_int( long, QCollection::Item item = 0 ); + QPtrBucket *unlink_ptr( void *, QCollection::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(); + + QCollection::Item toFirst(); + + QCollection::Item get() const; + QString getKeyString() const; + const char *getKeyAscii() const; + long getKeyInt() const; + void *getKeyPtr() const; + + QCollection::Item operator()(); + QCollection::Item operator++(); + QCollection::Item operator+=(uint); + +protected: + QGDict *dict; + +private: + QBaseBucket *curNode; + uint curIndex; +}; + +inline QCollection::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/qtools/qgeneric.h b/qtools/qgeneric.h new file mode 100644 index 0000000..c2892a0 --- /dev/null +++ b/qtools/qgeneric.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** +** Macros for pasting tokens; utilized by our generic 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 QGENERIC_H +#define QGENERIC_H + +#error "do not include qgeneric.h any more" + +#endif // QGENERIC_H diff --git a/qtools/qglist.cpp b/qtools/qglist.cpp new file mode 100644 index 0000000..f464a73 --- /dev/null +++ b/qtools/qglist.cpp @@ -0,0 +1,1223 @@ +/**************************************************************************** +** +** +** 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" + + +// NOT REVISED +/*! + \class QLNode qglist.h + \brief The QLNode class is an internal class for the QList template collection. + + QLNode is a doubly linked list node; it has three pointers: + <ol> + <li> Pointer to the previous node. + <li> Pointer to the next node. + <li> Pointer to the actual data. + </ol> + + Sometimes it might be practical to have direct access to the list nodes + in a QList, but it is seldom required. + + \warning Be very careful if you want to access the list nodes. The heap + can easily get corrupted if you make a mistake. + + \sa QList::currentNode(), QList::removeNode(), QList::takeNode() +*/ + +/*! + \fn QCollection::Item QLNode::getData() + Returns a pointer (\c void*) to the actual data in the list node. +*/ + + +/*! + \class QGList qglist.h + \brief The QGList class is an internal class for implementing Qt collection classes. + + QGList is a strictly internal class that acts as a base class for several + \link collection.html collection classes\endlink; QList, QQueue and + QStack. + + QGList has some virtual functions that can be reimplemented to customize + the subclasses. + <ul> + <li> compareItems() compares two collection/list items. + <li> read() reads a collection/list item from a QDataStream. + <li> write() writes a collection/list item to a QDataStream. + </ul> + Normally, you do not have to reimplement any of these functions. + If you still want to reimplement them, see the QStrList class (qstrlist.h), + which is a good example. +*/ + + +/***************************************************************************** + Default implementation of virtual functions + *****************************************************************************/ + +/*! + This virtual function compares two list items. + + Returns: + <ul> + <li> 0 if \e item1 == \e item2 + <li> non-zero if \e item1 != \e item2 + </ul> + + This function returns \e int rather than \e bool so that + reimplementations can return three values and use it to sort by: + + <ul> + <li> 0 if \e item1 == \e item2 + <li> \> 0 (positive integer) if \e item1 \> \e item2 + <li> \< 0 (negative integer) if \e item1 \< \e item2 + </ul> + + The QList::inSort() function requires that compareItems() is implemented + as described here. + + This function should not modify the list because some const functions + call compareItems(). + + The default implementation compares the pointers: + \code + + \endcode +*/ + +int QGList::compareItems( QCollection::Item item1, QCollection::Item item2 ) +{ + return item1 != item2; // compare pointers +} + +#ifndef QT_NO_DATASTREAM +/*! + 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, QCollection::Item &item ) +{ + item = 0; + return s; +} + +/*! + 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, QCollection::Item ) const +{ + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QGList member functions + *****************************************************************************/ + +/*! + \internal + Constructs an empty list. +*/ + +QGList::QGList() +{ + firstNode = lastNode = curNode = 0; // initialize list + numNodes = 0; + curIndex = -1; + iterators = 0; // initialize iterator list +} + +/*! + \internal + Constructs a copy of \e list. +*/ + +QGList::QGList( const QGList & list ) + : QCollection( 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; + } +} + +/*! + \internal + Removes all items from the list and destroys the list. +*/ + +QGList::~QGList() +{ + clear(); + if ( !iterators ) // no iterators for this list + return; + QGListIterator *i = (QGListIterator*)iterators->first(); + while ( i ) { // notify all iterators that + i->list = 0; // this list is deleted + i->curNode = 0; + i = (QGListIterator*)iterators->next(); + } + delete iterators; +} + + +/*! + \internal + Assigns \e list to this list. +*/ + +QGList& QGList::operator=( const QGList &list ) +{ + 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. Retruns TRUE if the lists + contain the same data, else 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 + \internal + Returns the number of items in the list. +*/ + + +/*! + \internal + Returns the node at position \e 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(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; +} + + +/*! + \internal + Inserts an item at its sorted position in the list. +*/ + +void QGList::inSort( QCollection::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 ); +} + + +/*! + \internal + Inserts an item at the start of the list. +*/ + +void QGList::prepend( QCollection::Item d ) +{ + register QLNode *n = new QLNode( newItem(d) ); + 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; +} + + +/*! + \internal + Inserts an item at the end of the list. +*/ + +void QGList::append( QCollection::Item d ) +{ + register QLNode *n = new QLNode( newItem(d) ); + 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++; +} + + +/*! + \internal + Inserts an item at position \e index in the list. +*/ + +bool QGList::insertAt( uint index, QCollection::Item d ) +{ + if ( index == 0 ) { // insert at head of list + prepend( d ); + return TRUE; + } else if ( index == numNodes ) { // append at tail of list + append( d ); + return TRUE; + } + QLNode *nextNode = locate( index ); + if ( !nextNode ) // illegal position + return FALSE; + QLNode *prevNode = nextNode->prev; + register QLNode *n = new QLNode( newItem(d) ); + 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; +} + + +/*! + \internal + Relinks node \e 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; +} + + +/*! + \internal + 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->count() ) { // update iterators + QGListIterator *i = (QGListIterator*)iterators->first(); + while ( i ) { // fix all iterators that + if ( i->curNode == n ) // refers to pending node + i->curNode = curNode; + i = (QGListIterator*)iterators->next(); + } + } + numNodes--; + return n; +} + + +/*! + \internal + Removes the node \e n from the list. +*/ + +bool QGList::removeNode( QLNode *n ) +{ +#if defined(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; +} + +/*! + \internal + Removes the item \e d from the list. Uses compareItems() to find the item. +*/ + +bool QGList::remove( QCollection::Item d ) +{ + if ( d ) { // find the item + if ( find(d) == -1 ) + return FALSE; + } + QLNode *n = unlink(); // unlink node + if ( !n ) + return FALSE; + deleteItem( n->data ); // deallocate this node + delete n; + return TRUE; +} + +/*! + \internal + Removes the item \e d from the list. +*/ + +bool QGList::removeRef( QCollection::Item d ) +{ + if ( d ) { // find the item + if ( findRef(d) == -1 ) + return FALSE; + } + QLNode *n = unlink(); // unlink node + if ( !n ) + return FALSE; + deleteItem( n->data ); // deallocate this node + delete n; + return TRUE; +} + +/*! + \fn bool QGList::removeFirst() + \internal + Removes the first item in the list. +*/ + +/*! + \fn bool QGList::removeLast() + \internal + Removes the last item in the list. +*/ + +/*! + \internal + Removes the item at position \e index from the list. +*/ + +bool QGList::removeAt( uint index ) +{ + if ( !locate(index) ) + return FALSE; + QLNode *n = unlink(); // unlink node + if ( !n ) + return FALSE; + deleteItem( n->data ); // deallocate this node + delete n; + return TRUE; +} + + +/*! + \internal + Takes the node \e n out of the list. +*/ + +QCollection::Item QGList::takeNode( QLNode *n ) +{ +#if defined(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; +} + +/*! + \internal + Takes the current item out of the list. +*/ + +QCollection::Item QGList::take() +{ + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; // delete node, keep contents + return d; +} + +/*! + \internal + Takes the item at position \e index out of the list. +*/ + +QCollection::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; +} + +/*! + \internal + Takes the first item out of the list. +*/ + +QCollection::Item QGList::takeFirst() +{ + first(); + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; + return d; +} + +/*! + \internal + Takes the last item out of the list. +*/ + +QCollection::Item QGList::takeLast() +{ + last(); + QLNode *n = unlink(); // unlink node + Item d = n ? n->data : 0; + delete n; + return d; +} + + +/*! + \internal + 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->count() ) { + QGListIterator *i = (QGListIterator*)iterators->first(); + while ( i ) { // notify all iterators that + i->curNode = 0; // this list is empty + i = (QGListIterator*)iterators->next(); + } + } + + QLNode *prevNode; + while ( n ) { // for all nodes ... + deleteItem( n->data ); // deallocate data + prevNode = n; + n = n->next; + delete prevNode; // deallocate node + } +} + + +/*! + \internal + Finds an item in the list. +*/ + +int QGList::findRef( QCollection::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 +} + +/*! + \internal + Finds an item in the list. Uses compareItems(). +*/ + +int QGList::find( QCollection::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 +} + + +/*! + \internal + Counts the number an item occurs in the list. +*/ + +uint QGList::containsRef( QCollection::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; +} + +/*! + \internal + Counts the number an item occurs in the list. Uses compareItems(). +*/ + +uint QGList::contains( QCollection::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; +} + + +/*! + \fn QCollection::Item QGList::at( uint index ) + \internal + Sets the item at position \e index to the current item. +*/ + +/*! + \fn int QGList::at() const + \internal + Returns the current index. +*/ + +/*! + \fn QLNode *QGList::currentNode() const + \internal + Returns the current node. +*/ + +/*! + \fn QCollection::Item QGList::get() const + \internal + Returns the current item. +*/ + +/*! + \fn QCollection::Item QGList::cfirst() const + \internal + Returns the first item in the list. +*/ + +/*! + \fn QCollection::Item QGList::clast() const + \internal + Returns the last item in the list. +*/ + + +/*! + \internal + Returns the first list item. Sets this to current. +*/ + +QCollection::Item QGList::first() +{ + if ( firstNode ) { + curIndex = 0; + return (curNode=firstNode)->data; + } + return 0; +} + +/*! + \internal + Returns the last list item. Sets this to current. +*/ + +QCollection::Item QGList::last() +{ + if ( lastNode ) { + curIndex = numNodes-1; + return (curNode=lastNode)->data; + } + return 0; +} + +/*! + \internal + Returns the next list item (after current). Sets this to current. +*/ + +QCollection::Item QGList::next() +{ + if ( curNode ) { + if ( curNode->next ) { + curIndex++; + curNode = curNode->next; + return curNode->data; + } + curIndex = -1; + curNode = 0; + } + return 0; +} + +/*! + \internal + Returns the previous list item (before current). Sets this to current. +*/ + +QCollection::Item QGList::prev() +{ + if ( curNode ) { + if ( curNode->prev ) { + curIndex--; + curNode = curNode->prev; + return curNode->data; + } + curIndex = -1; + curNode = 0; + } + return 0; +} + + +/*! + \internal + Converts the list to 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( QCollection::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 ) { + QCollection::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 + QCollection::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 + QCollection::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 + QCollection::Item* realheap = new QCollection::Item[ n ]; + // Wow, what a fake. But I want the heap to be indexed as 1...n + QCollection::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 ) { + QCollection::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 ); +} + +/*! + \internal + Reads a list from the stream \e 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 ); + CHECK_PTR( d ); + if ( !d ) // no memory + break; + QLNode *n = new QLNode( d ); + 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; +} + +/*! + \internal + Writes the list to the stream \e 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 + \brief The QGListIterator class is an internal class for implementing QListIterator. + + QGListIterator is a strictly internal class that does the heavy work for + QListIterator. +*/ + +/*! + \internal + Constructs an iterator that operates on the list \e 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 QGList; // create iterator list + CHECK_PTR( list->iterators ); + } + list->iterators->append( this ); // attach iterator to list +} + +/*! + \internal + Constructs a copy of the iterator \e it. +*/ + +QGListIterator::QGListIterator( const QGListIterator &it ) +{ + list = it.list; + curNode = it.curNode; + if ( list ) + list->iterators->append( this ); // attach iterator to list +} + +/*! + \internal + Assigns a copy of the iterator \e it and returns a reference to this + iterator. +*/ + +QGListIterator &QGListIterator::operator=( const QGListIterator &it ) +{ + if ( list ) // detach from old list + list->iterators->removeRef( this ); + list = it.list; + curNode = it.curNode; + if ( list ) + list->iterators->append( this ); // attach to new list + return *this; +} + +/*! + \internal + Destroys the iterator. +*/ + +QGListIterator::~QGListIterator() +{ + if ( list ) // detach iterator from list + list->iterators->removeRef(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. +*/ + +QCollection::Item QGListIterator::toFirst() +{ + if ( !list ) { +#if defined(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. +*/ + +QCollection::Item QGListIterator::toLast() +{ + if ( !list ) { +#if defined(CHECK_NULL) + qWarning( "QGListIterator::toLast: List has been deleted" ); +#endif + return 0; + } + return list->lastNode ? (curNode = list->lastNode)->getData() : 0; +} + + +/*! + \fn QCollection::Item QGListIterator::get() const + \internal + Returns the iterator item. +*/ + + +/*! + \internal + Moves to the next item (postfix). +*/ + +QCollection::Item QGListIterator::operator()() +{ + if ( !curNode ) + return 0; + QCollection::Item d = curNode->getData(); + curNode = curNode->next; + return d; +} + +/*! + \internal + Moves to the next item (prefix). +*/ + +QCollection::Item QGListIterator::operator++() +{ + if ( !curNode ) + return 0; + curNode = curNode->next; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves \e jumps positions forward. +*/ + +QCollection::Item QGListIterator::operator+=( uint jumps ) +{ + while ( curNode && jumps-- ) + curNode = curNode->next; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves to the previous item (prefix). +*/ + +QCollection::Item QGListIterator::operator--() +{ + if ( !curNode ) + return 0; + curNode = curNode->prev; + return curNode ? curNode->getData() : 0; +} + +/*! + \internal + Moves \e jumps positions backward. +*/ + +QCollection::Item QGListIterator::operator-=( uint jumps ) +{ + while ( curNode && jumps-- ) + curNode = curNode->prev; + return curNode ? curNode->getData() : 0; +} diff --git a/qtools/qglist.h b/qtools/qglist.h new file mode 100644 index 0000000..f400b64 --- /dev/null +++ b/qtools/qglist.h @@ -0,0 +1,257 @@ +/**************************************************************************** +** +** +** 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 "qcollection.h" +#endif // QT_H + + +/***************************************************************************** + QLNode class (internal doubly linked list node) + *****************************************************************************/ + +class Q_EXPORT QLNode +{ +friend class QGList; +friend class QGListIterator; +public: + QCollection::Item getData() { return data; } +private: + QCollection::Item data; + QLNode *prev; + QLNode *next; + QLNode( QCollection::Item d ) { data = d; } +}; + + +/***************************************************************************** + QGList class + *****************************************************************************/ + +class Q_EXPORT QGList : public QCollection // doubly linked generic list +{ +friend class QGListIterator; +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( QCollection::Item ); // add item sorted in list + void append( QCollection::Item ); // add item at end of list + bool insertAt( uint index, QCollection::Item ); // add item at i'th position + void relinkNode( QLNode * ); // relink as first item + bool removeNode( QLNode * ); // remove node + bool remove( QCollection::Item = 0 ); // remove item (0=current) + bool removeRef( QCollection::Item = 0 ); // remove item (0=current) + bool removeFirst(); // remove first item + bool removeLast(); // remove last item + bool removeAt( uint index ); // remove item at i'th position + QCollection::Item takeNode( QLNode * ); // take out node + QCollection::Item take(); // take out current item + QCollection::Item takeAt( uint index ); // take out item at i'th pos + QCollection::Item takeFirst(); // take out first item + QCollection::Item takeLast(); // take out last item + + void sort(); // sort all items; + void clear(); // remove all items + + int findRef( QCollection::Item, bool = TRUE ); // find exact item in list + int find( QCollection::Item, bool = TRUE ); // find equal item in list + + uint containsRef( QCollection::Item ) const; // get number of exact matches + uint contains( QCollection::Item ) const; // get number of equal matches + + QCollection::Item at( uint index ); // access item at i'th pos + int at() const; // get current index + QLNode *currentNode() const; // get current node + + QCollection::Item get() const; // get current item + + QCollection::Item cfirst() const; // get ptr to first list item + QCollection::Item clast() const; // get ptr to last list item + QCollection::Item first(); // set first item in list curr + QCollection::Item last(); // set last item in list curr + QCollection::Item next(); // set next item in list curr + QCollection::Item prev(); // set prev item in list curr + + void toVector( QGVector * ) const; // put items in vector + + virtual int compareItems( QCollection::Item, QCollection::Item ); + +#ifndef QT_NO_DATASTREAM + virtual QDataStream &read( QDataStream &, QCollection::Item & ); + virtual QDataStream &write( QDataStream &, QCollection::Item ) const; +#endif +private: + void prepend( QCollection::Item ); // add item at start of list + + void heapSortPushDown( QCollection::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 + QGList *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 QCollection::Item QGList::at( uint index ) +{ + QLNode *n = locate( index ); + return n ? n->data : 0; +} + +inline QLNode *QGList::currentNode() const +{ + return curNode; +} + +inline QCollection::Item QGList::get() const +{ + return curNode ? curNode->data : 0; +} + +inline QCollection::Item QGList::cfirst() const +{ + return firstNode ? firstNode->data : 0; +} + +inline QCollection::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; +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 + QCollection::Item toFirst(); // move to first item + QCollection::Item toLast(); // move to last item + + QCollection::Item get() const; // get current item + QCollection::Item operator()(); // get current and move to next + QCollection::Item operator++(); // move to next item (prefix) + QCollection::Item operator+=(uint); // move n positions forward + QCollection::Item operator--(); // move to prev item (prefix) + QCollection::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 QCollection::Item QGListIterator::get() const +{ + return curNode ? curNode->data : 0; +} + + +#endif // QGLIST_H diff --git a/qtools/qglobal.cpp b/qtools/qglobal.cpp new file mode 100644 index 0000000..2789e30 --- /dev/null +++ b/qtools/qglobal.cpp @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** +** Global functions +** +** Created : 920604 +** +** 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" +#include "qasciidict.h" +#include "qstring.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> + +// NOT REVISED + +/*! + \relates QApplication + Returns the Qt version number for the library, typically "1.30" + or "2.1.0". +*/ + +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 \e *wordSize. + The \e *bigEndian is set to TRUE if this is a big-endian machine, + or to FALSE if this is a little-endian machine. + + This function calls qFatal() with a message if the computer is truly weird + (i.e. different endianness for 16 bit and 32 bit integers). +*/ + +bool qSysInfo( int *wordSize, bool *bigEndian ) +{ +#if defined(CHECK_NULL) + ASSERT( wordSize != 0 ); + ASSERT( bigEndian != 0 ); +#endif + + if ( si_alreadyDone ) { // run it only once + *wordSize = si_wordSize; + *bigEndian = si_bigEndian; + return TRUE; + } + si_alreadyDone = TRUE; + + si_wordSize = 0; + uint n = (uint)(~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(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(float) != 4 || sizeof(double) != 8 ) { +#if defined(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(CHECK_RANGE) + qFatal( "qSysInfo: Inconsistent system byte order" ); +#endif + return FALSE; + } + + *bigEndian = si_bigEndian = be32; + return TRUE; +} + + +/***************************************************************************** + Debug output routines + *****************************************************************************/ + +/*! + \fn void qDebug( const char *msg, ... ) + + \relates QApplication + Prints a debug message, 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). + + \sa qWarning(), qFatal(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + +/*! + \fn void qWarning( const char *msg, ... ) + + \relates QApplication + Prints a warning message, 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). + + \sa qDebug(), qFatal(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + +/*! + \fn void qFatal( const char *msg, ... ) + + \relates QApplication + Prints a fatal error message 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). + + \sa qDebug(), qWarning(), qInstallMsgHandler(), + \link debug.html Debugging\endlink +*/ + + +static msg_handler handler = 0; // pointer to debug handler + + +#ifdef _OS_MAC_ + +static FILE * mac_debug=0; + +void qDebug( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+" ); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } else { + exit(0); + } +} + +// copied... this looks really bad. +void debug( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+" ); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } +} + +void qWarning( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+" ); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } +} + +// copied... this looks really bad. +void warning( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+" ); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } +} + +void qFatal( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+"); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } + exit(0); +} + +// copied... this looks really bad. +void fatal( const char *msg, ... ) +{ + mac_debug=fopen( "debug.txt", "a+" ); + if(mac_debug) { + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( mac_debug, msg, ap ); + va_end( ap ); + fprintf( mac_debug, "\n" ); // add newline + fflush( mac_debug ); + } + fclose(mac_debug); + } + exit(0); +} + +#else + +void qDebug( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); // ### vsnprintf would be great here + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline + } +} + +// copied... this looks really bad. +void debug( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtDebugMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline + } +} + +void qWarning( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtWarningMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline + } +} + + +// again, copied +void warning( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtWarningMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline + } +} + +void qFatal( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtFatalMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#if defined(_OS_UNIX_) && defined(DEBUG) + abort(); // trap; generates core dump +#else + exit( 1 ); // goodbye cruel world +#endif + } +} + +// yet again, copied +void fatal( const char *msg, ... ) +{ + char buf[8196]; + va_list ap; + va_start( ap, msg ); // use variable arg list + if ( handler ) { + vsprintf( buf, msg, ap ); + va_end( ap ); + (*handler)( QtFatalMsg, buf ); + } else { + vfprintf( stderr, msg, ap ); + va_end( ap ); + fprintf( stderr, "\n" ); // add newline +#if defined(_OS_UNIX_) && defined(DEBUG) + abort(); // trap; generates core dump +#else + exit( 1 ); // goodbye cruel world +#endif + } +} + +#endif + + +/*! + \fn void ASSERT( bool test ) + \relates QApplication + Prints a warning message containing the source code file name and line number + if \e test is FALSE. + + This is really a macro defined in qglobal.h. + + ASSERT is useful for testing required conditions in your program. + + Example: + \code + // + // File: div.cpp + // + + #include <qglobal.h> + + int divide( int a, int b ) + { + ASSERT( b != 0 ); // this is line 9 + return a/b; + } + \endcode + + If \c b is zero, the 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 CHECK_PTR( void *p ) + \relates QApplication + If \e 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 qglobal.h. + + Example: + \code + int *a; + CHECK_PTR( a = new int[80] ); // never do this! + // do this instead: + a = new int[80]; + CHECK_PTR( a ); // this is fine + \endcode + + \sa qFatal(), \link debug.html Debugging\endlink +*/ + + +// +// The CHECK_PTR macro calls this function to check if an allocation went ok. +// + +bool qt_check_pointer( bool c, const char *n, int l ) +{ + if ( c ) + qFatal( "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(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; + qDebug( "%s::%s: This function is obsolete, use %s instead", + obj, oldfunc, newfunc ); +} + +void qObsolete( const char *obj, const char *oldfunc ) +{ + if ( suppressObsolete ) + return; + if ( !firstObsoleteWarning(obj, oldfunc) ) + return; + qDebug( "%s::%s: This function is obsolete.", obj, oldfunc ); +} + +void qObsolete( const char *message ) +{ + if ( suppressObsolete ) + return; + if ( !firstObsoleteWarning( "Qt", message) ) + return; + qDebug( "%s", message ); +} + + +/*! + \relates QApplication + Installs a Qt message handler. 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(); // dump core on purpose + } + } + + 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 +*/ + +msg_handler qInstallMsgHandler( msg_handler h ) +{ + msg_handler old = handler; + handler = h; + return old; +} + + +#ifdef _WS_WIN_ +bool qt_winunicode=FALSE; +#endif diff --git a/qtools/qglobal.h b/qtools/qglobal.h new file mode 100644 index 0000000..314043a --- /dev/null +++ b/qtools/qglobal.h @@ -0,0 +1,592 @@ +/**************************************************************************** +** +** +** Global type declarations and definitions +** +** 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 QGLOBAL_H +#define QGLOBAL_H + + +#define QT_VERSION 220 +#define QT_VERSION_STR "2.2.0" + + +// +// The operating system, must be one of: (_OS_x_) +// +// MAC - Macintosh +// MSDOS - MS-DOS and Windows +// OS2 - OS/2 +// OS2EMX - XFree86 on OS/2 (not PM) +// WIN32 - Win32 (Windows 95/98 and Windows NT) +// SUN - SunOS +// SOLARIS - Sun Solaris +// HPUX - HP-UX +// ULTRIX - DEC Ultrix +// LINUX - Linux +// FREEBSD - FreeBSD +// NETBSD - NetBSD +// OPENBSD - OpenBSD +// IRIX - SGI Irix +// OSF - OSF Unix +// BSDI - BSDI Unix +// SCO - SCO of some sort +// AIX - AIX Unix +// UNIXWARE - SCO UnixWare +// GNU - GNU Hurd +// DGUX - DG Unix +// UNIX - Any UNIX bsd/sysv system +// + +#if defined(macintosh) +#define _OS_MAC_ +#elif defined(MSDOS) || defined(_MSDOS) || defined(__MSDOS__) +#define _OS_MSDOS_ +#elif defined(OS2) || defined(_OS2) || defined(__OS2__) +#if defined(__EMX__) +#define _OS_OS2EMX_ +#else +#define _OS_OS2_ +#endif +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#define _OS_WIN32_ +#elif defined(__MWERKS__) && defined(__INTEL__) +#define _OS_WIN32_ +#elif defined(sun) || defined(__sun) || defined(__sun__) +#if defined(__SVR4) +#define _OS_SOLARIS_ +#else +#define _OS_SUN_ +#endif +#elif defined(hpux) || defined(__hpux) || defined(__hpux__) +#define _OS_HPUX_ +#elif defined(ultrix) || defined(__ultrix) || defined(__ultrix__) +#define _OS_ULTRIX_ +#elif defined(reliantunix) +#define _OS_RELIANTUNIX_ +#elif defined(linux) || defined(__linux) || defined(__linux__) +#define _OS_LINUX_ +#if defined(__alpha__) || defined(__alpha) +#define _OS_ALPHA_LINUX_ +#endif +#elif defined(__FreeBSD__) +#define _OS_FREEBSD_ +#elif defined(__NetBSD__) +#define _OS_NETBSD_ +#elif defined(__OpenBSD__) +#define _OS_OPENBSD_ +#elif defined(sgi) || defined(__sgi) +#define _OS_IRIX_ +#elif defined(__osf__) +#define _OS_OSF_ +#elif defined(bsdi) || defined(__bsdi__) +#define _OS_BSDI_ +#elif defined(_AIX) +#define _OS_AIX_ +#elif defined(__Lynx__) +#define _OS_LYNXOS_ +#elif defined(_UNIXWARE) +#define _OS_UNIXWARE_ +#elif defined(__GNU__) +#define _OS_GNU_ +#elif defined(DGUX) +#define _OS_DGUX_ +#elif defined(__QNX__) +#define _OS_QNX_ +#elif defined(_SCO_DS) || defined(M_UNIX) || defined(M_XENIX) +#define _OS_SCO_ +#elif defined(sco) || defined(_UNIXWARE7) +#define _OS_UNIXWARE7_ +#elif !defined(_SCO_DS) && defined(__USLC__) && defined(__SCO_VERSION__) +#define _OS_UNIXWARE7_ +#else +#error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" +#endif + +#if defined(_OS_MAC_) || defined(_OS_MSDOS_) || defined(_OS_OS2_) || defined(_OS_WIN32_) +#undef _OS_UNIX_ +#elif !defined(_OS_UNIX_) +#define _OS_UNIX_ +// QT_CLEAN_NAMESPACE is not defined by default; it would break too +// much code. +#if !defined(QT_CLEAN_NAMESPACE) && !defined(UNIX) +// ### remove 3.0 +#define UNIX +#endif +#endif + + +// +// The compiler, must be one of: (_CC_x_) +// +// SYM - Symantec C++ for both PC and Macintosh +// MPW - MPW C++ +// MWERKS - Metroworks 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 ObjectCenter C++ +// SUN - Sun C++ +// DEC - DEC C++ +// HP - HPUX C++ +// USLC - SCO UnixWare C++ +// KAI - KAI C++ +// + + +// Should be sorted most-authorative to least-authorative + +#if defined(__SC__) +#define _CC_SYM_ +#elif defined( __KCC ) +#define _CC_KAI_ +#define Q_HAS_BOOL_TYPE +#elif defined(applec) +#define _CC_MPW_ +#elif defined(__MWERKS__) +#define _CC_MWERKS_ +#define Q_HAS_BOOL_TYPE +#elif defined(_MSC_VER) +#define _CC_MSVC_ +#elif defined(__BORLANDC__) || defined(__TURBOC__) +#define _CC_BOR_ +#elif defined(__WATCOMC__) +#define _CC_WAT_ +#define Q_HAS_BOOL_TYPE +#elif defined(__GNUC__) +#define _CC_GNU_ +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 7 +#define Q_FULL_TEMPLATE_INSTANTIATION +#define Q_TEMPLATE_NEEDS_CLASS_DECLARATION +#define Q_TEMPLATE_NEEDS_EXPLICIT_CONVERSION +#define Q_SPURIOUS_NON_VOID_WARNING +#endif +#if __GNUC__ == 2 && __GNUC_MINOR__ >= 96 +#define Q_DELETING_VOID_UNDEFINED +#define Q_FP_CCAST_BROKEN +#endif +#if (defined(__arm__) || defined(__ARMEL__)) && !defined(QT_MOC_CPP) +#define Q_PACKED __attribute__ ((packed)) +#endif +#elif defined(__xlC__) +#define _CC_XLC_ +#define Q_FULL_TEMPLATE_INSTANTIATION +#elif defined(como40) +#define _CC_EDG_ +#define _CC_COMEAU_ +#elif defined(__USLC__) +#define _CC_USLC_ +#ifdef __EDG__ // UnixWare7 +#define Q_HAS_BOOL_TYPE +#endif +#elif defined(__EDG) || defined(__EDG__) +// one observed on SGI DCC, the other documented +#define Q_HAS_BOOL_TYPE +#define _CC_EDG_ +#elif defined(OBJECTCENTER) || defined(CENTERLINE_CLPP) +#define _CC_OC_ +#elif defined(__SUNPRO_CC) +#define _CC_SUN_ +#if __SUNPRO_CC >= 0x500 +#define Q_HAS_BOOL_TYPE +#define Q_SPARCWORKS_FUNCP_BUG +#define Q_C_CALLBACKS +#endif +#elif defined(__DECCXX) +#define _CC_DEC_ +#elif defined(__CDS__) +#define _CC_CDS_ +#define Q_HAS_BOOL_TYPE +#elif defined(_OS_HPUX_) +// this test is from aCC online help +#if defined(__HP_aCC) || __cplusplus >= 199707L +// this is the aCC +#define _CC_HP_ACC_ +#define Q_HAS_BOOL_TYPE +#else +// this is the CC +#define _CC_HP_ +#define Q_FULL_TEMPLATE_INSTANTIATION +#define Q_TEMPLATE_NEEDS_EXPLICIT_CONVERSION +#endif // __HP_aCC +#else +#error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com" +#endif + +#if defined(_CC_COMEAU_) +#define Q_C_CALLBACKS +#endif + +#ifndef Q_PACKED +#define Q_PACKED +#endif + +// Window system setting + +#if defined(_OS_MAC_) +#define _WS_MAC_ +#elif defined(_OS_MSDOS_) +#define _WS_WIN16_ +#error "Qt requires Win32 and does not work with Windows 3.x" +#elif defined(_WIN32_X11_) +#define _WS_X11_ +#elif defined(_OS_WIN32_) +#define _WS_WIN32_ +#elif defined(_OS_OS2_) +#error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" +#elif defined(_OS_UNIX_) +#ifdef QWS +#define _WS_QWS_ +#else +#define _WS_X11_ +#endif +#endif + +#if defined(_WS_WIN16_) || defined(_WS_WIN32_) +#define _WS_WIN_ +#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 + + +// +// Useful type definitions for Qt +// + +#if defined(bool) +#define Q_HAS_BOOL_TYPE +#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6) +#define Q_HAS_BOOL_TYPE +#elif _MSC_VER >= 1100 || __BORLANDC__ >= 0x500 +#define Q_HAS_BOOL_TYPE +#elif defined(_CC_COMEAU_) +#define Q_HAS_BOOL_TYPE +#elif defined(sgi) && ( (_COMPILER_VERSION >= 710) || defined(_BOOL) ) +#define Q_HAS_BOOL_TYPE +#elif defined(__DECCXX) && (__DECCXX_VER >= 60060005) +#define Q_HAS_BOOL_TYPE +#elif defined(_AIX) && (__xlC__ >= 0x500) +#define Q_HAS_BOOL_TYPE +#endif + +#if (QT_VERSION >= 300) +#error "Use an enum for bool" +#endif + +#if !defined(Q_HAS_BOOL_TYPE) +#if defined(_CC_MSVC_) +#define _CC_BOOL_DEF_ +#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(_CC_MSVC_) +// Workaround for static const members. +#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) ((a) > (b) ? (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-0.5); +} + + +// +// Size-dependent types (architechture-dependent byte order) +// + +// QT_CLEAN_NAMESPACE is not defined by default; it would break too +// much code. +#if !defined(QT_CLEAN_NAMESPACE) +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 +typedef long Q_INT64; // up to 64 bit signed +typedef unsigned long Q_UINT64; // up to 64 bit unsigned + +// +// Data stream functions is provided by many classes (defined in qdatastream.h) +// + +class QDataStream; + + + +#ifdef _WS_WIN_ +extern bool qt_winunicode; +#endif + +#ifndef QT_H +#include <qfeatures.h> +#endif // QT_H + +// +// Create Qt DLL if QT_DLL is defined (Windows only) +// + +#if defined(_OS_WIN32_) +#if defined(QT_NODLL) +#undef QT_MAKEDLL +#undef QT_DLL +#endif +#ifdef QT_DLL +#if defined(QT_MAKEDLL) /* create a Qt DLL library */ +#undef QT_DLL +#define Q_EXPORT __declspec(dllexport) +#define Q_TEMPLATEDLL +#undef Q_DISABLE_COPY /* avoid unresolved externals */ +#endif +#endif +#if defined(QT_DLL) /* use a Qt DLL library */ +#define Q_EXPORT __declspec(dllimport) +#define Q_TEMPLATEDLL +#undef Q_DISABLE_COPY /* avoid unresolved externals */ +#endif +#else // ! _OS_WIN32_ +#undef QT_MAKEDLL /* ignore these for other platforms */ +#undef QT_DLL +#endif + +#ifndef Q_EXPORT +#define Q_EXPORT +#endif + +// +// System information +// + +Q_EXPORT const char *qVersion(); +Q_EXPORT bool qSysInfo( int *wordSize, bool *bigEndian ); + + +// +// Debugging and error handling +// + +#if !defined(NO_CHECK) +#define CHECK_STATE // check state of objects etc. +#define CHECK_RANGE // check range of indexes etc. +#define CHECK_NULL // check null pointers +#define CHECK_MATH // check math functions +#endif + +#if !defined(NO_DEBUG) && !defined(DEBUG) +#define DEBUG // display debug messages +#endif + +// +// Avoid some particularly useless warnings from some stupid compilers. +// To get ALL C++ compiler warnings, define CC_WARNINGS or comment out +// the line "#define Q_NO_WARNINGS" +// + +#if !defined(CC_WARNINGS) +#define Q_NO_WARNINGS +#endif +#if defined(Q_NO_WARNINGS) +#if defined(_CC_MSVC_) +#pragma warning(disable: 4244) +#pragma warning(disable: 4275) +#pragma warning(disable: 4514) +#pragma warning(disable: 4800) +#elif defined(_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(_CC_MWERKS_) +#pragma warn_possunwant off +#endif +#endif // Q_NO_WARNINGS + +// +// Avoid dead code +// + +#if defined(_CC_EDG_) || defined(_CC_WAT_) +#define Q_NO_DEAD_CODE +#endif + +// +// Use to avoid "unused parameter" warnings +// + +#define Q_UNUSED(x) x=x; +#define Q_CONST_UNUSED(x) (void)x; + +Q_EXPORT void qDebug( const char *, ... ) // print debug message +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void qWarning( const char *, ... ) // print warning message +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void qFatal( const char *, ... ) // print fatal message and exit +#if defined(_CC_GNU_) + __attribute__ ((format (printf, 1, 2))) +#endif +; + + +// QT_CLEAN_NAMESPACE is not defined by default; it would break too +// much code. +#if !defined(QT_CLEAN_NAMESPACE) +// in that case, also define the old ones... + +Q_EXPORT void debug( const char *, ... ) // print debug message +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void warning( const char *, ... ) // print warning message +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +Q_EXPORT void fatal( const char *, ... ) // print fatal message and exit +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 1, 2))) +#endif +; + +// okay, that was debug()/warning()/fatal() +#endif + +#if !defined(ASSERT) +#if defined(CHECK_STATE) +#if defined(QT_FATAL_ASSERT) +#define ASSERT(x) if ( !(x) )\ + qFatal("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__) +#else +#define ASSERT(x) if ( !(x) )\ + qWarning("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__) +#endif +#else +#define ASSERT(x) +#endif +#endif + +Q_EXPORT bool qt_check_pointer( bool c, const char *, int ); + +#if defined(CHECK_NULL) +#define CHECK_PTR(p) (qt_check_pointer((p)==0,__FILE__,__LINE__)) +#else +#define CHECK_PTR(p) +#endif + +enum QtMsgType { QtDebugMsg, QtWarningMsg, QtFatalMsg }; + +typedef void (*msg_handler)(QtMsgType, const char *); +Q_EXPORT msg_handler qInstallMsgHandler( msg_handler ); + + +Q_EXPORT void qSuppressObsoleteWarnings( bool = TRUE ); + +#if !defined(QT_REJECT_OBSOLETE) +#define QT_OBSOLETE +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 ); +#endif + +#endif // QGLOBAL_H diff --git a/qtools/qgvector.cpp b/qtools/qgvector.cpp new file mode 100644 index 0000000..88409ce --- /dev/null +++ b/qtools/qgvector.cpp @@ -0,0 +1,638 @@ +/**************************************************************************** +** +** +** 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> + +#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 + +// NOT REVISED + +/*! + \class QGVector qgvector.h + + \brief The QGVector class is an internal class for implementing Qt + collection classes. + + QGVector is a strictly internal class that acts as a base class for + the QVector collection class. + + QGVector has some virtual functions that may be reimplemented in + subclasses to to customize behavior. + + <ul> + <li> compareItems() compares two collection/vector items. + <li> read() reads a collection/vector item from a QDataStream. + <li> write() writes a collection/vector item to a QDataStream. + </ul> +*/ + +/***************************************************************************** + Default implementation of virtual functions + *****************************************************************************/ + +/*! + This virtual function compares two list items. + + Returns: + <ul> + <li> 0 if \a item1 == \a item2 + <li> non-zero if \a item1 != \a item2 + </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 \e item1 == \e item2 + <li> \> 0 (positive integer) if \a item1 \> \a item2 + <li> \< 0 (negative integer) if \a item1 \< \a item2 + </ul> + + The QVector::sort() and QVector::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 \e item 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 + *****************************************************************************/ + +/*! + \internal +*/ + +QGVector::QGVector() // create empty vector +{ + vec = 0; + len = numItems = 0; +} + +/*! + \internal +*/ +QGVector::QGVector( uint size ) // create vectors with nullptrs +{ + len = size; + numItems = 0; + if ( len == 0 ) { // zero length + vec = 0; + return; + } + vec = NEW(Item,len); + CHECK_PTR( vec ); + memset( (void*)vec, 0, len*sizeof(Item) ); // fill with nulls +} + +/*! + \internal +*/ + +QGVector::QGVector( const QGVector &a ) // make copy of other vector + : QCollection( a ) +{ + len = a.len; + numItems = a.numItems; + vec = NEW(Item,len); + CHECK_PTR( vec ); + for ( uint i=0; i<len; i++ ) { + vec[i] = a.vec[i] ? newItem( a.vec[i] ) : 0; + CHECK_PTR( vec[i] ); + } +} + +/*! + \internal +*/ + +QGVector::~QGVector() +{ + clear(); +} + + +/*! + \internal +*/ + +QGVector& QGVector::operator=( const QGVector &v ) +{ // assign from other vector + clear(); // first delete old vector + len = v.len; + numItems = v.numItems; + vec = NEW(Item,len); // create new vector + CHECK_PTR( vec ); + for ( uint i=0; i<len; i++ ) { // copy elements + vec[i] = v.vec[i] ? newItem( v.vec[i] ) : 0; + CHECK_PTR( vec[i] ); + } + return *this; +} + + +/*! + \fn Item *QGVector::data() const + \internal +*/ + +/*! + \fn uint QGVector::size() const + \internal +*/ + +/*! + \fn uint QGVector::count() const + \internal +*/ + +/*! + \fn Item QGVector::at( uint index ) const + \internal +*/ + +/*! + \internal +*/ + +bool QGVector::insert( uint index, Item d ) // insert item at index +{ +#if defined(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 ); + CHECK_PTR( vec[index] ); + numItems++; + return vec[index] != 0; + } else { + vec[index] = 0; // reset item + } + return TRUE; +} + +/*! + \internal +*/ + +bool QGVector::remove( uint index ) // remove item at index +{ +#if defined(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; +} + +/*! + \internal +*/ + +QCollection::Item QGVector::take( uint index ) // take out item +{ +#if defined(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; +} + + +/*! + \internal +*/ + +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; + } +} + +/*! + \internal +*/ + +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) + 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; + } + 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; +} + + +/*! + \internal +*/ + +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 + +static int cmp_vec( const void *n1, const void *n2 ) +{ + return sort_vec->compareItems( *((QCollection::Item*)n1), *((QCollection::Item*)n2) ); +} + +#if defined(Q_C_CALLBACKS) +} +#endif + + +/*! + \internal +*/ + +void QGVector::sort() // sort vector +{ + if ( count() == 0 ) // no elements + return; + register Item *start = &vec[0]; + register Item *end = &vec[len-1]; + Item tmp; + while ( TRUE ) { // 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; + } + } + sort_vec = (QGVector*)this; + qsort( vec, count(), sizeof(Item), cmp_vec ); + sort_vec = 0; +} + +/*! + \internal +*/ + +int QGVector::bsearch( Item d ) const // binary search; when sorted +{ + if ( !len ) + return -1; + if ( !d ) { +#if defined(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; +} + + +/*! + \internal +*/ + +int QGVector::findRef( Item d, uint index) const // find exact item in vector +{ +#if defined(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; +} + +/*! + \internal +*/ + +int QGVector::find( Item d, uint index ) const // find equal item in vector +{ +#if defined(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; +} + +/*! + \internal +*/ + +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; +} + +/*! + \internal +*/ + +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; +} + + +/*! + \internal +*/ + +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; +} + + +/*! + \internal +*/ + +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(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 ); +} + +/*! + \internal +*/ + +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 ); + CHECK_PTR( d ); + if ( !d ) // no memory + break; + vec[i] = d; + } + return s; +} + +/*! + \internal +*/ + +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; +} +#endif // QT_NO_DATASTREAM diff --git a/qtools/qgvector.h b/qtools/qgvector.h new file mode 100644 index 0000000..6a7999d --- /dev/null +++ b/qtools/qgvector.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** +** 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 "qcollection.h" +#endif // QT_H + + +class Q_EXPORT QGVector : public QCollection // 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 + + 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(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/qtools/qintdict.h b/qtools/qintdict.h new file mode 100644 index 0000000..ddc5fdf --- /dev/null +++ b/qtools/qintdict.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** +** 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 Q_EXPORT QIntDict : public QGDict +{ +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(); } +private: + void deleteItem( Item d ); +}; + +#if defined(Q_DELETING_VOID_UNDEFINED) +template<> inline void QIntDict<void>::deleteItem( QCollection::Item ) +{ +} +#endif + +template<class type> inline void QIntDict<type>::deleteItem( QCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template<class type> class Q_EXPORT 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/qtools/qiodevice.cpp b/qtools/qiodevice.cpp new file mode 100644 index 0000000..b2a6751 --- /dev/null +++ b/qtools/qiodevice.cpp @@ -0,0 +1,636 @@ +/**************************************************************************** +** +** +** Implementation of QIODevice class +** +** Created : 940913 +** +** 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 "qiodevice.h" + +// NOT REVISED +/*! + \class QIODevice qiodevice.h + + \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 like QFile, QBuffer and + QSocket inherit QIODevice and implement virtual functions like + write() appropriately. + + While applications sometimes use QIODevice directly, mostly it is + better to go through QTextStream and QDataStream, which provide + stream operations on any QIODevice subclass. QTextStream provides + text-oriented stream functionality (for human-readable ASCII files, + for example), while 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: <ul> + + <li> open() opens a device for reading and/or writing, depending on + the argument to open(). + + <li> close() closes the device and tidies up. + + <li> readBlock() reads a block of data from the device. + + <li> writeBlock() writes a block of data to the device. + + <li> readLine() reads a line (of text, usually) from the device. + + <li> flush() ensures that all buffered data are written to the real device. + + </ul>There are also some other, less used, action functions: <ul> + + <li> getch() reads a single character. + + <li> ungetch() forgets the last call to getch(), if possible. + + <li> putch() writes a single character. + + <li> size() returns the size of the device, if there is one. + + <li> at() returns the current read/write pointer, if there is one + for this device, or it moves the pointer. + + <li> atEnd() says whether there is more to read, if that is a + meaningful question for this device. + + <li> reset() moves the read/write pointer to the start of the + device, if that is possible for this device. + + </ul>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: <ul> + + <li> Access type. Some devices are direct access (it is possible to + read/write anywhere) while others are sequential. QIODevice + provides the access functions isDirectAccess(), isSequentialAccess() + and isCombinedAccess() to tell users what a given I/O device + supports. + + <li> Buffering. Some devices are accessed in raw mode while 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().) + + <li> Synchronicity. Synchronous devices work there and then, for + example files. When you read from a file, the file delivers its + data right away. Others, 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() tells the user how this + device operates. + + <li> CR/LF translation. For simplicity, applications often like to + see just a single CR/LF style, and QIODevice subclasses can provide + that. 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().) + + <li> Accessibility. Some files cannot be written, for example. + isReadable(), isWritable and isReadWrite() tells 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().) + + <li> Finally, isOpen() returns TRUE if the device is open. This can + quite obviously be set using open() :) + + </ul> + + QIODevice provides numerous pure virtual functions you need to + implement when subclassing it. Here is a skeleton subclass with all + the members you are certain to need, and some it's likely that you + will need: + + \code + class YourDevice : public QIODevice + { + public: + YourDevice(); + ~YourDevice(); + + bool open( int mode ); + void close(); + void flush(); + + uint size() const; + int at() const; // not a pure virtual function + bool at( int ); // not a pure virtual function + bool atEnd() const; // not a pure virtual function + + 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 can be ignored if your device + is sequential (e.g. an RS-232 port). + + \sa QDataStream, QTextStream +*/ + + +/*! + Constructs an I/O device. +*/ + +QIODevice::QIODevice() +{ + ioMode = 0; // initial mode + ioSt = IO_Ok; + ioIndex = 0; +} + +/*! + Destructs 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 more flags. +*/ + +/*! + \fn bool QIODevice::isDirectAccess() const + Returns TRUE if the I/O device is a direct access (not sequential) device, + otherwise FALSE. + \sa isSequentialAccess() +*/ + +/*! + \fn bool QIODevice::isSequentialAccess() const + Returns TRUE if the I/O device is a sequential access (not direct) device, + otherwise FALSE. 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 FALSE. + + This access method is currently not in use. +*/ + +/*! + \fn bool QIODevice::isBuffered() const + Returns TRUE if the I/O device is a buffered (not raw) device, otherwise + FALSE. + \sa isRaw() +*/ + +/*! + \fn bool QIODevice::isRaw() const + Returns TRUE if the I/O device is a raw (not buffered) device, otherwise + FALSE. + \sa isBuffered() +*/ + +/*! + \fn bool QIODevice::isSynchronous() const + Returns TRUE if the I/O device is a synchronous device, otherwise + FALSE. + \sa isAsynchronous() +*/ + +/*! + \fn bool QIODevice::isAsynchronous() const + Returns TRUE if the I/O device is a asynchronous device, otherwise + FALSE. + + 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. + + 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. + \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. + \sa isReadable(), isReadWrite() +*/ + +/*! + \fn bool QIODevice::isReadWrite() const + Returns TRUE if the I/O device was opened using \c IO_ReadWrite mode. + \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. + \sa isOpen() +*/ + +/*! + \fn bool QIODevice::isOpen() const + Returns TRUE if the I/O device state has been opened, otherwise 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 + get the reason why the operation did not succeed. + + The status codes are: + <ul> + <li>\c IO_Ok The operation was successful. + <li>\c IO_ReadError Could not read from the device. + <li>\c IO_WriteError Could not write to the device. + <li>\c IO_FatalError A fatal unrecoverable error occurred. + <li>\c IO_OpenError Could not open the device. + <li>\c IO_ConnectError Could not connect to the device. + <li>\c IO_AbortError The operation was unexpectedly aborted. + <li>\c IO_TimeOutError The operation timed out. + <li>\c IO_OnCloseError An unspecified error happened on close. + </ul> + + \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(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(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(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). +*/ + +void QIODevice::setStatus( int s ) +{ + ioSt = s; +} + + +/*! + \fn bool QIODevice::open( int mode ) + Opens the I/O device using the specified \e mode. + Returns TRUE if successful, or FALSE if the device could not be opened. + + The mode parameter \e m must be a combination of the following flags. + <ul> + <li>\c IO_Raw specified raw (unbuffered) file access. + <li>\c IO_ReadOnly opens a file in read-only mode. + <li>\c IO_WriteOnly opens a file in write-only mode. + <li>\c IO_ReadWrite opens a file in read/write mode. + <li>\c IO_Append sets the file index to the end of the file. + <li>\c IO_Truncate truncates the file. + <li>\c IO_Translate enables carriage returns and linefeed translation + for text files under MS-DOS, Window, OS/2 and Macintosh. Cannot be + combined with \c IO_Raw. + </ul> + + 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 uint 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 index. + + This index is the data read/write head of the I/O device. + + \sa size() +*/ + +int QIODevice::at() const +{ + return ioIndex; +} + +/*! + Virtual function that sets the I/O device index to \e pos. + \sa size() +*/ + +bool QIODevice::at( int pos ) +{ +#if defined(CHECK_RANGE) + if ( (uint)pos > size() ) { + qWarning( "QIODevice::at: Index %d out of range", pos ); + return FALSE; + } +#endif + ioIndex = pos; + return TRUE; +} + +/*! + Virtual function that returns TRUE if the I/O device index is at the + end of the input. +*/ + +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() == (int)size(); + } +} + +/*! + \fn bool QIODevice::reset() + Sets the device index to 0. + \sa at() +*/ + + +/*! + \fn int QIODevice::readBlock( char *data, uint maxlen ) + Reads at most \e maxlen bytes from the I/O device into \e data and + returns the number of bytes actually read. + + This virtual function must be reimplemented by all subclasses. + + \sa writeBlock() +*/ + +/*! + This convenience function returns all of the remaining data in the + device. Note that this only works for direct access devices, such + as QFile. + + \sa isDirectAccess() +*/ +QByteArray QIODevice::readAll() +{ + int n = size()-at(); + QByteArray ba(size()-at()); + char* c = ba.data(); + while ( n ) { + int r = readBlock( c, n ); + if ( r < 0 ) + return QByteArray(); + n -= r; + c += r; + } + return ba; +} + +/*! + \fn int QIODevice::writeBlock( const char *data, uint len ) + Writes \e len bytes from \e p to the I/O device and returns the number of + bytes actually written. + + This virtual function must be reimplemented by all subclasses. + + \sa readBlock() +*/ + +/*! + This convenience function is the same as calling + writeBlock( data.data(), data.size() ). +*/ +int QIODevice::writeBlock( const QByteArray& data ) +{ + return writeBlock( data.data(), data.size() ); +} + +/*! + Reads a line of text, up to \e maxlen bytes including a terminating + \0. If there is a newline at the end if the line, it is not stripped. + + Returns the number of bytes read, or -1 in case of error. + + This virtual function can be reimplemented much more efficiently by + the most subclasses. + + \sa readBlock(), QTextStream::readLine() +*/ + +int QIODevice::readLine( char *data, uint maxlen ) +{ + if ( maxlen == 0 ) // application bug? + return 0; + int pos = at(); // get current position + int s = (int)size(); // size of I/O device + char *p = data; + if ( pos >= s ) + return 0; + while ( pos++ < s && --maxlen ) { // read one byte at a time + readBlock( p, 1 ); + if ( *p++ == '\n' ) // end of line + break; + } + *p++ = '\0'; + return (int)((long)p - (long)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 \e ch to the I/O device. + + Returns \e ch, or -1 if some error occurred. + + This virtual function must be reimplemented by all subclasses. + + \sa getch(), ungetch() +*/ + +/*! + \fn int QIODevice::ungetch( int ch ) + + Puts the character \e ch back into the I/O device and decrements the + index if it is not zero. + + This function is normally called to "undo" a getch() operation. + + Returns \e ch, or -1 if some error occurred. + + This virtual function must be reimplemented by all subclasses. + + \sa getch(), putch() +*/ diff --git a/qtools/qiodevice.h b/qtools/qiodevice.h new file mode 100644 index 0000000..1c54217 --- /dev/null +++ b/qtools/qiodevice.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** +** Definition of QIODevice class +** +** Created : 940913 +** +** 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 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 // IO device class +{ +public: + 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 uint size() const = 0; + virtual int at() const; + virtual bool at( int ); + virtual bool atEnd() const; + bool reset() { return at(0); } + + virtual int readBlock( char *data, uint maxlen ) = 0; + virtual int writeBlock( const char *data, uint len ) = 0; + virtual int readLine( char *data, uint maxlen ); + int writeBlock( const QByteArray& data ); + 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 ); + int 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/qtools/qlist.h b/qtools/qlist.h new file mode 100644 index 0000000..678e92d --- /dev/null +++ b/qtools/qlist.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** +** Definition of QList template/macro class +** +** Created : 920701 +** +** 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 QLIST_H +#define QLIST_H + +#ifndef QT_H +#include "qglist.h" +#endif // QT_H + + +template<class type> class Q_EXPORT QList : public QGList +{ +public: + QList() {} + QList( const QList<type> &l ) : QGList(l) {} + ~QList() { clear(); } + QList<type> &operator=(const QList<type> &l) + { return (QList<type>&)QGList::operator=(l); } + bool operator==( const QList<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,(QCollection::Item)d); } + void inSort( const type *d ) { QGList::inSort((QCollection::Item)d); } + void prepend( const type *d ) { QGList::insertAt(0,(QCollection::Item)d); } + void append( const type *d ) { QGList::append((QCollection::Item)d); } + bool remove( uint i ) { return QGList::removeAt(i); } + bool remove() { return QGList::remove((QCollection::Item)0); } + bool remove( const type *d ) { return QGList::remove((QCollection::Item)d); } + bool removeRef( const type *d ) { return QGList::removeRef((QCollection::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((QCollection::Item)d); } + int findNext( const type *d ) { return QGList::find((QCollection::Item)d,FALSE); } + int findRef( const type *d ) { return QGList::findRef((QCollection::Item)d); } + int findNextRef( const type *d ){ return QGList::findRef((QCollection::Item)d,FALSE);} + uint contains( const type *d ) const { return QGList::contains((QCollection::Item)d); } + uint containsRef( const type *d ) const + { return QGList::containsRef((QCollection::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); } +private: + void deleteItem( QCollection::Item d ); +}; + +#if defined(Q_DELETING_VOID_UNDEFINED) +template<> inline void QList<void>::deleteItem( QCollection::Item ) +{ +} +#endif + +template<class type> inline void QList<type>::deleteItem( QCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + + + +template<class type> class Q_EXPORT QListIterator : public QGListIterator +{ +public: + QListIterator(const QList<type> &l) :QGListIterator((QGList &)l) {} + ~QListIterator() {} + 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 QList<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);} + QListIterator<type>& operator=(const QListIterator<type>&it) + { QGListIterator::operator=(it); return *this; } +}; + + +#endif // QLIST_H diff --git a/qtools/qptrdict.h b/qtools/qptrdict.h new file mode 100644 index 0000000..c075e30 --- /dev/null +++ b/qtools/qptrdict.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** +** Definition of QPtrDict template class +** +** Created : 970415 +** +** 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 QPTRDICT_H +#define QPTRDICT_H + +#ifndef QT_H +#include "qgdict.h" +#endif // QT_H + + +template<class type> class Q_EXPORT QPtrDict : public QGDict +{ +public: + QPtrDict(int size=17) : QGDict(size,PtrKey,0,0) {} + QPtrDict( const QPtrDict<type> &d ) : QGDict(d) {} + ~QPtrDict() { clear(); } + QPtrDict<type> &operator=(const QPtrDict<type> &d) + { return (QPtrDict<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( void *k, const type *d ) + { QGDict::look_ptr(k,(Item)d,1); } + void replace( void *k, const type *d ) + { QGDict::look_ptr(k,(Item)d,2); } + bool remove( void *k ) { return QGDict::remove_ptr(k); } + type *take( void *k ) { return (type*)QGDict::take_ptr(k); } + type *find( void *k ) const + { return (type *)((QGDict*)this)->QGDict::look_ptr(k,0,0); } + type *operator[]( void *k ) const + { return (type *)((QGDict*)this)->QGDict::look_ptr(k,0,0); } + void clear() { QGDict::clear(); } + void resize( uint n ) { QGDict::resize(n); } + void statistics() const { QGDict::statistics(); } +private: + void deleteItem( Item d ); +}; + +#if defined(Q_DELETING_VOID_UNDEFINED) +template<> inline void QPtrDict<void>::deleteItem( QCollection::Item ) +{ +} +#endif + +template<class type> inline void QPtrDict<type>::deleteItem( QCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + + +template<class type> class Q_EXPORT QPtrDictIterator : public QGDictIterator +{ +public: + QPtrDictIterator(const QPtrDict<type> &d) :QGDictIterator((QGDict &)d) {} + ~QPtrDictIterator() {} + 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(); } + void *currentKey() const { return QGDictIterator::getKeyPtr(); } + type *operator()() { return (type *)QGDictIterator::operator()(); } + type *operator++() { return (type *)QGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j);} +}; + + +#endif // QPTRDICT_H diff --git a/qtools/qqueue.h b/qtools/qqueue.h new file mode 100644 index 0000000..94bc130 --- /dev/null +++ b/qtools/qqueue.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** +** Definition of QQueue template/macro class +** +** Created : 920917 +** +** 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 QQUEUE_H +#define QQUEUE_H + +#ifndef QT_H +#include "qglist.h" +#endif // QT_H + + +template<class type> class QQueue : private QGList +{ +public: + QQueue() {} + QQueue( const QQueue<type> &q ) : QGList(q) {} + ~QQueue() { clear(); } + QQueue<type>& operator=(const QQueue<type> &q) + { return (QQueue<type>&)QGList::operator=(q); } + bool autoDelete() const { return QCollection::autoDelete(); } + void setAutoDelete( bool del ) { QCollection::setAutoDelete(del); } + uint count() const { return QGList::count(); } + bool isEmpty() const { return QGList::count() == 0; } + void enqueue( const type *d ) { QGList::append(Item(d)); } + type *dequeue() { return (type *)QGList::takeFirst();} + bool remove() { return QGList::removeFirst(); } + void clear() { QGList::clear(); } + type *head() const { return (type *)QGList::cfirst(); } + operator type *() const { return (type *)QGList::cfirst(); } + type *current() const { return (type *)QGList::cfirst(); } +private: + void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } +}; + + +#endif // QQUEUE_H diff --git a/qtools/qregexp.cpp b/qtools/qregexp.cpp new file mode 100644 index 0000000..671867e --- /dev/null +++ b/qtools/qregexp.cpp @@ -0,0 +1,1091 @@ +/**************************************************************************** +** +** +** 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" +#include <ctype.h> +#include <stdlib.h> + +// NOT REVISED +/*! + \class QRegExp qregexp.h + \ingroup tools + \ingroup misc + \brief The QRegExp class provides pattern matching using regular + expressions or wildcards. + + QRegExp knows these regexp primitives: + <ul plain> + <li><dfn>c</dfn> matches the character 'c' + <li><dfn>.</dfn> matches any character + <li><dfn>^</dfn> matches start of input + <li><dfn>$</dfn> matches end of input + <li><dfn>[]</dfn> matches a defined set of characters - see below. + <li><dfn>a*</dfn> matches a sequence of zero or more a's + <li><dfn>a+</dfn> matches a sequence of one or more a's + <li><dfn>a?</dfn> matches an optional a + <li><dfn>\c</dfn> escape code for matching special characters such + as \, [, *, +, . etc. + <li><dfn>\t</dfn> matches the TAB character (9) + <li><dfn>\n</dfn> matches newline (10) + <li><dfn>\r</dfn> matches return (13) + <li><dfn>\s</dfn> matches a white space (defined as any character + for which QChar::isSpace() returns TRUE. This includes at least + ASCII characters 9 (TAB), 10 (LF), 11 (VT), 12(FF), 13 (CR) and 32 + (Space)). + <li><dfn>\d</dfn> matches a digit (defined as any character for + which QChar::isDigit() returns TRUE. This includes at least ASCII + characters '0'-'9'). + <li><dfn>\x1f6b</dfn> matches the character with unicode point U1f6b + (hexadecimal 1f6b). \x0012 will match the ASCII/Latin1 character + 0x12 (18 decimal, 12 hexadecimal). + <li><dfn>\022</dfn> matches the ASCII/Latin1 character 022 (18 + decimal, 22 octal). + </ul> + + In wildcard mode, it only knows four primitives: + <ul plain> + <li><dfn>c</dfn> matches the character 'c' + <li><dfn>?</dfn> matches any character + <li><dfn>*</dfn> matches any sequence of characters + <li><dfn>[]</dfn> matches a defined set of characters - see below. + </ul> + + QRegExp supports Unicode both in the pattern strings and in the + strings to be matched. + + When writing regular expressions in C++ code, remember that C++ + processes \ characters. So in order to match e.g. a "." character, + you must write "\\." in C++ source, not "\.". + + A character set matches a defined set of characters. For example, + [BSD] matches any of 'B', 'D' and 'S'. Within a character set, the + special characters '.', '*', '?', '^', '$', '+' and '[' lose their + special meanings. The following special characters apply: + <ul plain> + <li><dfn>^</dfn> When placed first in the list, changes the + character set to match any character \e not in the list. To include + the character '^' itself in the set, escape it or place it anywhere + but first. + <li><dfn>-</dfn> Defines a range of characters. To include the + character '-' itself in the set, escape it or place it last. + <li><dfn>]</dfn> Ends the character set definition. To include the + character ']' itself in the set, escape it or place it first (but + after the negation operator '^', if present) + </ul> + Thus, [a-zA-Z0-9.] matches upper and lower case ASCII letters, + digits and dot; and [^\s] matches everything except white space. + + \bug Case insensitive matching is not supported for non-ASCII/Latin1 + (non-8bit) characters. Any character with a non-zero QChar.row() is + matched case sensitively even if the QRegExp is in case insensitive + mode. + + \note In Qt 3.0, the language of regular expressions will contain + five more special characters, namely '(', ')', '{', '|' and '}'. To + ease porting, it's a good idea to escape these characters with a + backslash in all the regular expressions you'll write from now on. +*/ + + +// +// The regexp pattern is internally represented as an array of uints, +// each element containing an 16-bit character or a 32-bit code +// (listed below). User-defined character classes (e.g. [a-zA-Z]) +// are encoded as this: +// uint no: 1 2 3 ... +// value: CCL | n from | to from | to +// +// where n is the (16-bit) number of following range definitions and +// from and to define the ranges inclusive. from <= to is always true, +// otherwise it is a built-in charclass (Pxx, eg \s - PWS). Single +// characters in the class are coded as from==to. Negated classes +// (e.g. [^a-z]) use CCN instead of CCL. + +const uint END = 0x00000000; +const uint PWS = 0x10010000; // predef charclass: whitespace (\s) +const uint PDG = 0x10020000; // predef charclass: digit (\d) +const uint CCL = 0x20010000; // character class [] +const uint CCN = 0x20020000; // neg character class [^] +const uint CHR = 0x40000000; // character +const uint BOL = 0x80010000; // beginning of line ^ +const uint EOL = 0x80020000; // end of line $ +const uint BOW = 0x80030000; // beginning of word \< +const uint EOW = 0x80040000; // end of word \> +const uint ANY = 0x80050000; // any character . +const uint CLO = 0x80070000; // Kleene closure * +const uint OPT = 0x80080000; // Optional closure ? + +const uint MCC = 0x20000000; // character class bitmask +const uint MCD = 0xffff0000; // code mask +const uint MVL = 0x0000ffff; // value mask + +// +// QRegExp::error codes (internal) +// + +const int PatOk = 0; // pattern ok +const int PatNull = 1; // no pattern defined +const int PatSyntax = 2; // pattern syntax error +const int PatOverflow = 4; // pattern too long + + +/***************************************************************************** + QRegExp member functions + *****************************************************************************/ + +/*! + Constructs an empty regular expression. +*/ + +QRegExp::QRegExp() +{ + rxdata = 0; + cs = TRUE; + wc = FALSE; + error = PatOk; +} + +/*! + Constructs a regular expression. + + \arg \e pattern is the regular expression pattern string. + \arg \e caseSensitive specifies whether or not to use case sensitive + matching. + \arg \e wildcard specifies whether the pattern string should be used for + wildcard matching (also called globbing expression), normally used for + matching file names. + + \sa setWildcard() +*/ + +QRegExp::QRegExp( const QString &pattern, bool caseSensitive, bool wildcard ) +{ + rxstring = pattern; + rxdata = 0; + cs = caseSensitive; + wc = wildcard; + compile(); +} + +/*! + Constructs a regular expression which is a copy of \e r. + \sa operator=(const QRegExp&) +*/ + +QRegExp::QRegExp( const QRegExp &r ) +{ + rxstring = r.pattern(); + rxdata = 0; + cs = r.caseSensitive(); + wc = r.wildcard(); + compile(); +} + +/*! + Destructs the regular expression and cleans up its internal data. +*/ + +QRegExp::~QRegExp() +{ + if ( rxdata ) // Avoid purify complaints + delete [] rxdata; +} + +/*! + Copies the regexp \e r and returns a reference to this regexp. + The case sensitivity and wildcard options are copied, as well. +*/ + +QRegExp &QRegExp::operator=( const QRegExp &r ) +{ + rxstring = r.rxstring; + cs = r.cs; + wc = r.wc; + compile(); + return *this; +} + +/*! + \obsolete + Consider using setPattern() instead of this method. + + Sets the pattern string to \e pattern and returns a reference to this regexp. + The case sensitivity or wildcard options do not change. +*/ + +QRegExp &QRegExp::operator=( const QString &pattern ) +{ + rxstring = pattern; + compile(); + return *this; +} + + +/*! + Returns TRUE if this regexp is equal to \e r. + + Two regexp objects are equal if they have equal pattern strings, + case sensitivity options and wildcard options. +*/ + +bool QRegExp::operator==( const QRegExp &r ) const +{ + return rxstring == r.rxstring && cs == r.cs && wc == r.wc; +} + +/*! + \fn bool QRegExp::operator!=( const QRegExp &r ) const + + Returns TRUE if this regexp is \e not equal to \e r. + + \sa operator==() +*/ + +/*! + \fn bool QRegExp::isEmpty() const + Returns TRUE if the regexp is empty. +*/ + +/*! + \fn bool QRegExp::isValid() const + Returns TRUE if the regexp is valid, or FALSE if it is invalid. + + The pattern "[a-z" is an example of an invalid pattern, since it lacks a + closing bracket. +*/ + + +/*! + \fn bool QRegExp::wildcard() const + Returns TRUE if wildcard mode is on, otherwise FALSE. \sa setWildcard(). +*/ + +/*! + Sets the wildcard option for the regular expression. The default + is FALSE. + + Setting \e wildcard to TRUE makes it convenient to match filenames + instead of plain text. + + For example, "qr*.cpp" matches the string "qregexp.cpp" in wildcard mode, + but not "qicpp" (which would be matched in normal mode). + + \sa wildcard() +*/ + +void QRegExp::setWildcard( bool wildcard ) +{ + if ( wildcard != wc ) { + wc = wildcard; + compile(); + } +} + +/*! + \fn bool QRegExp::caseSensitive() const + + Returns TRUE if case sensitivity is enabled, otherwise FALSE. The + default is TRUE. + + \sa setCaseSensitive() +*/ + +/*! + Enables or disables case sensitive matching. + + In case sensitive mode, "a.e" matches "axe" but not "Axe". + + See also: caseSensitive() +*/ + +void QRegExp::setCaseSensitive( bool enable ) +{ + if ( cs != enable ) { + cs = enable; + compile(); + } +} + + +/*! + \fn QString QRegExp::pattern() const + Returns the pattern string of the regexp. +*/ + + +/*! + \fn void QRegExp::setPattern(const QString & pattern) + Sets the pattern string to \a pattern and returns a reference to this regexp. + The case sensitivity or wildcard options do not change. +*/ + +static inline bool iswordchar( int x ) +{ + return isalnum(x) || x == '_'; //# Only 8-bit support +} + + +/*! + \internal + Match character class +*/ + +static bool matchcharclass( uint *rxd, QChar c ) +{ + uint *d = rxd; + uint clcode = *d & MCD; + bool neg = clcode == CCN; + if ( clcode != CCL && clcode != CCN) + qWarning("QRegExp: Internal error, please report to qt-bugs@trolltech.com"); + uint numFields = *d & MVL; + uint cval = (((uint)(c.row())) << 8) | ((uint)c.cell()); + bool found = FALSE; + for ( int i = 0; i < (int)numFields; i++ ) { + d++; + if ( *d == PWS && c.isSpace() ) { + found = TRUE; + break; + } + if ( *d == PDG && c.isDigit() ) { + found = TRUE; + break; + } + else { + uint from = ( *d & MCD ) >> 16; + uint to = *d & MVL; + if ( (cval >= from) && (cval <= to) ) { + found = TRUE; + break; + } + } + } + return neg ? !found : found; +} + + + +/* + Internal: Recursively match string. +*/ + +static int matchstring( uint *rxd, const QChar *str, uint strlength, + const QChar *bol, bool cs ) +{ + const QChar *p = str; + const QChar *start = p; + uint pl = strlength; + uint *d = rxd; + + //### in all cases here: handle pl == 0! (don't read past strlen) + while ( *d ) { + if ( *d & CHR ) { // match char + if ( !pl ) + return -1; + QChar c( *d ); + if ( !cs && !c.row() ) { // case insensitive, #Only 8bit + if ( p->row() || tolower(p->cell()) != c.cell() ) + return -1; + p++; + pl--; + } else { // case insensitive + if ( *p != c ) + return -1; + p++; + pl--; + } + d++; + } + else if ( *d & MCC ) { // match char class + if ( !pl ) + return -1; + if ( !matchcharclass( d, *p ) ) + return -1; + p++; + pl--; + d += (*d & MVL) + 1; + } + else switch ( *d++ ) { + case PWS: // match whitespace + if ( !pl || !p->isSpace() ) + return -1; + p++; + pl--; + break; + case PDG: // match digits + if ( !pl || !p->isDigit() ) + return -1; + p++; + pl--; + break; + case ANY: // match anything + if ( !pl ) + return -1; + p++; + pl--; + break; + case BOL: // match beginning of line + if ( p != bol ) + return -1; + break; + case EOL: // match end of line + if ( pl ) + return -1; + break; + case BOW: // match beginning of word + if ( !iswordchar(*p) || (p > bol && iswordchar(*(p-1)) ) ) + return -1; + break; + case EOW: // match end of word + if ( iswordchar(*p) || p == bol || !iswordchar(*(p-1)) ) + return -1; + break; + case CLO: // Kleene closure + { + const QChar *first_p = p; + if ( *d & CHR ) { // match char + QChar c( *d ); + if ( !cs && !c.row() ) { // case insensitive, #only 8bit + while ( pl && !p->row() && tolower(p->cell())==c.cell() ) { + p++; + pl--; + } + } + else { // case sensitive + while ( pl && *p == c ) { + p++; + pl--; + } + } + d++; + } + else if ( *d & MCC ) { // match char class + while( pl && matchcharclass( d, *p ) ) { + p++; + pl--; + } + d += (*d & MVL) + 1; + } + else if ( *d == PWS ) { + while ( pl && p->isSpace() ) { + p++; + pl--; + } + d++; + } + else if ( *d == PDG ) { + while ( pl && p->isDigit() ) { + p++; + pl--; + } + d++; + } + else if ( *d == ANY ) { + p += pl; + pl = 0; + d++; + } + else { + return -1; // error + } + d++; // skip CLO's END + while ( p >= first_p ) { // go backwards + int end = matchstring( d, p, pl, bol, cs ); + if ( end >= 0 ) + return ( p - start ) + end; + if ( !p ) + return -1; + --p; + ++pl; + } + } + return -1; + case OPT: // optional closure + { + const QChar *first_p = p; + if ( *d & CHR ) { // match char + QChar c( *d ); + if ( !cs && !c.row() ) { // case insensitive, #only 8bit + if ( pl && !p->row() && tolower(p->cell()) == c.cell() ) { + p++; + pl--; + } + } + else { // case sensitive + if ( pl && *p == c ) { + p++; + pl--; + } + } + d++; + } + else if ( *d & MCC ) { // match char class + if ( pl && matchcharclass( d, *p ) ) { + p++; + pl--; + } + d += (*d & MVL) + 1; + } + else if ( *d == PWS ) { + if ( pl && p->isSpace() ) { + p++; + pl--; + } + d++; + } + else if ( *d == PDG ) { + if ( pl && p->isDigit() ) { + p++; + pl--; + } + d++; + } + else if ( *d == ANY ) { + if ( pl ) { + p++; + pl--; + } + d++; + } + else { + return -1; // error + } + d++; // skip OPT's END + while ( p >= first_p ) { // go backwards + int end = matchstring( d, p, pl, bol, cs ); + if ( end >= 0 ) + return ( p - start ) + end; + if ( !p ) + return -1; + --p; + ++pl; + } + } + return -1; + + default: // error + return -1; + } + } + return p - start; +} + + +/*! + \internal + Recursively match string. +*/ + +// This is obsolete now, but since it is protected (not private), it +// is still implemented on the off-chance that somebody has made a +// class derived from QRegExp and calls this directly. +// Qt 3.0: Remove this? + + +const QChar *QRegExp::matchstr( uint *rxd, const QChar *str, uint strlength, + const QChar *bol ) const +{ + int len = matchstring( rxd, str, strlength, bol, cs ); + if ( len < 0 ) + return 0; + return str + len; +} + +/*! + Attempts to match in \e str, starting from position \e index. + Returns the position of the match, or -1 if there was no match. + + If \e len is not a null pointer, the length of the match is stored in + \e *len. + + If \e indexIsStart is TRUE (the default), the position \e index in + the string will match the start-of-input primitive (^) in the + regexp, if present. Otherwise, position 0 in \e str will match. + + Example: + \code + QRegExp r("[0-9]*\\.[0-9]+"); // matches floating point + int len; + r.match("pi = 3.1416", 0, &len); // returns 5, len == 6 + \endcode + + \note In Qt 3.0, this function will be replaced by find(). +*/ + +int QRegExp::match( const QString &str, int index, int *len, + bool indexIsStart ) const +{ + if ( !isValid() || isEmpty() ) + return -1; + if ( str.length() < (uint)index ) + return -1; + const QChar *start = str.unicode(); + const QChar *p = start + index; + uint pl = str.length() - index; + uint *d = rxdata; + int ep = -1; + + if ( *d == BOL ) { // match from beginning of line + ep = matchstring( d, p, pl, indexIsStart ? p : start, cs ); + } else { + if ( *d & CHR ) { + QChar c( *d ); + if ( !cs && !c.row() ) { // case sensitive, # only 8bit + while ( pl && ( p->row() || tolower(p->cell()) != c.cell() ) ) { + p++; + pl--; + } + } else { // case insensitive + while ( pl && *p != c ) { + p++; + pl--; + } + } + } + while( 1 ) { // regular match + ep = matchstring( d, p, pl, indexIsStart ? start+index : start, cs ); + if ( ep >= 0 ) + break; + if ( !pl ) + break; + p++; + pl--; + } + } + if ( len ) + *len = ep >= 0 ? ep : 0; // No match -> 0, for historical reasons + return ep >= 0 ? (int)(p - start) : -1; // return index; +} + +/*! \fn int QRegExp::find( const QString& str, int index ) + + Attempts to match in \e str, starting from position \e index. + Returns the position of the match, or -1 if there was no match. + + \sa match() +*/ + +// +// Translate wildcard pattern to standard regexp pattern. +// Ex: *.cpp ==> ^.*\.cpp$ +// + +static QString wc2rx( const QString &pattern ) +{ + int patlen = (int)pattern.length(); + QString wcpattern = QString::fromLatin1("^"); + + QChar c; + for( int i = 0; i < patlen; i++ ) { + c = pattern[i]; + switch ( (char)c ) { + case '*': // '*' ==> '.*' + wcpattern += '.'; + break; + case '?': // '?' ==> '.' + c = '.'; + break; + case '.': // quote special regexp chars + case '+': + case '\\': + case '$': + case '^': + wcpattern += '\\'; + break; + case '[': + if ( (char)pattern[i+1] == '^' ) { // don't quote '^' after '[' + wcpattern += '['; + c = pattern[i+1]; + i++; + } + break; + } + wcpattern += c; + + } + wcpattern += '$'; + return wcpattern; // return new regexp pattern +} + + +// +// Internal: Get char value and increment pointer. +// + +static uint char_val( const QChar **str, uint *strlength ) // get char value +{ + const QChar *p = *str; + uint pl = *strlength; + uint len = 1; + uint v = 0; + if ( (char)*p == '\\' ) { // escaped code + p++; + pl--; + if ( !pl ) { // it is just a '\' + (*str)++; + (*strlength)--; + return '\\'; + } + len++; // length at least 2 + int i; + char c; + char ch = tolower((char)*p); + switch ( ch ) { + case 'b': v = '\b'; break; // bell + case 'f': v = '\f'; break; // form feed + case 'n': v = '\n'; break; // newline + case 'r': v = '\r'; break; // return + case 't': v = '\t'; break; // tab + case 's': v = PWS; break; // whitespace charclass + case 'd': v = PDG; break; // digit charclass + case '<': v = BOW; break; // word beginning matcher + case '>': v = EOW; break; // word ending matcher + + case 'x': { // hex code + p++; + pl--; + for ( i = 0; (i < 4) && pl; i++ ) { //up to 4 hex digits + c = tolower((char)*p); + bool a = ( c >= 'a' && c <= 'f' ); + if ( (c >= '0' && c <= '9') || a ) { + v <<= 4; + v += a ? 10 + c - 'a' : c - '0'; + len++; + } + else { + break; + } + p++; + pl--; + } + } + break; + + default: { + if ( ch >= '0' && ch <= '7' ) { //octal code + len--; + for ( i = 0; (i < 3) && pl; i++ ) { // up to 3 oct digits + c = (char)*p; + if ( c >= '0' && c <= '7' ) { + v <<= 3; + v += c - '0'; + len++; + } + else { + break; + } + p++; + pl--; + } + } + else { // not an octal number + v = (((uint)(p->row())) << 8) | ((uint)p->cell()); + } + } + } + } else { + v = (((uint)(p->row())) << 8) | ((uint)p->cell()); + } + *str += len; + *strlength -= len; + return v; +} + + +#if defined(DEBUG) +static uint *dump( uint *p ) +{ + while ( *p != END ) { + if ( *p & CHR ) { + QChar uc = (QChar)*p; + char c = (char)uc; + uint u = (((uint)(uc.row())) << 8) | ((uint)uc.cell()); + qDebug( "\tCHR\tU%04x (%c)", u, (c ? c : ' ')); + p++; + } + else if ( *p & MCC ) { + uint clcode = *p & MCD; + uint numFields = *p & MVL; + if ( clcode == CCL ) + qDebug( "\tCCL\t%i", numFields ); + else if ( clcode == CCN ) + qDebug( "\tCCN\t%i", numFields ); + else + qDebug("coding error!"); + for ( int i = 0; i < (int)numFields; i++ ) { + p++; + if ( *p == PWS ) + qDebug( "\t\tPWS" ); + else if ( *p == PDG ) + qDebug( "\t\tPDG" ); + else { + uint from = ( *p & MCD ) >> 16; + uint to = *p & MVL; + char fc = (char)QChar(from); + char tc = (char)QChar(to); + qDebug( "\t\tU%04x (%c) - U%04x (%c)", from, + (fc ? fc : ' '), to, (tc ? tc : ' ') ); + } + } + p++; + } + else switch ( *p++ ) { + case PWS: + qDebug( "\tPWS" ); + break; + case PDG: + qDebug( "\tPDG" ); + break; + case BOL: + qDebug( "\tBOL" ); + break; + case EOL: + qDebug( "\tEOL" ); + break; + case BOW: + qDebug( "\tBOW" ); + break; + case EOW: + qDebug( "\tEOW" ); + break; + case ANY: + qDebug( "\tANY" ); + break; + case CLO: + qDebug( "\tCLO" ); + p = dump( p ); + break; + case OPT: + qDebug( "\tOPT" ); + p = dump( p ); + break; + } + } + qDebug( "\tEND" ); + return p+1; +} +#endif // DEBUG + + +static const int maxlen = 1024; // max length of regexp array +static uint rxarray[ maxlen ]; // tmp regexp array + +/*! + \internal + Compiles the regular expression and stores the result in rxdata. + The 'error' flag is set to non-zero if an error is detected. + NOTE! This function is not reentrant! +*/ + +void QRegExp::compile() +{ + if ( rxdata ) { // delete old data + delete [] rxdata; + rxdata = 0; + } + if ( rxstring.isEmpty() ) { // no regexp pattern set + error = PatNull; + return; + } + + error = PatOk; // assume pattern is ok + + QString pattern; + if ( wc ) + pattern = wc2rx(rxstring); + else + pattern = rxstring; + const QChar *start = pattern.unicode(); // pattern pointer + const QChar *p = start; // pattern pointer + uint pl = pattern.length(); + uint *d = rxarray; // data pointer + uint *prev_d = 0; + +#define GEN(x) *d++ = (x) + + while ( pl ) { + char ch = (char)*p; + switch ( ch ) { + + case '^': // beginning of line + prev_d = d; + GEN( p == start ? BOL : (CHR | ch) ); + p++; + pl--; + break; + + case '$': // end of line + prev_d = d; + GEN( pl == 1 ? EOL : (CHR | ch) ); + p++; + pl--; + break; + + case '.': // any char + prev_d = d; + GEN( ANY ); + p++; + pl--; + break; + + case '[': // character class + { + prev_d = d; + p++; + pl--; + if ( !pl ) { + error = PatSyntax; + return; + } + bool firstIsEscaped = ( (char)*p == '\\' ); + uint cch = char_val( &p, &pl ); + if ( cch == '^' && !firstIsEscaped ) { // negate! + GEN( CCN ); + if ( !pl ) { + error = PatSyntax; + return; + } + cch = char_val( &p, &pl ); + } else { + GEN( CCL ); + } + uint numFields = 0; + while ( pl ) { + if ((pl>2) && ((char)*p == '-') && ((char)*(p+1) != ']')) { + // Found a range + char_val( &p, &pl ); // Read the '-' + uint cch2 = char_val( &p, &pl ); // Read the range end + if ( cch > cch2 ) { // swap start and stop + int tmp = cch; + cch = cch2; + cch2 = tmp; + } + GEN( (cch << 16) | cch2 ); // from < to + numFields++; + } + else { + // Found a single character + if ( cch & MCD ) // It's a code; will not be mistaken + GEN( cch ); // for a range, since from > to + else + GEN( (cch << 16) | cch ); // from == to range + numFields++; + } + if ( d >= rxarray + maxlen ) { // pattern too long + error = PatOverflow; + return; + } + if ( !pl ) { // At least ']' should be left + error = PatSyntax; + return; + } + bool nextIsEscaped = ( (char)*p == '\\' ); + cch = char_val( &p, &pl ); + if ( cch == (uint)']' && !nextIsEscaped ) + break; + if ( !pl ) { // End, should have seen ']' + error = PatSyntax; + return; + } + } + *prev_d |= numFields; // Store number of fields + } + break; + + case '*': // Kleene closure, or + case '+': // positive closure, or + case '?': // optional closure + { + if ( prev_d == 0 ) { // no previous expression + error = PatSyntax; // empty closure + return; + } + switch ( *prev_d ) { // test if invalid closure + case BOL: + case BOW: + case EOW: + case CLO: + case OPT: + error = PatSyntax; + return; + } + int ddiff = d - prev_d; + if ( *p == '+' ) { // convert to Kleene closure + if ( d + ddiff >= rxarray + maxlen ) { + error = PatOverflow; // pattern too long + return; + } + memcpy( d, prev_d, ddiff*sizeof(uint) ); + d += ddiff; + prev_d += ddiff; + } + memmove( prev_d+1, prev_d, ddiff*sizeof(uint) ); + *prev_d = ch == '?' ? OPT : CLO; + d++; + GEN( END ); + p++; + pl--; + } + break; + + default: + { + prev_d = d; + uint cv = char_val( &p, &pl ); + if ( cv & MCD ) { // It's a code + GEN( cv ); + } + else { + if ( !cs && cv <= 0xff ) // #only 8bit support + cv = tolower( cv ); + GEN( CHR | cv ); + } + } + } + if ( d >= rxarray + maxlen ) { // oops! + error = PatOverflow; // pattern too long + return; + } + } + GEN( END ); + int len = d - rxarray; + rxdata = new uint[ len ]; // copy from rxarray to rxdata + CHECK_PTR( rxdata ); + memcpy( rxdata, rxarray, len*sizeof(uint) ); +#if defined(DEBUG) + //dump( rxdata ); // uncomment this line for debugging +#endif +} diff --git a/qtools/qregexp.h b/qtools/qregexp.h new file mode 100644 index 0000000..25868ce --- /dev/null +++ b/qtools/qregexp.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** +** 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 "qstring.h" +#endif // QT_H + + +class Q_EXPORT QRegExp +{ +public: + QRegExp(); + QRegExp( const QString &, bool caseSensitive=TRUE, bool wildcard=FALSE ); + QRegExp( const QRegExp & ); + ~QRegExp(); + QRegExp &operator=( const QRegExp & ); + QRegExp &operator=( const QString &pattern ); + + bool operator==( const QRegExp & ) const; + bool operator!=( const QRegExp &r ) const + { return !(this->operator==(r)); } + + bool isEmpty() const { return rxdata == 0; } + bool isValid() const { return error == 0; } + + bool caseSensitive() const { return cs; } + void setCaseSensitive( bool ); + + bool wildcard() const { return wc; } + void setWildcard( bool ); + + QString pattern() const { return rxstring; } + // ### in Qt 3.0, provide a real implementation + void setPattern( const QString& pattern ) + { operator=( pattern ); } + + int match( const QString &str, int index=0, int *len=0, + bool indexIsStart = TRUE ) const; + int find( const QString& str, int index ) + { return match( str, index ); } + +protected: + void compile(); + const QChar *matchstr( uint *, const QChar *, uint, const QChar * ) const; + +private: + QString rxstring; // regular expression pattern + uint *rxdata; // compiled regexp pattern + int error; // error status + bool cs; // case sensitive + bool wc; // wildcard +}; + + +#endif // QREGEXP_H diff --git a/qtools/qshared.h b/qtools/qshared.h new file mode 100644 index 0000000..79fab7b --- /dev/null +++ b/qtools/qshared.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** +** 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 QShared +{ + QShared() { count = 1; } + void ref() { count++; } + bool deref() { return !--count; } + uint count; +}; + + +#endif // QSHARED_H diff --git a/qtools/qsortedlist.h b/qtools/qsortedlist.h new file mode 100644 index 0000000..aeadd90 --- /dev/null +++ b/qtools/qsortedlist.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** +** Definition of QList template/macro class +** +** Created : 920701 +** +** 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 QSORTEDLIST_H +#define QSORTEDLIST_H + +#ifndef QT_H +#include "qlist.h" +#endif // QT_H + + +template<class type> class Q_EXPORT QSortedList : public QList<type> +{ +public: + QSortedList() {} + QSortedList( const QSortedList<type> &l ) : QList<type>(l) {} + ~QSortedList() { clear(); } + QSortedList<type> &operator=(const QSortedList<type> &l) + { return (QSortedList<type>&)QList<type>::operator=(l); } + + virtual int compareItems( QCollection::Item s1, QCollection::Item s2 ) + { if ( *((type*)s1) == *((type*)s2) ) return 0; return ( *((type*)s1) < *((type*)s2) ? -1 : 1 ); } +}; + +#endif diff --git a/qtools/qstack.h b/qtools/qstack.h new file mode 100644 index 0000000..c23215c --- /dev/null +++ b/qtools/qstack.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** +** Definition of QStack template/macro class +** +** Created : 920917 +** +** 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 QSTACK_H +#define QSTACK_H + +#ifndef QT_H +#include "qglist.h" +#endif // QT_H + + +template<class type> class QStack : private QGList +{ +public: + QStack() {} + QStack( const QStack<type> &s ) : QGList(s) {} + ~QStack() { clear(); } + QStack<type> &operator=(const QStack<type> &s) + { return (QStack<type>&)QGList::operator=(s); } + bool autoDelete() const { return QCollection::autoDelete(); } + void setAutoDelete( bool del ) { QCollection::setAutoDelete(del); } + uint count() const { return QGList::count(); } + bool isEmpty() const { return QGList::count() == 0; } + void push( const type *d ) { QGList::insertAt(0,Item(d)); } + type *pop() { return (type *)QGList::takeFirst(); } + bool remove() { return QGList::removeFirst(); } + void clear() { QGList::clear(); } + type *top() const { return (type *)QGList::cfirst(); } + operator type *() const { return (type *)QGList::cfirst(); } + type *current() const { return (type *)QGList::cfirst(); } +private: + void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } +}; + + +#endif // QSTACK_H diff --git a/qtools/qstring.cpp b/qtools/qstring.cpp new file mode 100644 index 0000000..44d4e6b --- /dev/null +++ b/qtools/qstring.cpp @@ -0,0 +1,15205 @@ +/**************************************************************************** +** +** +** 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" +#include "qtextcodec.h" +#include "qstack.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> + + +/* ------------------------------------------------------------------------- + * unicode information + * these tables are generated from the unicode reference file + * ftp://ftp.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.html + * + * Lars Knoll <knoll@mpi-hd.mpg.de> + * ------------------------------------------------------------------------- + */ + +/* Perl script to generate (run perl -x tools/qstring.cpp) + +#!perl + +sub numberize +{ + my(%r, $n, $id); + for $id ( @_ ) { + $id="" if $id eq "EMPTY"; + $r{$id}=$n++; + } + return %r; +} + + +# 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 /;/; + $code = shift @fields; + 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 @fields; + $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; + } + @fields = split(" ", $decomp); + $tag = shift @fields; + $tag = $character_decomposition_tag{$tag}; + $decomp = join( ", 0x", @fields ); + $decomp = "0x".$decomp; + $decomposition{$code} = $decomp; + $decomposition_tag{$code} = $tag; + $decomposition_pos{$code} = $position; + $len = scalar(@fields); + $decomposition_len{$code} = $len; + +# we use canonical decompositions longer than 1 char +# and all arabic ligatures for the ligature table + if(($len > 1 and $tag == 1) or ($tag > 3 and $tag < 8)) { +# ligature to add... + $start = shift @fields; + $ligature{$start} = $ligature{$start}." ".$code; + } + +# adjust position + if($len != 0) { + $position += $len + 3; + } + + +} + +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 it's 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"; + + + +print "#endif\n\n"; +print "// END OF GENERATED DATA\n\n"; + + +__END__ + +*/ + + +// START OF GENERATED DATA + +#ifndef QT_NO_UNICODETABLES + +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, +}; + +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, + 0, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 0, 0, 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, 0, 0, 0, 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, 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, 15, 16, 15, 16, 0, 0, 15, + 16, 0, 0, 15, 16, 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, 0, 0, + 15, 16, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_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, 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, 0, 0, + 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, 3, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2, 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, 0, + 0, 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, 6, 6, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_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, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 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, 26, + 26, 26, 26, 28, 26, 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, 11, 11, 11, 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, 0, + 26, 26, 26, 26, 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, 11, 11, 11, 11, 11, 11, + 6, 0, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, + 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_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, 0, 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, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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_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, 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 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, 27, + 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, + 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, + 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_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_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, 0, 0, 0, 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, 0, 0, 0, + 0, 1, 1, 29, 29, 18, 18, 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, 20, 18, 18, 18, 0, +}; + +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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 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, 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, 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, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 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_34[] = { + 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_4D[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 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, 0, 30, 30, 30, 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_D7[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_DB[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12, + 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12, +}; + +static const Q_UINT8 ui_DF[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12, +}; + +static const Q_UINT8 ui_E0[] = { + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_F8[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, +}; + +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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, +}; + +static const Q_UINT8 ui_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, + 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, 0, 0, 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, 0, 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, 0, + 0, 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_08, ui_08, ui_08, ui_08, ui_08, ui_2E, ui_2F, + ui_30, ui_31, ui_32, ui_33, ui_34, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_4D, ui_34, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, 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_34, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_D7, + ui_D8, ui_08, ui_08, ui_DB, ui_D8, ui_08, ui_08, ui_DF, + ui_E0, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, ui_08, + ui_F8, ui_15, ui_FA, ui_FB, ui_15, ui_FD, ui_FE, ui_FF, +}; +// 15616 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, + 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, 0x2048, 0x003F, 0x0021, 0, + 16, 0x2049, 0x0021, 0x003F, 0, + 9, 0x2070, 0x0030, 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, + 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, 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, + 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, + 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, 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, + 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, 0x96FB, 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, + 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, + 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, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_04[] = { + 1688, 1693, 0, 1698, 0, 0, 0, 1703, + 0, 0, 0, 0, 1708, 1713, 1718, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1723, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1728, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1733, 1738, 0, 1743, 0, 0, 0, 1748, + 0, 0, 0, 0, 1753, 1758, 1763, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1768, 1773, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1778, 1783, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1788, 1793, 1798, 1803, 0, 0, 1808, 1813, + 0, 0, 1818, 1823, 1828, 1833, 1838, 1843, + 0, 0, 1848, 1853, 1858, 1863, 1868, 1873, + 0, 0, 1878, 1883, 1888, 1893, 1898, 1903, + 1908, 1913, 1918, 1923, 1928, 1933, 0, 0, + 1938, 1943, 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, 1948, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1953, 1958, 1963, 1968, 1973, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1978, 1983, 1988, + 1993, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1998, 0, 2003, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2008, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2013, 0, 0, 0, 0, 0, 0, + 0, 2018, 0, 0, 2023, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2028, 2033, 2038, 2043, 2048, 2053, 2058, 2063, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2068, 2073, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2078, 2083, 0, 2088, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2093, 0, 0, 2098, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2103, 2108, 2113, 0, 0, 2118, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 2123, 0, 0, 2128, 2133, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2138, 2143, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2148, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2153, 2158, 2163, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 2168, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2173, 0, 0, 0, 0, 0, 0, 2178, + 2183, 0, 2188, 2193, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2198, 2203, 2208, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2213, 0, 2218, 2223, 2228, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2233, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2238, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2243, 2248, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2253, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2257, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2262, 0, 0, + 0, 0, 2267, 0, 0, 0, 0, 2272, + 0, 0, 0, 0, 2277, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2282, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2287, 0, 2292, 2297, 2302, + 2307, 2312, 0, 0, 0, 0, 0, 0, + 0, 2317, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2322, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2327, 0, 0, + 0, 0, 2332, 0, 0, 0, 0, 2337, + 0, 0, 0, 0, 2342, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2347, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2352, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 2357, 2362, 2367, 2372, 2377, 2382, 2387, 2392, + 2397, 2402, 2407, 2412, 2417, 2422, 2427, 2432, + 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, + 2477, 2482, 2487, 2492, 2497, 2502, 2507, 2512, + 2517, 2522, 2527, 2532, 2537, 2542, 2547, 2552, + 2557, 2562, 2567, 2572, 2577, 2582, 2587, 2592, + 2597, 2602, 2607, 2612, 2617, 2622, 2627, 2632, + 2637, 2642, 2647, 2652, 2657, 2662, 2667, 2672, + 2677, 2682, 2687, 2692, 2697, 2702, 2707, 2712, + 2717, 2722, 2727, 2732, 2737, 2742, 2747, 2752, + 2757, 2762, 2767, 2772, 2777, 2782, 2787, 2792, + 2797, 2802, 2807, 2812, 2817, 2822, 2827, 2832, + 2837, 2842, 2847, 2852, 2857, 2862, 2867, 2872, + 2877, 2882, 2887, 2892, 2897, 2902, 2907, 2912, + 2917, 2922, 2927, 2932, 2937, 2942, 2947, 2952, + 2957, 2962, 2967, 2972, 2977, 2982, 2987, 2992, + 2997, 3002, 3007, 3012, 3017, 3022, 3027, 3032, + 3037, 3042, 3047, 3052, 3057, 3062, 3067, 3072, + 3077, 3082, 3087, 3092, 3097, 3102, 3107, 3112, + 3117, 3122, 3127, 3132, 0, 0, 0, 0, + 3137, 3142, 3147, 3152, 3157, 3162, 3167, 3172, + 3177, 3182, 3187, 3192, 3197, 3202, 3207, 3212, + 3217, 3222, 3227, 3232, 3237, 3242, 3247, 3252, + 3257, 3262, 3267, 3272, 3277, 3282, 3287, 3292, + 3297, 3302, 3307, 3312, 3317, 3322, 3327, 3332, + 3337, 3342, 3347, 3352, 3357, 3362, 3367, 3372, + 3377, 3382, 3387, 3392, 3397, 3402, 3407, 3412, + 3417, 3422, 3427, 3432, 3437, 3442, 3447, 3452, + 3457, 3462, 3467, 3472, 3477, 3482, 3487, 3492, + 3497, 3502, 3507, 3512, 3517, 3522, 3527, 3532, + 3537, 3542, 3547, 3552, 3557, 3562, 3567, 3572, + 3577, 3582, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_1F[] = { + 3587, 3592, 3597, 3602, 3607, 3612, 3617, 3622, + 3627, 3632, 3637, 3642, 3647, 3652, 3657, 3662, + 3667, 3672, 3677, 3682, 3687, 3692, 0, 0, + 3697, 3702, 3707, 3712, 3717, 3722, 0, 0, + 3727, 3732, 3737, 3742, 3747, 3752, 3757, 3762, + 3767, 3772, 3777, 3782, 3787, 3792, 3797, 3802, + 3807, 3812, 3817, 3822, 3827, 3832, 3837, 3842, + 3847, 3852, 3857, 3862, 3867, 3872, 3877, 3882, + 3887, 3892, 3897, 3902, 3907, 3912, 0, 0, + 3917, 3922, 3927, 3932, 3937, 3942, 0, 0, + 3947, 3952, 3957, 3962, 3967, 3972, 3977, 3982, + 0, 3987, 0, 3992, 0, 3997, 0, 4002, + 4007, 4012, 4017, 4022, 4027, 4032, 4037, 4042, + 4047, 4052, 4057, 4062, 4067, 4072, 4077, 4082, + 4087, 4092, 4096, 4101, 4105, 4110, 4114, 4119, + 4123, 4128, 4132, 4137, 4141, 4146, 0, 0, + 4150, 4155, 4160, 4165, 4170, 4175, 4180, 4185, + 4190, 4195, 4200, 4205, 4210, 4215, 4220, 4225, + 4230, 4235, 4240, 4245, 4250, 4255, 4260, 4265, + 4270, 4275, 4280, 4285, 4290, 4295, 4300, 4305, + 4310, 4315, 4320, 4325, 4330, 4335, 4340, 4345, + 4350, 4355, 4360, 4365, 4370, 4375, 4380, 4385, + 4390, 4395, 4400, 4405, 4410, 0, 4415, 4420, + 4425, 4430, 4435, 4440, 4444, 4449, 4454, 4458, + 4463, 4468, 4473, 4478, 4483, 0, 4488, 4493, + 4498, 4503, 4507, 4512, 4516, 4521, 4526, 4531, + 4536, 4541, 4546, 4551, 0, 0, 4555, 4560, + 4565, 4570, 4575, 4580, 0, 4584, 4589, 4594, + 4599, 4604, 4609, 4614, 4618, 4623, 4628, 4633, + 4638, 4643, 4648, 4653, 4657, 4662, 4667, 4671, + 0, 0, 4675, 4680, 4685, 0, 4690, 4695, + 4700, 4705, 4709, 4714, 4718, 4723, 4727, 0, +}; + +static const Q_UINT16 di_20[] = { + 4732, 4736, 4740, 4744, 4748, 4752, 4756, 4760, + 4764, 4768, 4772, 0, 0, 0, 0, 0, + 0, 4776, 0, 0, 0, 0, 0, 4780, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4785, 4789, 4794, 0, + 0, 0, 0, 0, 0, 0, 0, 4800, + 0, 0, 0, 4804, 4809, 0, 4815, 4820, + 0, 0, 0, 0, 4826, 0, 4831, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4836, 4841, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4846, 0, 0, 0, 4850, 4854, 4858, 4862, + 4866, 4870, 4874, 4878, 4882, 4886, 4890, 4894, + 4898, 4902, 4906, 4910, 4914, 4918, 4922, 4926, + 4930, 4934, 4938, 4942, 4946, 4950, 4954, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4958, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 4963, 4969, 4975, 4979, 0, 4984, 4990, 4996, + 0, 5000, 5005, 5009, 5013, 5017, 5021, 5025, + 5029, 5033, 5037, 5041, 0, 5045, 5049, 0, + 0, 5054, 5058, 5062, 5066, 5070, 0, 0, + 5074, 5079, 5085, 0, 5090, 0, 5094, 0, + 5098, 0, 5102, 5106, 5110, 5114, 0, 5118, + 5122, 5126, 0, 5130, 5134, 5138, 5142, 5146, + 5150, 5154, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5158, 5164, 5170, 5176, 5182, + 5188, 5194, 5200, 5206, 5212, 5218, 5224, 5230, + 5235, 5239, 5244, 5250, 5255, 5259, 5264, 5270, + 5277, 5282, 5286, 5291, 5297, 5301, 5305, 5309, + 5313, 5317, 5322, 5328, 5333, 5337, 5342, 5348, + 5355, 5360, 5364, 5369, 5375, 5379, 5383, 5387, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5391, 5396, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5401, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5406, 5411, 5416, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 5421, 0, 0, 0, + 0, 5426, 0, 0, 5431, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5436, 0, 5441, 0, + 0, 0, 0, 0, 5446, 5451, 0, 5457, + 5462, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5468, 0, 0, 5473, 0, 0, 5478, + 0, 5483, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5488, 0, 5493, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5498, 5503, 5508, + 5513, 5518, 0, 0, 5523, 5528, 0, 0, + 5533, 5538, 0, 0, 0, 0, 0, 0, + 5543, 5548, 0, 0, 5553, 5558, 0, 0, + 5563, 5568, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5573, 5578, 5583, 5588, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5593, 5598, 5603, 5608, 0, 0, 0, 0, + 0, 0, 5613, 5618, 5623, 5628, 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, 5633, 5637, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 5641, 5645, 5649, 5653, 5657, 5661, 5665, 5669, + 5673, 5677, 5682, 5687, 5692, 5697, 5702, 5707, + 5712, 5717, 5722, 5727, 5732, 5738, 5744, 5750, + 5756, 5762, 5768, 5774, 5780, 5786, 5793, 5800, + 5807, 5814, 5821, 5828, 5835, 5842, 5849, 5856, + 5863, 5868, 5873, 5878, 5883, 5888, 5893, 5898, + 5903, 5908, 5914, 5920, 5926, 5932, 5938, 5944, + 5950, 5956, 5962, 5968, 5974, 5980, 5986, 5992, + 5998, 6004, 6010, 6016, 6022, 6028, 6034, 6040, + 6046, 6052, 6058, 6064, 6070, 6076, 6082, 6088, + 6094, 6100, 6106, 6112, 6118, 6124, 6130, 6134, + 6138, 6142, 6146, 6150, 6154, 6158, 6162, 6166, + 6170, 6174, 6178, 6182, 6186, 6190, 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, 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, 6342, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6346, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 di_2F[] = { + 6350, 6354, 6358, 6362, 6366, 6370, 6374, 6378, + 6382, 6386, 6390, 6394, 6398, 6402, 6406, 6410, + 6414, 6418, 6422, 6426, 6430, 6434, 6438, 6442, + 6446, 6450, 6454, 6458, 6462, 6466, 6470, 6474, + 6478, 6482, 6486, 6490, 6494, 6498, 6502, 6506, + 6510, 6514, 6518, 6522, 6526, 6530, 6534, 6538, + 6542, 6546, 6550, 6554, 6558, 6562, 6566, 6570, + 6574, 6578, 6582, 6586, 6590, 6594, 6598, 6602, + 6606, 6610, 6614, 6618, 6622, 6626, 6630, 6634, + 6638, 6642, 6646, 6650, 6654, 6658, 6662, 6666, + 6670, 6674, 6678, 6682, 6686, 6690, 6694, 6698, + 6702, 6706, 6710, 6714, 6718, 6722, 6726, 6730, + 6734, 6738, 6742, 6746, 6750, 6754, 6758, 6762, + 6766, 6770, 6774, 6778, 6782, 6786, 6790, 6794, + 6798, 6802, 6806, 6810, 6814, 6818, 6822, 6826, + 6830, 6834, 6838, 6842, 6846, 6850, 6854, 6858, + 6862, 6866, 6870, 6874, 6878, 6882, 6886, 6890, + 6894, 6898, 6902, 6906, 6910, 6914, 6918, 6922, + 6926, 6930, 6934, 6938, 6942, 6946, 6950, 6954, + 6958, 6962, 6966, 6970, 6974, 6978, 6982, 6986, + 6990, 6994, 6998, 7002, 7006, 7010, 7014, 7018, + 7022, 7026, 7030, 7034, 7038, 7042, 7046, 7050, + 7054, 7058, 7062, 7066, 7070, 7074, 7078, 7082, + 7086, 7090, 7094, 7098, 7102, 7106, 7110, 7114, + 7118, 7122, 7126, 7130, 7134, 7138, 7142, 7146, + 7150, 7154, 7158, 7162, 7166, 7170, 7174, 7178, + 7182, 7186, 7190, 7194, 7198, 7202, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 7206, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7210, 0, + 7214, 7218, 7222, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7226, 0, 7231, 0, + 7236, 0, 7241, 0, 7246, 0, 7251, 0, + 7256, 0, 7261, 0, 7266, 0, 7271, 0, + 7276, 0, 7281, 0, 0, 7286, 0, 7291, + 0, 7296, 0, 0, 0, 0, 0, 0, + 7301, 7306, 0, 7311, 7316, 0, 7321, 7326, + 0, 7331, 7336, 0, 7341, 7346, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7351, 0, 0, 0, + 0, 0, 0, 7356, 7361, 0, 7366, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7371, 0, 7376, 0, + 7381, 0, 7386, 0, 7391, 0, 7396, 0, + 7401, 0, 7406, 0, 7411, 0, 7416, 0, + 7421, 0, 7426, 0, 0, 7431, 0, 7436, + 0, 7441, 0, 0, 0, 0, 0, 0, + 7446, 7451, 0, 7456, 7461, 0, 7466, 7471, + 0, 7476, 7481, 0, 7486, 7491, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7496, 0, 0, 7501, + 7506, 7511, 7516, 0, 0, 0, 7521, 0, +}; + +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, 7526, 7530, 7534, 7538, 7542, 7546, 7550, + 7554, 7558, 7562, 7566, 7570, 7574, 7578, 7582, + 7586, 7590, 7594, 7598, 7602, 7606, 7610, 7614, + 7618, 7622, 7626, 7630, 7634, 7638, 7642, 7646, + 7650, 7654, 7658, 7662, 7666, 7670, 7674, 7678, + 7682, 7686, 7690, 7694, 7698, 7702, 7706, 7710, + 7714, 7718, 7722, 7726, 7730, 7734, 7738, 7742, + 7746, 7750, 7754, 7758, 7762, 7766, 7770, 7774, + 7778, 7782, 7786, 7790, 7794, 7798, 7802, 7806, + 7810, 7814, 7818, 7822, 7826, 7830, 7834, 7838, + 7842, 7846, 7850, 7854, 7858, 7862, 7866, 7870, + 7874, 7878, 7882, 7886, 7890, 7894, 7898, 0, + 0, 0, 7902, 7906, 7910, 7914, 7918, 7922, + 7926, 7930, 7934, 7938, 7942, 7946, 7950, 7954, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 7958, 7964, 7970, 7976, 7982, 7988, 7994, 8000, + 8006, 8012, 8018, 8024, 8030, 8036, 8042, 8049, + 8056, 8063, 8070, 8077, 8084, 8091, 8098, 8105, + 8112, 8119, 8126, 8133, 8140, 0, 0, 0, + 8147, 8153, 8159, 8165, 8171, 8177, 8183, 8189, + 8195, 8201, 8207, 8213, 8219, 8225, 8231, 8237, + 8243, 8249, 8255, 8261, 8267, 8273, 8279, 8285, + 8291, 8297, 8303, 8309, 8315, 8321, 8327, 8333, + 8339, 8345, 8351, 8357, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8363, 8367, 8371, 8375, 8379, 8383, 8387, 8391, + 8395, 8399, 8403, 8407, 8411, 8415, 8419, 8424, + 8429, 8434, 8439, 8444, 8449, 8454, 8459, 8464, + 8469, 8474, 8479, 8484, 0, 0, 0, 0, + 8489, 8493, 8497, 8501, 8505, 8509, 8513, 8517, + 8521, 8525, 8529, 8533, 8537, 8541, 8545, 8549, + 8553, 8557, 8561, 8565, 8569, 8573, 8577, 8581, + 8585, 8589, 8593, 8597, 8601, 8605, 8609, 8613, + 8617, 8621, 8625, 8629, 8633, 8637, 8641, 8645, + 8649, 8653, 8657, 8661, 8665, 8669, 8673, 8677, + 8681, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8685, 8690, 8695, 8700, 8705, 8710, 8715, 8720, + 8725, 8730, 8736, 8742, 0, 0, 0, 0, + 8748, 8752, 8756, 8760, 8764, 8768, 8772, 8776, + 8780, 8784, 8788, 8792, 8796, 8800, 8804, 8808, + 8812, 8816, 8820, 8824, 8828, 8832, 8836, 8840, + 8844, 8848, 8852, 8856, 8860, 8864, 8868, 8872, + 8876, 8880, 8884, 8888, 8892, 8896, 8900, 8904, + 8908, 8912, 8916, 8920, 8924, 8928, 8932, 0, +}; + +static const Q_UINT16 di_33[] = { + 8936, 8943, 8950, 8957, 8963, 8970, 8976, 8982, + 8990, 8997, 9003, 9009, 9015, 9022, 9029, 9035, + 9041, 9046, 9052, 9059, 9066, 9071, 9079, 9088, + 9096, 9102, 9110, 9118, 9125, 9131, 9137, 9143, + 9150, 9158, 9165, 9171, 9177, 9183, 9188, 9193, + 9198, 9203, 9209, 9215, 9223, 9229, 9236, 9244, + 9250, 9255, 9260, 9268, 9275, 9283, 9289, 9297, + 9302, 9308, 9314, 9320, 9326, 9332, 9339, 9345, + 9350, 9356, 9362, 9368, 9375, 9381, 9387, 9393, + 9401, 9408, 9413, 9421, 9426, 9433, 9440, 9446, + 9452, 9458, 9465, 9470, 9476, 9483, 9488, 9496, + 9502, 9507, 9512, 9517, 9522, 9527, 9532, 9537, + 9542, 9547, 9552, 9558, 9564, 9570, 9576, 9582, + 9588, 9594, 9600, 9606, 9612, 9618, 9624, 9630, + 9636, 9642, 9648, 9653, 9658, 9664, 9669, 0, + 0, 0, 0, 9674, 9679, 9684, 9689, 9694, + 9701, 9706, 9711, 9716, 9721, 9726, 9731, 9736, + 9741, 9747, 9754, 9759, 9764, 9769, 9774, 9779, + 9784, 9789, 9795, 9801, 9807, 9813, 9818, 9823, + 9828, 9833, 9838, 9843, 9848, 9853, 9858, 9863, + 9869, 9875, 9880, 9886, 9892, 9898, 9903, 9909, + 9915, 9922, 9927, 9933, 9939, 9945, 9951, 9959, + 9968, 9973, 9978, 9983, 9988, 9993, 9998, 10003, + 10008, 10013, 10018, 10023, 10028, 10033, 10038, 10043, + 10048, 10053, 10058, 10065, 10070, 10075, 10080, 10087, + 10093, 10098, 10103, 10108, 10113, 10118, 10123, 10128, + 10133, 10138, 10143, 10149, 10154, 10159, 10165, 10171, + 10176, 10183, 10189, 10194, 10199, 10204, 0, 0, + 10209, 10214, 10219, 10224, 10229, 10234, 10239, 10244, + 10249, 10254, 10260, 10266, 10272, 10278, 10284, 10290, + 10296, 10302, 10308, 10314, 10320, 10326, 10332, 10338, + 10344, 10350, 10356, 10362, 10368, 10374, 10380, 0, +}; + +static const Q_UINT16 di_F9[] = { + 10386, 10390, 10394, 10398, 10402, 10406, 10410, 10414, + 10418, 10422, 10426, 10430, 10434, 10438, 10442, 10446, + 10450, 10454, 10458, 10462, 10466, 10470, 10474, 10478, + 10482, 10486, 10490, 10494, 10498, 10502, 10506, 10510, + 10514, 10518, 10522, 10526, 10530, 10534, 10538, 10542, + 10546, 10550, 10554, 10558, 10562, 10566, 10570, 10574, + 10578, 10582, 10586, 10590, 10594, 10598, 10602, 10606, + 10610, 10614, 10618, 10622, 10626, 10630, 10634, 10638, + 10642, 10646, 10650, 10654, 10658, 10662, 10666, 10670, + 10674, 10678, 10682, 10686, 10690, 10694, 10698, 10702, + 10706, 10710, 10714, 10718, 10722, 10726, 10730, 10734, + 10738, 10742, 10746, 10750, 10754, 10758, 10762, 10766, + 10770, 10774, 10778, 10782, 10786, 10790, 10794, 10798, + 10802, 10806, 10810, 10814, 10818, 10822, 10826, 10830, + 10834, 10838, 10842, 10846, 10850, 10854, 10858, 10862, + 10866, 10870, 10874, 10878, 10882, 10886, 10890, 10894, + 10898, 10902, 10906, 10910, 10914, 10918, 10922, 10926, + 10930, 10934, 10938, 10942, 10946, 10950, 10954, 10958, + 10962, 10966, 10970, 10974, 10978, 10982, 10986, 10990, + 10994, 10998, 11002, 11006, 11010, 11014, 11018, 11022, + 11026, 11030, 11034, 11038, 11042, 11046, 11050, 11054, + 11058, 11062, 11066, 11070, 11074, 11078, 11082, 11086, + 11090, 11094, 11098, 11102, 11106, 11110, 11114, 11118, + 11122, 11126, 11130, 11134, 11138, 11142, 11146, 11150, + 11154, 11158, 11162, 11166, 11170, 11174, 11178, 11182, + 11186, 11190, 11194, 11198, 11202, 11206, 11210, 11214, + 11218, 11222, 11226, 11230, 11234, 11238, 11242, 11246, + 11250, 11254, 11258, 11262, 11266, 11270, 11274, 11278, + 11282, 11286, 11290, 11294, 11298, 11302, 11306, 11310, + 11314, 11318, 11322, 11326, 11330, 11334, 11338, 11342, + 11346, 11350, 11354, 11358, 11362, 11366, 11370, 11374, + 11378, 11382, 11386, 11390, 11394, 11398, 11402, 11406, +}; + +static const Q_UINT16 di_FA[] = { + 11410, 11414, 11418, 11422, 11426, 11430, 11434, 11438, + 11442, 11446, 11450, 11454, 11458, 11462, 0, 0, + 11466, 0, 11470, 0, 0, 11474, 11478, 11482, + 11486, 11490, 11494, 11498, 11502, 11506, 11510, 0, + 11514, 0, 11518, 0, 0, 11522, 11526, 0, + 0, 0, 11530, 11534, 11538, 11542, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 11546, 11551, 11556, 11561, 11567, 11573, 11578, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11583, 11588, 11593, 11598, 11603, + 0, 0, 0, 0, 0, 11608, 0, 11613, + 11618, 11622, 11626, 11630, 11634, 11638, 11642, 11646, + 11650, 11654, 11658, 11663, 11668, 11673, 11678, 11683, + 11688, 11693, 11698, 11703, 11708, 11713, 11718, 0, + 11723, 11728, 11733, 11738, 11743, 0, 11748, 0, + 11753, 11758, 0, 11763, 11768, 0, 11773, 11778, + 11783, 11788, 11793, 11798, 11803, 11808, 11813, 11818, + 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, 12035, 12039, 12043, + 12047, 12051, 12055, 12059, 12063, 12067, 12071, 12075, + 12079, 12083, 12087, 12091, 12095, 12099, 12103, 12107, + 12111, 12115, 12119, 12123, 12127, 12131, 12135, 12139, + 12143, 12147, 12151, 12155, 12159, 12163, 12167, 12171, + 12175, 12179, 12183, 12187, 12191, 12195, 12199, 12203, + 12207, 12211, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12215, 12219, 12223, 12227, 12231, + 12235, 12239, 12243, 12247, 12251, 12255, 12259, 12263, + 12267, 12271, 12275, 12279, 12283, 12287, 12291, 12295, + 12299, 12303, 12307, 12312, 12317, 12322, 12327, 12332, + 12337, 12342, 12347, 12352, 12357, 12362, 12367, 12372, + 12377, 12382, 12387, 12392, 12397, 12401, 12405, 12409, +}; + +static const Q_UINT16 di_FC[] = { + 12413, 12418, 12423, 12428, 12433, 12438, 12443, 12448, + 12453, 12458, 12463, 12468, 12473, 12478, 12483, 12488, + 12493, 12498, 12503, 12508, 12513, 12518, 12523, 12528, + 12533, 12538, 12543, 12548, 12553, 12558, 12563, 12568, + 12573, 12578, 12583, 12588, 12593, 12598, 12603, 12608, + 12613, 12618, 12623, 12628, 12633, 12638, 12643, 12648, + 12653, 12658, 12663, 12668, 12673, 12678, 12683, 12688, + 12693, 12698, 12703, 12708, 12713, 12718, 12723, 12728, + 12733, 12738, 12743, 12748, 12753, 12758, 12763, 12768, + 12773, 12778, 12783, 12788, 12793, 12798, 12803, 12808, + 12813, 12818, 12823, 12828, 12833, 12838, 12843, 12848, + 12853, 12858, 12863, 12868, 12873, 12878, 12883, 12889, + 12895, 12901, 12907, 12913, 12919, 12924, 12929, 12934, + 12939, 12944, 12949, 12954, 12959, 12964, 12969, 12974, + 12979, 12984, 12989, 12994, 12999, 13004, 13009, 13014, + 13019, 13024, 13029, 13034, 13039, 13044, 13049, 13054, + 13059, 13064, 13069, 13074, 13079, 13084, 13089, 13094, + 13099, 13104, 13109, 13114, 13119, 13124, 13129, 13134, + 13139, 13144, 13149, 13154, 13159, 13164, 13169, 13174, + 13179, 13184, 13189, 13194, 13199, 13204, 13209, 13214, + 13219, 13224, 13229, 13234, 13239, 13244, 13249, 13254, + 13259, 13264, 13269, 13274, 13279, 13284, 13289, 13294, + 13299, 13304, 13309, 13314, 13319, 13324, 13329, 13334, + 13339, 13344, 13349, 13354, 13359, 13364, 13369, 13374, + 13379, 13384, 13389, 13394, 13399, 13404, 13409, 13414, + 13419, 13424, 13429, 13434, 13439, 13444, 13449, 13454, + 13459, 13464, 13469, 13474, 13479, 13484, 13489, 13494, + 13499, 13504, 13509, 13514, 13519, 13524, 13529, 13534, + 13539, 13544, 13549, 13554, 13559, 13564, 13569, 13574, + 13579, 13584, 13589, 13594, 13599, 13604, 13609, 13614, + 13619, 13624, 13629, 13635, 13641, 13647, 13652, 13657, + 13662, 13667, 13672, 13677, 13682, 13687, 13692, 13697, +}; + +static const Q_UINT16 di_FD[] = { + 13702, 13707, 13712, 13717, 13722, 13727, 13732, 13737, + 13742, 13747, 13752, 13757, 13762, 13767, 13772, 13777, + 13782, 13787, 13792, 13797, 13802, 13807, 13812, 13817, + 13822, 13827, 13832, 13837, 13842, 13847, 13852, 13857, + 13862, 13867, 13872, 13877, 13882, 13887, 13892, 13897, + 13902, 13907, 13912, 13917, 13922, 13927, 13932, 13937, + 13942, 13947, 13952, 13957, 13962, 13967, 13972, 13977, + 13982, 13987, 13992, 13997, 14002, 14007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14012, 14018, 14024, 14030, 14036, 14042, 14048, 14054, + 14060, 14066, 14072, 14078, 14084, 14090, 14096, 14102, + 14108, 14114, 14120, 14126, 14132, 14138, 14144, 14150, + 14156, 14162, 14168, 14174, 14180, 14186, 14192, 14198, + 14204, 14210, 14216, 14222, 14228, 14234, 14240, 14246, + 14252, 14258, 14264, 14270, 14276, 14282, 14288, 14294, + 14300, 14306, 14312, 14318, 14324, 14330, 14336, 14342, + 14348, 14354, 14360, 14366, 14372, 14378, 14384, 14390, + 0, 0, 14396, 14402, 14408, 14414, 14420, 14426, + 14432, 14438, 14444, 14450, 14456, 14462, 14468, 14474, + 14480, 14486, 14492, 14498, 14504, 14510, 14516, 14522, + 14528, 14534, 14540, 14546, 14552, 14558, 14564, 14570, + 14576, 14582, 14588, 14594, 14600, 14606, 14612, 14618, + 14624, 14630, 14636, 14642, 14648, 14654, 14660, 14666, + 14672, 14678, 14684, 14690, 14696, 14702, 14708, 14714, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14720, 14726, 14732, 14739, 14746, 14753, 14760, 14767, + 14774, 14781, 14787, 14808, 0, 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, + 14819, 14823, 14827, 14831, 14835, 14839, 14843, 14847, + 14851, 14855, 14859, 14863, 14867, 14871, 14875, 14879, + 14883, 14887, 14891, 14895, 14899, 0, 0, 0, + 0, 14903, 14907, 14911, 14915, 14919, 14923, 14927, + 14931, 14935, 14939, 0, 14943, 14947, 14951, 14955, + 14959, 14963, 14967, 14971, 14975, 14979, 14983, 14987, + 14991, 14995, 14999, 15003, 15007, 15011, 15015, 0, + 15019, 15023, 15027, 15031, 0, 0, 0, 0, + 15035, 15040, 15045, 0, 15050, 0, 15055, 15060, + 15065, 15070, 15075, 15080, 15085, 15090, 15095, 15100, + 15105, 15109, 15113, 15117, 15121, 15125, 15129, 15133, + 15137, 15141, 15145, 15149, 15153, 15157, 15161, 15165, + 15169, 15173, 15177, 15181, 15185, 15189, 15193, 15197, + 15201, 15205, 15209, 15213, 15217, 15221, 15225, 15229, + 15233, 15237, 15241, 15245, 15249, 15253, 15257, 15261, + 15265, 15269, 15273, 15277, 15281, 15285, 15289, 15293, + 15297, 15301, 15305, 15309, 15313, 15317, 15321, 15325, + 15329, 15333, 15337, 15341, 15345, 15349, 15353, 15357, + 15361, 15365, 15369, 15373, 15377, 15381, 15385, 15389, + 15393, 15397, 15401, 15405, 15409, 15413, 15417, 15421, + 15425, 15429, 15433, 15437, 15441, 15445, 15449, 15453, + 15457, 15461, 15465, 15469, 15473, 15477, 15481, 15485, + 15489, 15493, 15497, 15501, 15505, 15509, 15513, 15517, + 15521, 15525, 15529, 15533, 15537, 15541, 15545, 15549, + 15553, 15557, 15561, 15565, 15569, 15573, 15578, 15583, + 15588, 15593, 15598, 15603, 15608, 0, 0, 0, +}; + +static const Q_UINT16 di_FF[] = { + 0, 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, 0, + 0, 15989, 15993, 15997, 16001, 16005, 16009, 16013, + 16017, 16021, 16025, 16029, 16033, 16037, 16041, 16045, + 16049, 16053, 16057, 16061, 16065, 16069, 16073, 16077, + 16081, 16085, 16089, 16093, 16097, 16101, 16105, 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, 0, + 0, 0, 16365, 16369, 16373, 16377, 16381, 16385, + 0, 0, 16389, 16393, 16397, 16401, 16405, 16409, + 0, 0, 16413, 16417, 16421, 16425, 16429, 16433, + 0, 0, 16437, 16441, 16445, 0, 0, 0, + 16449, 16453, 16457, 16461, 16465, 16469, 16473, 0, + 16477, 16481, 16485, 16489, 16493, 16497, 16501, 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_07, 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, +}; +// 68080 bytes + +static const Q_UINT16 ligature_map [] = { + 0, + 12883, 12889, 12895, 12901, 12907, 12913, 15035, 15045, 15050, 15055, 15065, 15075, 15085, 15095, 0, + 5503, 0, + 5488, 0, + 5508, 0, + 67, 72, 77, 82, 87, 92, 332, 342, 352, 966, 1196, 1206, 1346, 2357, 3137, 3147, 0, + 2367, 2377, 2387, 0, + 97, 362, 372, 382, 392, 0, + 402, 2407, 2417, 2427, 2437, 2447, 0, + 102, 107, 112, 117, 412, 422, 432, 442, 452, 1216, 1226, 1356, 2477, 2487, 3257, 3267, 3277, 0, + 2507, 0, + 462, 472, 482, 492, 1076, 1146, 2517, 0, + 502, 1336, 2527, 2537, 2547, 2557, 2567, 0, + 122, 127, 132, 137, 512, 522, 532, 542, 552, 976, 1236, 1246, 2577, 3337, 3347, 0, + 567, 0, + 577, 1086, 2597, 2607, 2617, 0, + 587, 597, 607, 2627, 2647, 2657, 0, + 2667, 2677, 2687, 0, + 142, 627, 637, 647, 1156, 2697, 2707, 2717, 2727, 0, + 147, 152, 157, 162, 167, 662, 672, 682, 901, 986, 1096, 1256, 1266, 1386, 3357, 3367, 0, + 2777, 2787, 0, + 692, 702, 712, 1276, 1286, 2797, 2807, 2827, 0, + 722, 732, 742, 752, 1316, 2837, 2847, 0, + 762, 772, 1326, 2887, 2897, 2907, 2917, 0, + 172, 177, 182, 187, 782, 792, 802, 812, 822, 832, 911, 996, 1296, 1306, 2927, 2937, 2947, 3477, 3487, 0, + 2977, 2987, 0, + 842, 2997, 3007, 3017, 3027, 3037, 0, + 3047, 3057, 0, + 192, 852, 862, 1406, 3067, 3547, 3557, 3567, 3577, 0, + 867, 877, 887, 3077, 3087, 3097, 0, + 197, 202, 207, 212, 217, 222, 337, 347, 357, 971, 1201, 1211, 1351, 2362, 3142, 3152, 0, + 2372, 2382, 2392, 0, + 227, 367, 377, 387, 397, 0, + 407, 2412, 2422, 2432, 2442, 2452, 0, + 232, 237, 242, 247, 417, 427, 437, 447, 457, 1221, 1231, 1361, 2482, 2492, 3262, 3272, 3282, 0, + 2512, 0, + 467, 477, 487, 497, 1081, 1151, 2522, 0, + 507, 1341, 2532, 2542, 2552, 2562, 2572, 3107, 0, + 252, 257, 262, 267, 517, 527, 537, 547, 981, 1241, 1251, 2582, 3342, 3352, 0, + 572, 1126, 0, + 582, 1091, 2602, 2612, 2622, 0, + 592, 602, 612, 2632, 2652, 2662, 0, + 2672, 2682, 2692, 0, + 272, 632, 642, 652, 1161, 2702, 2712, 2722, 2732, 0, + 277, 282, 287, 292, 297, 667, 677, 687, 906, 991, 1101, 1261, 1271, 1391, 3362, 3372, 0, + 2782, 2792, 0, + 697, 707, 717, 1281, 1291, 2802, 2812, 2832, 0, + 727, 737, 747, 757, 1321, 2842, 2852, 0, + 767, 777, 1331, 2892, 2902, 2912, 2922, 3112, 0, + 302, 307, 312, 317, 787, 797, 807, 817, 827, 837, 916, 1001, 1301, 1311, 2932, 2942, 2952, 3482, 3492, 0, + 2982, 2992, 0, + 847, 3002, 3012, 3022, 3032, 3042, 3117, 0, + 3052, 3062, 0, + 322, 327, 857, 1411, 3072, 3122, 3552, 3562, 3572, 3582, 0, + 872, 882, 892, 3082, 3092, 3102, 0, + 1537, 4468, 4662, 0, + 3157, 3167, 3177, 3187, 0, + 1046, 0, + 1166, 0, + 1066, 1176, 0, + 2397, 0, + 3287, 3297, 3307, 3317, 0, + 2587, 0, + 3377, 3387, 3397, 3407, 0, + 1376, 2737, 2747, 0, + 1366, 0, + 1186, 0, + 1006, 1016, 1026, 1036, 0, + 3162, 3172, 3182, 3192, 0, + 1051, 0, + 1171, 0, + 1071, 1181, 0, + 2402, 0, + 3292, 3302, 3312, 3322, 0, + 2592, 0, + 3382, 3392, 3402, 3412, 0, + 1381, 2742, 2752, 0, + 1371, 0, + 1191, 0, + 1011, 1021, 1031, 1041, 0, + 3207, 3217, 3227, 3237, 0, + 3212, 3222, 3232, 3242, 0, + 2457, 2467, 0, + 2462, 2472, 0, + 2757, 2767, 0, + 2762, 2772, 0, + 2857, 0, + 2862, 0, + 2867, 0, + 2872, 0, + 2957, 0, + 2962, 0, + 2967, 0, + 2972, 0, + 3132, 0, + 3427, 3437, 3447, 3457, 3467, 0, + 3432, 3442, 3452, 3462, 3472, 0, + 3497, 3507, 3517, 3527, 3537, 0, + 3502, 3512, 3522, 3532, 3542, 0, + 1116, 0, + 1106, 0, + 1111, 0, + 1056, 0, + 1061, 0, + 2497, 0, + 2502, 0, + 1396, 0, + 1401, 0, + 1121, 0, + 1514, 0, + 1542, 3627, 3632, 4425, 4430, 4435, 4444, 0, + 1551, 3697, 3702, 4498, 0, + 1556, 3767, 3772, 4507, 4516, 0, + 1561, 1586, 3847, 3852, 4565, 4570, 4575, 0, + 1566, 3917, 3922, 4700, 0, + 4657, 0, + 1571, 1591, 3987, 4638, 4643, 4648, 0, + 1576, 4047, 4052, 4709, 4718, 0, + 4410, 0, + 4483, 0, + 1596, 3587, 3592, 4087, 4390, 4395, 4405, 4415, 0, + 1601, 3667, 3672, 4096, 0, + 1606, 3727, 3732, 4105, 4478, 4488, 0, + 1611, 1621, 3807, 3812, 4114, 4536, 4541, 4555, 0, + 1631, 3887, 3892, 4123, 0, + 4618, 4623, 0, + 1626, 1636, 3947, 3952, 4132, 4599, 4604, 4628, 0, + 1641, 4007, 4012, 4141, 4680, 4690, 0, + 1581, 4546, 4560, 0, + 1616, 4609, 4633, 0, + 4685, 0, + 1658, 1663, 0, + 1703, 0, + 1788, 1798, 0, + 1698, 0, + 1688, 1693, 1808, 0, + 1778, 1828, 0, + 1838, 0, + 1713, 1723, 1848, 1858, 0, + 1708, 0, + 1868, 0, + 1718, 1898, 1908, 1918, 0, + 1928, 0, + 1938, 0, + 1888, 0, + 1793, 1803, 0, + 1743, 0, + 1733, 1738, 1813, 0, + 1783, 1833, 0, + 1843, 0, + 1728, 1758, 1853, 1863, 0, + 1753, 0, + 1873, 0, + 1763, 1903, 1913, 1923, 0, + 1933, 0, + 1943, 0, + 1893, 0, + 1748, 0, + 1768, 0, + 1773, 0, + 1818, 0, + 1823, 0, + 1878, 0, + 1883, 0, + 11678, 11683, 11688, 0, + 11693, 11803, 0, + 11698, 0, + 11703, 0, + 11708, 0, + 11713, 11798, 0, + 11718, 0, + 11723, 0, + 11608, 11728, 0, + 11733, 0, + 11738, 11808, 0, + 11743, 0, + 11748, 0, + 11753, 0, + 11758, 0, + 11763, 0, + 11768, 11813, 0, + 11773, 0, + 11778, 0, + 11783, 0, + 11658, 11663, 11788, 0, + 11793, 0, + 11613, 0, + 15105, 0, + 15109, 15113, 0, + 15117, 15121, 0, + 15125, 15129, 0, + 15133, 15137, 0, + 12307, 12312, 12317, 12322, 12327, 12332, 12337, 12342, 12347, 12352, 12357, 12362, 12367, 12372, 12377, 12382, 12387, 12392, 12413, 12418, 12423, 12428, 12433, 12919, 12924, 12929, 12934, 12939, 12944, 13174, 13179, 13184, 13189, 13194, 13534, 13539, 15141, 15145, 15149, 15153, 0, + 14732, 14739, 1958, 1968, 14007, 14002, 1953, 15157, 15161, 0, + 14468, 14684, 12448, 12453, 12458, 12463, 12949, 12954, 12959, 12964, 12969, 12974, 13199, 13204, 13209, 13214, 13219, 13544, 13549, 12438, 12443, 15165, 15169, 15173, 15177, 0, + 15181, 15185, 0, + 14012, 14018, 14024, 14030, 14036, 14042, 14048, 14054, 14474, 14480, 14486, 14492, 14498, 14504, 13229, 13234, 13239, 13244, 13559, 13554, 12468, 12473, 12478, 12483, 12488, 12493, 12979, 12984, 12989, 12994, 12999, 13004, 13224, 15189, 15193, 15197, 15201, 0, + 12498, 12503, 12508, 12513, 13009, 13014, 13019, 13024, 13029, 13034, 13249, 13564, 13569, 15205, 15209, 15213, 15217, 0, + 14808, 14660, 14060, 14066, 14510, 14516, 14522, 12518, 12523, 13254, 13259, 13707, 13712, 13847, 13852, 15221, 15225, 15229, 15233, 0, + 14072, 14078, 14666, 13264, 13269, 13697, 13702, 13842, 13837, 12528, 12533, 15237, 15241, 15245, 15249, 0, + 12538, 12543, 12548, 13274, 13279, 13717, 13722, 13857, 13862, 15253, 15257, 15261, 15265, 0, + 15269, 15273, 0, + 12868, 15277, 15281, 0, + 14760, 12873, 15285, 15289, 0, + 15293, 15297, 0, + 14084, 14090, 14096, 14102, 14108, 14114, 14120, 14126, 14528, 14708, 13677, 13682, 13772, 13817, 13822, 13912, 13947, 13962, 13967, 13972, 12553, 12558, 12563, 12568, 13284, 13289, 13294, 13299, 13574, 13579, 15301, 15305, 15309, 15313, 0, + 14150, 14156, 14162, 14168, 14174, 14180, 14186, 14540, 13767, 13827, 13832, 13887, 13892, 13897, 13902, 13907, 13927, 13932, 13937, 13942, 13952, 13977, 13982, 13987, 13584, 13589, 13687, 13692, 13747, 13752, 13757, 13762, 15317, 15321, 15325, 15329, 0, + 14787, 14753, 14781, 14138, 14132, 14144, 14534, 14702, 14720, 12573, 12578, 13304, 13309, 13314, 13727, 13732, 13777, 13872, 13917, 13867, 15333, 15337, 15341, 15345, 0, + 14192, 14198, 14204, 14546, 13319, 13324, 13329, 13334, 13737, 13742, 13782, 13877, 13882, 13922, 12583, 12588, 12593, 12598, 15349, 15353, 15357, 15361, 0, + 14210, 14216, 14222, 14228, 13647, 13652, 13787, 13792, 13992, 13957, 12603, 12608, 13339, 15365, 15369, 15373, 15377, 0, + 12613, 13344, 13997, 15381, 15385, 15389, 15393, 0, + 14767, 14696, 14234, 14240, 14246, 14252, 14612, 12618, 12623, 13349, 13354, 13657, 13662, 13797, 13802, 15397, 15401, 15405, 15409, 0, + 14258, 14264, 14270, 13359, 13364, 13667, 13672, 13812, 13807, 12628, 12633, 15413, 15417, 15421, 15425, 0, + 13629, 13635, 13641, 15040, 15060, 15070, 15080, 15090, 15100, 0, + 14276, 14282, 14678, 12653, 12658, 12663, 13039, 13044, 13369, 13374, 13379, 13384, 12638, 12643, 12648, 15429, 15433, 15437, 15441, 0, + 14600, 14726, 14294, 14288, 14588, 12668, 12673, 12678, 12683, 13049, 13054, 13389, 13394, 15445, 15449, 15453, 15457, 0, + 14618, 14642, 14690, 12703, 12708, 12713, 12718, 12723, 13059, 13064, 13069, 13074, 13079, 13399, 13404, 13409, 13414, 13419, 13594, 13599, 12688, 12693, 12698, 15461, 15465, 15469, 15473, 0, + 14648, 14300, 14306, 14312, 14318, 14324, 14330, 14336, 14342, 14348, 14552, 14558, 14606, 14636, 12728, 12733, 12738, 12743, 12748, 12753, 13084, 13089, 13094, 13424, 13429, 13434, 13439, 13444, 13604, 15573, 15578, 15583, 15588, 15593, 15598, 15603, 15608, 15477, 15481, 15485, 15489, 0, + 14746, 14354, 14360, 14366, 14372, 14378, 14384, 14390, 14396, 14582, 14630, 14672, 12758, 12763, 12768, 12773, 12778, 12783, 13099, 13104, 13449, 13454, 13459, 13464, 15493, 15497, 15501, 15505, 0, + 14414, 14420, 14426, 14432, 14438, 14444, 14450, 14594, 14624, 14654, 14714, 13134, 13469, 13474, 13479, 13484, 13489, 13609, 13614, 12788, 12793, 12798, 12803, 12808, 12813, 13109, 13114, 13119, 13124, 13129, 15509, 15513, 15517, 15521, 0, + 14402, 14408, 12823, 12828, 12833, 13494, 13504, 13499, 12818, 15525, 15529, 15533, 15537, 0, + 14774, 1963, 15541, 15545, 0, + 12878, 13139, 12299, 12303, 15549, 15553, 0, + 14456, 14462, 14564, 14570, 14576, 12858, 12863, 13144, 13149, 13154, 13159, 13164, 13169, 13509, 13514, 13519, 13524, 13529, 13619, 13624, 1973, 12838, 12843, 12848, 12853, 15557, 15561, 15565, 15569, 0, + 11823, 11827, 0, + 12255, 0, + 11911, 11915, 11919, 11923, 0, + 11879, 11883, 11887, 11891, 0, + 11831, 11835, 11839, 11843, 0, + 11847, 11851, 11855, 11859, 0, + 11895, 11899, 11903, 11907, 0, + 11863, 11867, 11871, 11875, 0, + 11975, 11979, 11983, 11987, 0, + 11959, 11963, 11967, 11971, 0, + 11991, 11995, 11999, 12003, 0, + 12007, 12011, 12015, 12019, 0, + 12047, 12051, 0, + 12031, 12035, 0, + 12023, 12027, 0, + 12039, 12043, 0, + 12063, 12067, 0, + 12055, 12059, 0, + 11927, 11931, 11935, 11939, 0, + 11943, 11947, 11951, 11955, 0, + 12071, 12075, 12079, 12083, 0, + 12215, 12219, 12223, 12227, 0, + 12087, 12091, 12095, 12099, 0, + 12119, 12123, 12127, 12131, 0, + 12103, 12107, 12111, 12115, 0, + 12135, 12139, 0, + 12143, 12147, 12151, 12155, 0, + 12183, 12187, 12191, 12195, 0, + 12159, 12163, 0, + 2003, 12167, 12171, 12175, 12179, 0, + 12267, 12271, 0, + 12239, 12243, 0, + 12231, 12235, 0, + 12247, 12251, 0, + 12275, 12279, 0, + 12259, 12263, 0, + 12397, 12401, 12405, 12409, 0, + 12283, 12287, 12291, 12295, 0, + 2008, 12199, 12203, 0, + 12207, 12211, 0, + 1998, 0, + 2028, 0, + 2033, 0, + 2038, 0, + 2043, 0, + 2048, 0, + 2053, 0, + 2013, 0, + 2058, 0, + 2063, 0, + 2018, 0, + 2023, 0, + 2078, 0, + 2083, 0, + 2088, 0, + 2068, 2073, 0, + 2103, 0, + 2108, 0, + 2113, 0, + 2118, 0, + 2093, 0, + 2098, 0, + 2138, 0, + 2143, 0, + 2123, 2128, 2133, 0, + 2148, 0, + 2153, 2163, 0, + 2158, 0, + 2168, 0, + 2173, 0, + 2178, 2183, 2188, 0, + 2193, 0, + 2198, 2208, 0, + 2203, 0, + 2213, 2218, 2228, 0, + 2223, 0, + 2282, 0, + 2257, 0, + 2262, 0, + 2267, 0, + 2272, 0, + 2277, 0, + 2287, 2292, 2317, 0, + 2347, 0, + 2322, 0, + 2327, 0, + 2332, 0, + 2337, 0, + 2342, 0, + 2297, 0, + 2307, 0, + 2352, 0, + 2637, 0, + 2642, 0, + 2817, 0, + 2822, 0, + 2877, 0, + 2882, 0, + 3197, 3247, 0, + 3202, 3252, 0, + 3327, 0, + 3332, 0, + 3417, 0, + 3422, 0, + 3597, 3607, 3617, 4150, 0, + 3602, 3612, 3622, 4155, 0, + 4160, 0, + 4165, 0, + 4170, 0, + 4175, 0, + 4180, 0, + 4185, 0, + 3637, 3647, 3657, 4190, 0, + 3642, 3652, 3662, 4195, 0, + 4200, 0, + 4205, 0, + 4210, 0, + 4215, 0, + 4220, 0, + 4225, 0, + 3677, 3687, 0, + 3682, 3692, 0, + 3707, 3717, 0, + 3712, 3722, 0, + 3737, 3747, 3757, 4230, 0, + 3742, 3752, 3762, 4235, 0, + 4240, 0, + 4245, 0, + 4250, 0, + 4255, 0, + 4260, 0, + 4265, 0, + 3777, 3787, 3797, 4270, 0, + 3782, 3792, 3802, 4275, 0, + 4280, 0, + 4285, 0, + 4290, 0, + 4295, 0, + 4300, 0, + 4305, 0, + 3817, 3827, 3837, 0, + 3822, 3832, 3842, 0, + 3857, 3867, 3877, 0, + 3862, 3872, 3882, 0, + 3897, 3907, 0, + 3902, 3912, 0, + 3927, 3937, 0, + 3932, 3942, 0, + 3957, 3967, 3977, 0, + 3962, 3972, 3982, 0, + 3992, 3997, 4002, 0, + 4017, 4027, 4037, 4310, 0, + 4022, 4032, 4042, 4315, 0, + 4320, 0, + 4325, 0, + 4330, 0, + 4335, 0, + 4340, 0, + 4345, 0, + 4057, 4067, 4077, 4350, 0, + 4062, 4072, 4082, 4355, 0, + 4360, 0, + 4365, 0, + 4370, 0, + 4375, 0, + 4380, 0, + 4385, 0, + 4400, 0, + 4473, 0, + 4675, 0, + 4420, 0, + 4521, 4526, 4531, 0, + 4493, 0, + 4695, 0, + 4584, 4589, 4594, 0, + 5391, 0, + 5396, 0, + 5401, 0, + 5406, 0, + 5416, 0, + 5411, 0, + 5421, 0, + 5426, 0, + 5431, 0, + 5436, 0, + 5441, 0, + 5468, 0, + 5473, 0, + 5478, 0, + 5483, 0, + 5498, 0, + 5493, 0, + 5513, 0, + 5518, 0, + 5523, 0, + 5528, 0, + 5533, 0, + 5538, 0, + 5543, 0, + 5548, 0, + 5593, 0, + 5598, 0, + 5553, 0, + 5558, 0, + 5563, 0, + 5568, 0, + 5603, 0, + 5608, 0, + 5573, 0, + 5578, 0, + 5583, 0, + 5588, 0, + 5613, 0, + 5618, 0, + 5623, 0, + 5628, 0, + 7351, 0, + 7226, 0, + 7231, 0, + 7236, 0, + 7241, 0, + 7246, 0, + 7251, 0, + 7256, 0, + 7261, 0, + 7266, 0, + 7271, 0, + 7276, 0, + 7281, 0, + 7286, 0, + 7291, 0, + 7296, 0, + 7301, 7306, 0, + 7311, 7316, 0, + 7321, 7326, 0, + 7331, 7336, 0, + 7341, 7346, 0, + 7366, 0, + 7496, 0, + 7371, 0, + 7376, 0, + 7381, 0, + 7386, 0, + 7391, 0, + 7396, 0, + 7401, 0, + 7406, 0, + 7411, 0, + 7416, 0, + 7421, 0, + 7426, 0, + 7431, 0, + 7436, 0, + 7441, 0, + 7446, 7451, 0, + 7456, 7461, 0, + 7466, 7471, 0, + 7476, 7481, 0, + 7486, 7491, 0, + 7501, 0, + 7506, 0, + 7511, 0, + 7516, 0, + 7521, 0, + 11668, 11673, 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, + 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, 16, 18, 20, 0, + 0, 22, 39, 43, 49, 56, 74, 76, + 84, 92, 108, 110, 116, 123, 127, 137, + 154, 0, 157, 166, 174, 182, 202, 205, + 212, 215, 225, 0, 0, 0, 0, 0, + 0, 232, 249, 253, 259, 266, 284, 286, + 294, 303, 318, 321, 327, 334, 338, 348, + 365, 0, 368, 377, 385, 394, 414, 417, + 425, 428, 439, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 446, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 450, 0, 455, 457, 459, 462, + 0, 0, 464, 0, 0, 0, 0, 469, + 0, 0, 0, 0, 471, 476, 480, 0, + 482, 0, 0, 0, 484, 0, 0, 0, + 0, 0, 489, 0, 494, 496, 498, 501, + 0, 0, 503, 0, 0, 0, 0, 508, + 0, 0, 0, 0, 510, 515, 519, 0, + 521, 0, 0, 0, 523, 0, 0, 0, +}; + +static const Q_UINT16 li_01[] = { + 0, 0, 528, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 538, 541, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 544, 547, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 550, 552, 0, 0, 0, 0, + 554, 556, 0, 0, 0, 0, 0, 0, + 558, 560, 562, 564, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 566, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 568, 574, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 580, + 586, 0, 0, 0, 0, 0, 0, 592, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 594, 596, 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, 598, 600, + 602, 604, 0, 0, 0, 0, 606, 608, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 610, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 612, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 614, 0, 0, 0, 622, 0, 627, + 0, 633, 0, 0, 0, 0, 0, 641, + 0, 646, 0, 0, 0, 648, 0, 0, + 0, 655, 0, 0, 661, 0, 663, 0, + 0, 665, 0, 0, 0, 674, 0, 679, + 0, 686, 0, 0, 0, 0, 0, 695, + 0, 700, 0, 0, 0, 703, 0, 0, + 0, 712, 719, 723, 0, 0, 727, 0, + 0, 0, 729, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 732, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 734, 0, 0, 737, 0, 739, 743, 746, + 748, 0, 753, 0, 0, 0, 755, 0, + 0, 0, 0, 757, 0, 0, 0, 762, + 0, 0, 0, 764, 0, 766, 0, 0, + 768, 0, 0, 771, 0, 773, 777, 780, + 782, 0, 787, 0, 0, 0, 789, 0, + 0, 0, 0, 791, 0, 0, 0, 796, + 0, 0, 0, 798, 0, 800, 0, 0, + 0, 0, 0, 0, 0, 0, 802, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 804, 806, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 808, 810, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 812, 814, 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, + 816, 820, 823, 825, 827, 829, 832, 0, + 834, 836, 839, 841, 844, 0, 846, 0, + 848, 850, 0, 852, 854, 0, 857, 859, + 861, 863, 867, 0, 0, 0, 0, 0, + 0, 0, 869, 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, 871, 873, 876, 879, 882, 885, 926, + 936, 962, 965, 1003, 1021, 1041, 1057, 1071, + 1074, 1078, 1083, 1086, 1121, 1158, 1183, 1206, + 1224, 1232, 1252, 0, 0, 0, 0, 0, + 1268, 1278, 1298, 1316, 1344, 1386, 1415, 1450, + 1464, 1469, 1476, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1506, 0, 0, 0, 0, 0, 1509, + 0, 1511, 1516, 1521, 0, 0, 1526, 1531, + 1536, 0, 0, 1541, 1546, 0, 1551, 1556, + 1561, 0, 0, 0, 1564, 1567, 1570, 0, + 0, 1573, 0, 0, 0, 0, 0, 0, + 1576, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1579, 0, 1584, 0, + 0, 1589, 0, 0, 0, 1594, 0, 1599, + 0, 1604, 0, 1609, 0, 0, 0, 0, + 0, 0, 1614, 1617, 0, 0, 1622, 0, + 1627, 1630, 0, 0, 0, 1636, 1639, 1642, + 1645, 1648, 0, 1651, 1654, 0, 0, 0, + 1659, 0, 1664, 1668, 0, 1671, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1673, 1675, 1677, + 0, 0, 0, 0, 1679, 0, 0, 0, + 0, 1681, 1683, 0, 0, 0, 0, 0, + 1685, 0, 0, 1687, 0, 0, 0, 1689, + 1691, 0, 0, 1693, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1695, 1697, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1699, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1701, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1704, 1706, + 0, 0, 0, 0, 1708, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1710, 0, 0, 0, 0, + 0, 0, 1712, 0, 0, 0, 0, 0, + 1714, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1716, 1718, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1720, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1724, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1726, 1729, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1733, + 0, 0, 0, 0, 0, 0, 1735, 0, + 0, 0, 1739, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1741, 1744, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1746, 0, 0, 1750, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 1752, 0, 1754, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1756, 0, 0, 0, + 0, 1758, 0, 0, 0, 0, 1760, 0, + 0, 0, 0, 1762, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1764, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1768, 0, 1770, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1772, 0, 0, 0, + 0, 1774, 0, 0, 0, 0, 1776, 0, + 0, 0, 0, 1778, 0, 0, 0, 0, + 0, 0, 1780, 1782, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1784, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 1786, 1788, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1790, 1792, 0, 0, 0, 0, + 0, 0, 1794, 1796, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1798, 1801, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1804, 1806, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1808, 1810, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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[] = { + 1812, 1817, 1822, 1824, 1826, 1828, 1830, 1832, + 1834, 1839, 1844, 1846, 1848, 1850, 1852, 1854, + 1856, 1859, 0, 0, 0, 0, 0, 0, + 1862, 1865, 0, 0, 0, 0, 0, 0, + 1868, 1873, 1878, 1880, 1882, 1884, 1886, 1888, + 1890, 1895, 1900, 1902, 1904, 1906, 1908, 1910, + 1912, 1916, 0, 0, 0, 0, 0, 0, + 1920, 1924, 0, 0, 0, 0, 0, 0, + 1928, 1931, 0, 0, 0, 0, 0, 0, + 1934, 1937, 0, 0, 0, 0, 0, 0, + 1940, 1944, 0, 0, 0, 0, 0, 0, + 0, 1948, 0, 0, 0, 0, 0, 0, + 1952, 1957, 1962, 1964, 1966, 1968, 1970, 1972, + 1974, 1979, 1984, 1986, 1988, 1990, 1992, 1994, + 1996, 0, 0, 0, 1998, 0, 0, 0, + 0, 0, 0, 0, 2000, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2002, 0, + 0, 0, 0, 0, 0, 0, 0, 2004, + 0, 0, 0, 0, 0, 0, 2008, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2010, 0, + 0, 0, 0, 0, 0, 0, 2012, 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, + 2016, 0, 2018, 0, 2020, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2022, 0, 2024, 0, 2026, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2028, 0, 0, 0, 0, + 2030, 0, 0, 2032, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2034, 0, 2036, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2038, 0, 0, 0, + 0, 0, 0, 2040, 0, 2042, 0, 0, + 2044, 0, 0, 0, 0, 2046, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2048, 0, 0, 2050, 2052, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2054, 2056, 0, 0, 2058, 2060, + 0, 0, 2062, 2064, 2066, 2068, 0, 0, + 0, 0, 2070, 2072, 0, 0, 2074, 2076, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2078, 2080, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2082, 0, 0, 0, 0, 0, + 2084, 2086, 0, 2088, 0, 0, 0, 0, + 0, 0, 2090, 2092, 2094, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 2098, 0, + 0, 0, 0, 2100, 0, 2102, 0, 2104, + 0, 2106, 0, 2108, 0, 2110, 0, 2112, + 0, 2114, 0, 2116, 0, 2118, 0, 2120, + 0, 2122, 0, 0, 2124, 0, 2126, 0, + 2128, 0, 0, 0, 0, 0, 0, 2130, + 0, 0, 2133, 0, 0, 2136, 0, 0, + 2139, 0, 0, 2142, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2145, 0, 0, + 0, 0, 0, 0, 0, 0, 2147, 0, + 0, 0, 0, 2149, 0, 2151, 0, 2153, + 0, 2155, 0, 2157, 0, 2159, 0, 2161, + 0, 2163, 0, 2165, 0, 2167, 0, 2169, + 0, 2171, 0, 0, 2173, 0, 2175, 0, + 2177, 0, 0, 0, 0, 0, 0, 2179, + 0, 0, 2182, 0, 0, 2185, 0, 0, + 2188, 0, 0, 2191, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2194, + 2196, 2198, 2200, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2202, 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, 2204, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_07, 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, +}; +// 16188 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, 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, 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, 0, 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, 77, 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, 0, 0, + 17, 13, 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, 13, 17, 17, + 17, 17, 17, 17, 17, 17, 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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 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, 18, 18, 18, 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, 18, 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, 0, + 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, + 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_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, + 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, 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_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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +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, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_28[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 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_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, 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, 17, 17, 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, 10, 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, 0, 0, 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, 0, 10, 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, +}; + +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, 0, 0, 0, 0, +}; + +static const Q_UINT8 dir_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, + 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, 0, 0, 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, 0, 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, + 10, 10, 10, 4, 6, 4, 6, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 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, 0, 0, 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, 0, + 0, 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, 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_28, dir_01, dir_01, dir_01, dir_01, dir_01, dir_2E, dir_2F, + dir_30, 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_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, +}; +// 26940 bytes + +#endif + +// END OF GENERATED DATA + +// This is generated too. Script? + +#ifndef QT_NO_UNICODETABLES + +static const Q_UINT16 case_0 [] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 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, 0x0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x0, 0, 0, + 0, 0, 0x0, 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, 0x0, + 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_1 [] = { + 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, + 0x0, 0x13a, 0x139, 0x13c, 0x13b, 0x13e, 0x13d, 0x140, + 0x13f, 0x142, 0x141, 0x144, 0x143, 0x146, 0x145, 0x148, + 0x147, 0x0, 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, + 0x0, 0x253, 0x183, 0x182, 0x185, 0x184, 0x254, 0x188, + 0x187, 0x256, 0x257, 0x18c, 0x18b, 0x0, 0x1dd, 0x259, + 0x25b, 0x192, 0x191, 0x260, 0x263, 0x3d9, 0x269, 0x268, + 0x199, 0x198, 0x51, 0x0, 0x26f, 0x272, 0x0, 0x275, + 0x1a1, 0x1a0, 0x1a3, 0x1a2, 0x1a5, 0x1a4, 0x280, 0x1a8, + 0x1a7, 0x283, 0, 0x0, 0x1ad, 0x1ac, 0x288, 0x1b0, + 0x1af, 0x28a, 0x28b, 0x1b4, 0x1b3, 0x1b6, 0x1b5, 0x292, + 0x1b9, 0x1b8, 0x0, 0, 0x1bd, 0x1bc, 0, 0, + 0, 0, 0, 0, 0x1c6, 0, 0x1c4, 0x1c9, + 0, 0x1c7, 0x1cc, 0, 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, + 0x0, 0x1f3, 0, 0x1f1, 0x1f5, 0x1f4, 0, 0, + 0, 0, 0x1fb, 0x1fa, 0x1fd, 0x1fc, 0x1ff, 0x1fe, +}; + +static const Q_UINT16 case_2 [] = { + 0x201, 0x200, 0x203, 0x202, 0x205, 0x204, 0x207, 0x206, + 0x209, 0x208, 0x20b, 0x20a, 0x20d, 0x20c, 0x20f, 0x20e, + 0x211, 0x210, 0x213, 0x212, 0x215, 0x214, 0x217, 0x216, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x0, 0x0, 0x0, 0x181, 0x186, 0x0, 0x189, 0x18a, + 0x0, 0x18f, 0x0, 0x190, 0x0, 0x0, 0x0, 0x0, + 0x193, 0x0, 0x0, 0x194, 0x0, 0x0, 0x631, 0x579, + 0x197, 0x196, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19c, + 0x0, 0x0, 0x19d, 0x0, 0x0, 0x19f, 0x0, 0x0, + 0x0, 0x0, 0x7e1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1a6, 0x0, 0x0, 0x1a9, 0x0, 0x0, 0x0, 0x0, + 0x1ae, 0x0, 0x1b1, 0x1b2, 0x0, 0xa21, 0x971, 0x0, + 0x0, 0x0, 0x1b7, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_3 [] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 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, + 0x0, 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, + 0x0, 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, 0x0, 0x0, 0x0, 0x3a6, 0x3a0, 0, + 0, 0, 0x0, 0, 0x0, 0, 0x0, 0, + 0x0, 0, 0x3e3, 0x3e2, 0x3e5, 0x3e4, 0x3e7, 0x3e6, + 0x3e9, 0x3e8, 0x3eb, 0x3ea, 0x3ed, 0x3ec, 0x3ef, 0x3ee, + 0x39a, 0x3a1, 0x3a3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_4 [] = { + 0, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, + 0x458, 0x459, 0x45a, 0x45b, 0x45c, 0, 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, + 0, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, + 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0, 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, 0, 0, 0, 0, 0, 0, + 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, 0, 0, 0x4c8, + 0x4c7, 0, 0, 0x4cc, 0x4cb, 0, 0, 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, 0, 0, 0x4ef, 0x4ee, + 0x4f1, 0x4f0, 0x4f3, 0x4f2, 0x4f5, 0x4f4, 0, 0, + 0x4f9, 0x4f8, 0, 0, 0, 0, 0, 0, +}; + +static const Q_UINT16 case_5 [] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 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, 0x0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, + 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, + 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, + 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, + 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 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, 0x0, 0x0, + 0x0, 0x0, 0x0, 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, + 0x0, 0x1f59, 0x0, 0x1f5b, 0x0, 0x1f5d, 0x0, 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, 0x0, 0x1fbc, 0x0, 0, 0x0, 0x0, + 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0, 0x399, 0, + 0, 0, 0x0, 0x1fcc, 0x0, 0, 0x0, 0x0, + 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0, 0, 0, + 0x1fd8, 0x1fd9, 0x0, 0x0, 0, 0, 0x0, 0x0, + 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0, 0, 0, 0, + 0x1fe8, 0x1fe9, 0x0, 0x0, 0x0, 0x1fec, 0x0, 0x0, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0, 0, 0, + 0, 0, 0x0, 0x1ffc, 0x0, 0, 0x0, 0x0, + 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0, 0, 0, +}; + +static const Q_UINT16 case_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, 0x0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_21 [] = { + 0, 0, 0x0, 0, 0, 0, 0, 0x0, + 0, 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0, 0x0, 0, 0, + 0x761, 0x0, 0x0, 0x0, 0x0, 0x0, 0, 0, + 0, 0, 0, 0, 0x0, 0, 0x0, 0, + 0x0, 0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0, 0x0, 0x0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_fb [] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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_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_0, case_1, case_2, case_3, case_4, case_5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + case_10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, case_1e, case_1f, + case_20, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 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_fb, 0, 0, 0, case_ff, +}; + +static const Q_INT8 num_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, -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_6 [] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -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_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, 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_b [] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -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_d [] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -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_e [] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -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_f [] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -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_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_ff [] = { + -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 * const decimal_info[256] = { + num_0, 0, 0, 0, 0, 0, num_6, 0, + 0, num_9, num_9, num_b, num_9, num_d, num_e, num_f, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + num_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, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, num_ff, +}; + +static const Q_UINT16 symmetricPairs[] = { + 0x0028, 0x0029, 0x0029, 0x0028, 0x003C, 0x003E, 0x003E, 0x003C, + 0x005B, 0x005D, 0x005D, 0x005B, 0x007B, 0x007D, 0x007D, 0x007B, + 0x2045, 0x2046, 0x2046, 0x2045, 0x207D, 0x207E, 0x207E, 0x207D, + 0x208D, 0x208E, 0x208E, 0x208D, 0x3008, 0x3009, 0x3009, 0x3008, + 0x300A, 0x300B, 0x300B, 0x300A, 0x300C, 0x300D, 0x300D, 0x300C, + 0x300E, 0x300F, 0x300F, 0x300E, 0x3010, 0x3011, 0x3011, 0x3010, + 0x3014, 0x3015, 0x3015, 0x3014, 0x3016, 0x3017, 0x3017, 0x3016, + 0x3018, 0x3019, 0x3019, 0x3018, 0x301A, 0x301B, 0x301B, 0x301A, + 0xFD3E, 0xFD3F, 0xFD3F, 0xFD3E, 0xFE59, 0xFE5A, 0xFE5A, 0xFE59, + 0xFE5B, 0xFE5C, 0xFE5C, 0xFE5B, 0xFE5D, 0xFE5E, 0xFE5E, 0xFE5D, + 0xFF08, 0xFF09, 0xFF09, 0xFF08, 0xFF3B, 0xFF3D, 0xFF3D, 0xFF3B, + 0xFF5B, 0xFF5D, 0xFF5D, 0xFF5B, 0xFF62, 0xFF63, 0xFF63, 0xFF62, +}; + +static 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-- && a->lower() == b->lower() ) + a++,b++; + if ( l==-1 ) + return 0; + QChar al = a->lower(); + QChar bl = b->lower(); + return al.unicode() - bl.unicode(); +} + +// NOT REVISED +/*! \class QCharRef qstring.h + \brief The QCharRef class is a helper class for QString. + + It provides the ability to work on characters in a QString in a natural + fashion. + + When you get an object of type QCharRef, you can assign to it, which + will operate on the string from which you got it. That is its whole + purpose in life. It becomes invalid once further modifications are + made to the string: If you want to keep it, 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 + +\brief The QChar class provides a light-weight Unicode character. + +Unicode characters are (so far) 16-bit entities without any markup or +structure. This class represents such an entity. It is rather +light-weight, so it can be used everywhere. Most compilers treat it +approximately like "short int". (In a few years, it may be necessary +to make QChar 32-bit, once more than 65536 Unicode code points have +been defined and come into use.) + +QChar provides a full complement of testing/classification functions, +conversion to and from other formats, from composed to decomposed +unicode, and will try 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, and FALSE +otherwise. + +These 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 Marks), isLetter (letters), isNumber() (any sort of +numeric characters), isLetterOrNumber(), and isDigit() (decimal digits). +All of these are wrappers around category(), which returns the +unicode-defined category of each character. + +QChar further provides direction(), which indicates the "natural" +writing direction of this character, joining(), which indicates how +this character joins with its neighbors (needed mostly for Arabic) +and finally mirrored(), which indicates whether this 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") using +decomposition(). + +In Unicode, comparison is not necessarily possible, and case +conversion is at best very hard. Unicode, covering the "entire" +globe, also includes a globe-sized collection of 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. + +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. + +\sa QString QCharRef \link unicode.html About Unicode \endlink +*/ + +/*! \enum QChar::Category + +This enum maps the Unicode character categories. The currently known +categories are: <ul> + +<li> \c NoCategory - used when Qt is dazed and confused and cannot +make sense of anything. + +<li> \c Mark_NonSpacing - (Mn) - + +<li> \c Mark_SpacingCombining - (Mc) - + +<li> \c Mark_Enclosing - (Me) - + +<li> \c Number_DecimalDigit - (Nd) - + +<li> \c Number_Letter - (Nl) - + +<li> \c Number_Other - (No) - + +<li> \c Separator_Space - (Zs) - + +<li> \c Separator_Line - (Zl) - + +<li> \c Separator_Paragraph - (Zp) - + +<li> \c Other_Control - (Cc) - + +<li> \c Other_Format - (Cf) - + +<li> \c Other_Surrogate - (Cs) - + +<li> \c Other_PrivateUse - (Co) - + +<li> \c Other_NotAssigned - (Cn) - + +<li> \c Letter_Uppercase - (Lu) - + +<li> \c Letter_Lowercase - (Ll) - + +<li> \c Letter_Titlecase - (Lt) - + +<li> \c Letter_Modifier - (Lm) - + +<li> \c Letter_Other - (Lo) - + +<li> \c Punctuation_Connector - (Pc) - + +<li> \c Punctuation_Dask - (Pd) - + +<li> \c Punctuation_Open - (Ps) - + +<li> \c Punctuation_Close - (Pe) - + +<li> \c Punctuation_InitialQuote - (Pi) - + +<li> \c Punctuation_FinalQuote - (Pf) - + +<li> \c Punctuation_Other - (Po) - + +<li> \c Symbol_Math - (Sm) - + +<li> \c Symbol_Currency - (Sc) - + +<li> \c Symbol_Modifier - (Sk) - + +<li> \c Symbol_Other - (So) - + +</ul> +*/ + +/*! \enum QChar::Direction + + This enum type defines the Unicode direction attributes. + See <a href="http://www.unicode.org">the Unicode Standard</a> + 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 <a href="http://www.unicode.org">the Unicode Standard</a> + for a description of the values. +*/ + +/*! \enum QChar::Joining + + This enum type defines the Unicode decomposition attributes. + See <a href="http://www.unicode.org">the Unicode Standard</a> + for a description of the values. +*/ + + + +/*! \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 +light-weight 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 () + + Returns TRUE if this character is in network byte order (MSB first), + and FALSE if it is not. This is a platform-dependent property, so + we strongly advise against using this function in portable code. +*/ + + +/*! + \fn bool QChar::isNull() const + Returns TRUE if the characters is the unicode character 0x0000, + ie. ASCII NUL. +*/ + +/*! + \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. +*/ +/*! + \fn uchar& QChar::cell () + Returns a reference to the cell (least significant byte) of the Unicode character. +*/ +/*! + \fn uchar& QChar::row () + Returns a reference to the row (most significant byte) of the Unicode character. +*/ + +/*! + Returns whether the character is a printable character. This is + any character not of category Cc or Cn. Note that this gives no indication + of whether the character is available in some font. +*/ +bool QChar::isPrint() const +{ + Category c = category(); + return !(c == Other_Control || c == Other_NotAssigned); +} + +/*! + Returns whether the character is a separator + character (Separator_* categories). +*/ +bool QChar::isSpace() const +{ + if( !row() ) + if( cell() >= 9 && cell() <=13 ) return TRUE; + Category c = category(); + return c >= Separator_Space && c <= Separator_Paragraph; +} + +/*! + Returns whether the character is a mark (Mark_* categories). +*/ +bool QChar::isMark() const +{ + Category c = category(); + return c >= Mark_NonSpacing && c <= Mark_Enclosing; +} + +/*! + Returns whether the character is punctuation (Punctuation_* categories). +*/ +bool QChar::isPunct() const +{ + Category c = category(); + return (c >= Punctuation_Connector && c <= Punctuation_Other); +} + +/*! + Returns whether the character is a letter (Letter_* categories). +*/ +bool QChar::isLetter() const +{ + Category c = category(); + return (c >= Letter_Uppercase && c <= Letter_Other); +} + +/*! + Returns whether the character is a number (of any sort - Number_* categories). + + \sa isDigit() +*/ +bool QChar::isNumber() const +{ + Category c = category(); + return c >= Number_DecimalDigit && c <= Number_Other; +} + +/*! + Returns whether the character is a letter or number (Letter_* or Number_* categories). +*/ +bool QChar::isLetterOrNumber() const +{ + Category c = category(); + return (c >= Letter_Uppercase && c <= Letter_Other) + || (c >= Number_DecimalDigit && c <= Number_Other); +} + + +/*! + Returns whether the character is a decimal digit (Number_DecimalDigit). + */ +bool QChar::isDigit() const +{ + return (category() == Number_DecimalDigit); +} + +/*! + 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 decimal_info[row()][cell()]; +#else + // ##### just latin1 + if ( rw != 0 || cl < '0' || cl > '9' ) + return -1; + else + return cl - '0'; +#endif +} + +/*! + Returns the character category. + + \sa Category +*/ +QChar::Category QChar::category() const +{ +#ifndef QT_NO_UNICODETABLES + return (Category)(unicode_info[row()][cell()]); +#else +// ### just ASCII + if ( rw == 0 ) { + if ( cl >= '0' && cl <='9' ) + return Number_DecimalDigit; + if ( cl >= 'a' && cl <='z' ) + return Letter_Lowercase; + if ( cl >= 'A' && cl <='Z' ) + return Letter_Uppercase; + if ( cl == ' ' ) + return Separator_Space; + if ( cl == '\n' ) + return Separator_Line; + if ( cl < ' ' ) + return Other_Control; + return Symbol_Other; //####### + } + return Letter_Uppercase; //####### +#endif +} + +/*! + Returns the characters directionality. + + \sa Direction +*/ +QChar::Direction QChar::direction() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = direction_info[row()]; + if(!rowp) return QChar::DirL; + return (Direction) ( *(rowp+cell()) &0x1f ); +#else + return DirL; +#endif +} + +/*! + This function is not supported (it may change to use Unicode + character classes). + + Returns information about the joining properties of the + character (needed 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 whether the character is a mirrored character (one that + should be reversed if the text direction is reversed). +*/ +bool QChar::mirrored() const +{ +#ifndef QT_NO_UNICODETABLES + const Q_UINT8 *rowp = direction_info[row()]; + if ( !rowp ) + return FALSE; + return *(rowp+cell())>128; +#else + return FALSE; +#endif +} + +/*! + Returns the mirrored char if this character is a mirrored char, the char + itself otherwise +*/ +QChar QChar::mirroredChar() const +{ +#ifndef QT_NO_UNICODETABLES + if(!mirrored()) return *this; + + int i; + int c = unicode(); + for (i = 0; i < symmetricPairsSize; i += 2) { + if (symmetricPairs[i] == c) + return symmetricPairs[i+1]; + } + return 0; +#else + return *this; +#endif +} + +/*! + Decomposes a character into its parts. Returns QString::null if + no decomposition exists. +*/ +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); + + return s; +#else + return 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 lowercase equivalent if the character is uppercase, + or the character itself otherwise. +*/ +QChar QChar::lower() const +{ +#ifndef QT_NO_UNICODETABLES + if(category() != Letter_Uppercase) return *this; + Q_UINT16 lower = *(case_info[row()]+cell()); + if(lower == 0) return *this; + return lower; +#else + if (row()) + return *this; + else + return QChar(tolower(latin1())); +#endif +} + +/*! + Returns the uppercase equivalent if the character is lowercase, + or the character itself otherwise. +*/ +QChar QChar::upper() const +{ +#ifndef QT_NO_UNICODETABLES + if(category() != Letter_Lowercase) return *this; + Q_UINT16 upper = *(case_info[row()]+cell()); + if(upper == 0) return *this; + return upper; +#else + if (row()) + return *this; + else + return QChar(toupper(latin1())); +#endif +} + +/*! + \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 (eg. indexing into an array of Unicode information), this function + is useful. +*/ + +/***************************************************************************** + Documentation of QChar related functions + *****************************************************************************/ + +/*! + \fn int operator==( QChar c1, QChar c2 ) + \relates QChar + + Returns TRUE if \a c1 and \a c2 are the same Unicode character. +*/ + +/*! + \fn int operator==( char ch, QChar c ) + \relates QChar + + Returns TRUE if \a c is the ASCII/Latin1 character \a ch. +*/ + +/*! + \fn int operator==( QChar c, char ch ) + \relates QChar + + Returns TRUE if \a c is the ASCII/Latin1 character \a ch. +*/ + +/*! + \fn int operator!=( QChar c1, QChar c2 ) + \relates QChar + + Returns TRUE if \a c1 and \a c2 are not the same Unicode character. +*/ + +/*! + \fn int operator!=( char ch, QChar c ) + \relates QChar + + Returns TRUE if \a c is not the ASCII/Latin1 character \a ch. +*/ + +/*! + \fn int operator!=( QChar c, char ch ) + \relates QChar + + Returns TRUE if \a c is not the ASCII/Latin1 character \a ch. +*/ + +/*! + \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. +*/ + +/*! + \fn int operator<=( QChar c, char ch ) + \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. +*/ + +/*! + \fn int operator<=( char ch, QChar c ) + \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. +*/ + +/*! + \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. +*/ + +/*! + \fn int operator>=( QChar c, char ch ) + \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. +*/ + +/*! + \fn int operator>=( char ch, QChar c ) + \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. +*/ + +/*! + \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. +*/ + +/*! + \fn int operator<( QChar c, char ch ) + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is less than that + of the ASCII/Latin1 character \a ch. +*/ + +/*! + \fn int operator<( char ch, QChar c ) + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is less than that of \a c. +*/ + +/*! + \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. +*/ + +/*! + \fn int operator>( QChar c, char ch ) + \relates QChar + + Returns TRUE if the numeric Unicode value of \a c is greater than + that of the ASCII/Latin1 character \a ch. +*/ + +/*! + \fn int operator>( char ch, QChar c ) + \relates QChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin1 + character \a ch is greater than that of \a c. +*/ + +#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; +} + +#endif + +// 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() + +/* + 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. +*/ +/*! + Note that this function is not supported in Qt 2.0, and is merely + for experimental and illustrative purposes. 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 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; + + QArray<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 +} + +static QChar LRM ((ushort)0x200e); +static QChar RLM ((ushort)0x200f); +static QChar LRE ((ushort)0x202a); +static QChar RLE ((ushort)0x202b); +static QChar RLO ((ushort)0x202e); +static QChar LRO ((ushort)0x202d); +static QChar PDF ((ushort)0x202c); + +#if 0 +static inline bool is_arabic(unsigned short x) { + return (((x >= 0x0600) && (x <= 0x07bf)) || + ((x >= 0xfb50) && (x <= 0xfdff)) || + ((x >= 0xfe70) && (x <= 0xfeff))); +} +#endif + +static inline bool is_neutral(unsigned short dir) { + return ((dir == QChar::DirB) || + (dir == QChar::DirS) || + (dir == QChar::DirWS) || + (dir == QChar::DirON) || + (dir == QChar::DirNSM)); +} + +/*! + This function returns the basic directionality of the string (QChar::DirR for + right to left and QChar::DirL for left to right). Useful to find the right + alignment. + */ +QChar::Direction QString::basicDirection() +{ +#ifndef QT_NO_UNICODETABLES + // find base direction + unsigned int pos = 0; + while ((pos < length()) && + (at(pos) != RLE) && + (at(pos) != LRE) && + (at(pos) != RLO) && + (at(pos) != LRO) && + (at(pos).direction() > 1) && + (at(pos).direction() != QChar::DirAL)) // not R and not L + pos++; + + if ((at(pos).direction() == QChar::DirR) || + (at(pos).direction() == QChar::DirAL) || + (at(pos) == RLE) || + (at(pos) == RLO)) + return QChar::DirR; +#endif + + return QChar::DirL; +} + +#ifndef QT_NO_UNICODETABLES +// reverses part of the QChar array to get visual ordering +// called from QString::visual() +// +static unsigned int reverse( QString &chars, unsigned char *level, + unsigned int a, unsigned int b) +{ + unsigned int c = a; + unsigned char lev = level[c]; + + while ((c < b) && (level[c] >= lev)) { + if (level[c] > lev) + c = reverse(chars, level, c, b); + c++; + } + + if (lev > 0) { + QChar temp; + unsigned int d = a, e = c-1; + while (d < e) { + temp = chars[(int)d]; + chars[(int)d] = chars[(int)e]; + chars[(int)e] = temp; + + d++; e--; + } + } + + return c; +} + +// small class used for the ordering algorithm in QString::visual() +class QBidiState { +public: + unsigned char level; + signed char override; + + QBidiState(unsigned char l, signed char o) : level(l), override(o) {}; +}; + +// matrix for resolving neutral types + +#define NEG1 (QChar::Direction)(-1) + +static QChar::Direction resolv[5][5] = +{ + { NEG1, QChar::DirR, QChar::DirL, QChar::DirEN, QChar::DirAN }, + { QChar::DirR, QChar::DirR, NEG1, QChar::DirR, QChar::DirR }, + { QChar::DirL, NEG1, QChar::DirL, QChar::DirL, NEG1 }, + { QChar::DirEN, QChar::DirR, QChar::DirL, QChar::DirEN, QChar::DirR }, + { QChar::DirAN, QChar::DirR, NEG1, NEG1, QChar::DirAN } +}; + +#endif + +/*! + This function returns the QString ordered visually. Useful for + painting the string or when transforming to a visually ordered + encoding. +*/ +QString QString::visual(int index, int len) +{ +#ifndef QT_NO_UNICODETABLES + // #### This needs much more optimizing - it is called for + // #### every text operation. + + unsigned char *level; + QChar::Direction *dir; + unsigned char base = 0; + + unsigned int l = length(); + + // check bounds + if (len == -1) + len = length()-index; + if ((uint)index > l) + return QString::null; + + // find base direction + unsigned int pos = 0; + while ((pos < length()) && + (at(pos) != RLE) && + (at(pos) != LRE) && + (at(pos) != RLO) && + (at(pos) != LRO) && + (at(pos).direction() > 1) && + (at(pos).direction() != QChar::DirAL) + ) // not R and not L + pos++; + + if ((pos < length()) && + ((at(pos).direction() == QChar::DirR) || + (at(pos).direction() == QChar::DirAL) || + (at(pos) == RLE) || + (at(pos) == RLO))) + base = 1; + + // is there any BiDi char at all? + if ( base == 0 && pos == l ) { + return mid(index, len); + } + + + level = new uchar[l]; + dir = new QChar::Direction[l]; + + // explicit override pass + //unsigned int code_count = 0; + + QStack<QBidiState> stack; + stack.setAutoDelete(TRUE); + + unsigned char clevel = base; + signed char override = -1; + + for (pos = 0; pos < l; pos++) { + + if (at(pos) == RLE) { + //code_count++; + stack.push(new QBidiState(clevel, override)); + if (clevel < 254) + clevel += 1 + clevel % 2; + override = -1; + } + else if (at(pos) == LRE) { + //code_count++; + stack.push(new QBidiState(clevel, override)); + if (clevel < 254) + clevel += 2 - clevel % 2; + override = -1; + } + else if (at(pos) == RLO) { + //code_count++; + stack.push(new QBidiState(clevel, override)); + if (clevel < 254) + clevel += 1 + clevel % 2; + override = QChar::DirR; + } + else if (at(pos) == LRO) { + //code_count++; + stack.push(new QBidiState(clevel, override)); + if (clevel < 254) + clevel += 2 - clevel % 2; + override = QChar::DirL; + } + else if (at(pos) == PDF) { + //code_count++; + if (!stack.isEmpty()) { + override = stack.top()->override; + clevel = stack.top()->level; + stack.remove(); + } + } + + // TODO: catch block separators (newlines, paras, etc.) + + level[pos] = clevel; + if (override != -1) + dir[pos] = (QChar::Direction) override; + else + dir[pos] = at(pos).direction(); + } + + // weak type pass + for (pos = 0; pos < l; pos++) { + + int i; + + switch (at(pos).direction()) { + case QChar::DirEN: + i = pos-1; + while ((i >= 0) && + !(at(i).direction() == QChar::DirAN) && + !(at(i).direction() == QChar::DirAL) && + !(at(i).direction() == QChar::DirB)) + i--; + + if ((i >= 0) && + ((at(i).direction() == QChar::DirAN) || + (at(i).direction() == QChar::DirAL))) + dir[pos] = QChar::DirAN; + + break; + case QChar::DirES: + case QChar::DirCS: + if ((pos > 0) && (pos < l-1) && + (dir[pos-1] == dir[pos+1])) + dir[pos] = dir[pos-1]; + else + dir[pos] = QChar::DirON; + + break; + case QChar::DirET: + if (((pos > 0) && (dir[pos-1] == QChar::DirEN)) || + ((pos < l-1) && (dir[pos+1] == QChar::DirEN))) + dir[pos] = QChar::DirEN; + else + dir[pos] = QChar::DirON; + + break; + case QChar::DirAL: + dir[pos] = QChar::DirR; + break; + default: + break; + } + } + + // neutral type pass + for (pos = 0; pos < l; pos++) { + QChar::Direction left,right; // declaring l here shadowed previous l + + if (is_neutral(dir[pos])) { + if (pos > 0) + left = dir[pos-1]; + else + left = (base == 0 ? QChar::DirL : QChar::DirR); + + int i = pos; + + while ((i < (int)l-1) && is_neutral(dir[i+1])) + i++; + + if (i < (int)l-1) + right = dir[i+1]; + else + right = (base == 0 ? QChar::DirL : QChar::DirR); + + for (int j=pos; j <= i; j++) { + int a = 1, b = 1; + while ((a < 5) && (left != resolv[0][a])) + a++; + while ((b < 5) && (right != resolv[0][b])) + b++; + if ((a == 5) || (b == 5)) + dir[j] = (base == 0 ? QChar::DirL : QChar::DirR); + else + dir[j] = resolv[a][b]; + + if (dir[j] == (QChar::Direction)(-1)) + dir[j] = (base == 0 ? QChar::DirL : QChar::DirR); + } + } + } + + // implicit level pass + QChar::Direction prec = (base == 0 ? QChar::DirL : QChar::DirR); + + for (pos = 0; pos < l; pos++) { + if (level[pos] % 2) { + switch (dir[pos]) { + case QChar::DirL: + case QChar::DirAN: + case QChar::DirEN: + level[pos] += 1; + break; + default: + break; + } + } else { + switch (dir[pos]) { + case QChar::DirL: + // do nothing + break; + case QChar::DirR: + level[pos] += 1; + break; + case QChar::DirEN: + if (prec == QChar::DirL) + continue; + // fall through + case QChar::DirAN: + level[pos] += 2; + break; + default: + break; + } + } + + prec = dir[pos]; + } + + // now do the work! + QString ret(*this); + reverse(ret, level, index, index+len); + + delete [] level; + delete [] dir; + + return ret; +#else + return mid(index,len); +#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; +} + +/*! + This utility function converts the NUL-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 NUL-terminated string. + + The caller is responsible for deleting the 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++; + *a = '\0'; + return result; +} + +/***************************************************************************** + QString member functions + *****************************************************************************/ + +/*! + \class QString qstring.h + + \brief The QString class provides an abstraction of Unicode text and + the classic C null-terminated char array (<var>char*</var>). + + \ingroup tools + \ingroup shared + + QString uses \link shclass.html implicit sharing\endlink, and so it + is very efficient and easy to use. + + In all QString methods that take <var>const char*</var> parameters, + the <var>const char*</var> is interpreted as a classic C-style + 0-terminated ASCII string. It is legal for the <var>const + char*</var> parameter to be 0. The results are undefined if the + <var>const char*</var> string is not 0-terminated. 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 not terminated by a null. + + A QString that has not been assigned to anything is \a null, i.e. both + the length and data pointer is 0. A QString that references the empty + string ("", a single '\0' char) is \a empty. Both null and empty + QStrings are legal parameters to the methods. Assigning <var>const char + * 0</var> to QString gives a null QString. + + Note that if you find that you are mixing usage of QCString, QString, + and 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 NUL-terminated 8-bit data, use QCString; + if it is unterminated (ie. contains NULs) 8-bit data, use QByteArray; + if it is text, use QString. + + \sa QChar \link shclass.html Shared classes\endlink +*/ + +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() +{ + return shared_null=new QStringData; +} + +// 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. + \sa isNull() +*/ + +/*! + Constructs a string containing the one 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. +*/ +QString::QString( const QString &s ) : + d(s.d) +{ + Q2HELPER(stat_fast_copy++) + d->ref(); +} + +/*! + 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 QChar in the array \a unicode. + + If \a unicode and \a length are 0, 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 some cases up a little. + + \sa isNull() +*/ + +QString::QString( const QChar* unicode, uint length ) +{ + if ( !unicode && !length ) { + d = shared_null ? shared_null : makeSharedNull(); + } 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 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 QT_NO_CAST_ASCII when you compile your applications. + You can also make QString objects by using setLatin1()/fromLatin1(), or + fromLocal8Bit(), 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 "real" string, if this was the last +copy of that string. +*/ + + +/*! + Deallocates any space reserved solely by this QString. +*/ + +void QString::real_detach() +{ + setLength( length() ); +} + +void QString::deref() +{ + if ( d->deref() ) { + 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 ) + Sets the string to contain just the single character \a c. +*/ + +/*! + Assigns a shallow copy of \a s to this string and returns a + reference to this string. +*/ +QString &QString::operator=( const QString &s ) +{ + Q2HELPER(stat_fast_copy++) + s.d->ref(); + deref(); + d = s.d; + return *this; +} + +/*! + 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); +} + + +/*! + 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 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. + A null string is also an empty string. + + Example: + \code + QString a; // a.unicode() == 0, a.length() == 0 + QString b = ""; // b.unicode() == "", b.length() == 0 + a.isNull(); // TRUE, because a.unicode() == 0 + a.isEmpty(); // TRUE, because a.length() == 0 + b.isNull(); // FALSE, because b.unicode() != 0 + b.isEmpty(); // TRUE, because b.length() == 0 + \endcode + + \sa isEmpty(), length() +*/ + +/*! + \fn bool QString::isEmpty() const + + Returns TRUE if the string is empty, i.e. if length() == 0. + An empty string is not always a null string. + + See example in isNull(). + + \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() +*/ + +/*! + Truncates the string at position \a newLen if newLen is less than the + current length . Otherwise, nothing happens. + + Example: + \code + QString s = "truncate this string"; + s.truncate( 5 ); // s == "trunc" + \endcode + + In Qt 1.x, it was possible to "truncate" a string to a longer + length. This is no longer possible. + +*/ + +void QString::truncate( uint newLen ) +{ + if ( newLen < d->len ) + setLength( newLen ); +} + +/*### Make this public in 3.0 + Ensures that at least \a newLen characters are allocated, and + sets the length to \a newLen. This function always detaches the + string from other references to the same data. Any new space + allocated is \e not defined. + + If \a newLen is 0, this string becomes empty, unless this string is + null, in which case it remains null. + + \sa truncate(), isNull(), isEmpty() +*/ + +void QString::setLength( uint newLen ) +{ + if ( d->count != 1 || newLen > d->maxl || // detach, grow, or + ( newLen*4 < d->maxl && d->maxl > 4 ) ) { // shrink + Q2HELPER(stat_copy_on_write++) + Q2HELPER(stat_copy_on_write_size+=d->len) + uint newMax = 4; + while ( newMax < newLen ) + newMax *= 2; + QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + 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->dirtyascii = 1; + } +} + +/*! Returns a string equal to this one, but with the lowest-numbered + occurrence of \c %i (for a positive integer i) replaced by \a a. + + \code + label.setText( tr("Rename %1 to %2?").arg(oldName).arg(newName) ); + \endcode + + \a fieldwidth is the minimum amount of space \a a is padded to. A + positive value produces right-aligned text, while a negative value + produces left aligned text. + + \warning Using arg() for constructing "real" sentences + programmatically is likely to lead to translation problems. + Inserting objects like numbers or file names is fairly safe. + + \warning Relying on spaces to create alignment is prone to lead to + translation problems. + + If there is no \c %i pattern, a warning message (qWarning()) is + printed and the text as appended at the end of the string. This is + error recovery and should not occur in correct code. + + \sa QObject::tr() +*/ +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", + (const char *)this, (const char *)a ); + // 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 + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. +*/ +QString QString::arg(long a, int fieldwidth, int base) const +{ + return arg( QString::number( a, base ), fieldwidth ); +} + +/*! \overload + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. +*/ +QString QString::arg(ulong a, int fieldwidth, int base) const +{ + return arg( QString::number( a, base ), fieldwidth ); +} + +/*! + \overload QString QString::arg(int a, int fieldwidth, int base) const + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. + +*/ + +/*! + \overload QString QString::arg(uint a, int fieldwidth, int base) const + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. +*/ + +/*! + \overload QString QString::arg(short a, int fieldwidth, int base) const + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. +*/ + +/*! + \overload QString QString::arg(ushort a, int fieldwidth, int base) const + + \a a is expressed in to \a base notation, which is decimal by + default and must be in the range 2-36 inclusive. +*/ + + +/*! \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 + + \a is formatted according to the \a fmt format specified, which is + 'g' by default and can be any of 'f', 'F', 'e', 'E', 'g' or 'G', all + of which have the same meaning as for sprintf(). \a prec determines + the precision, just as for number() and sprintf(). +*/ +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; + for (uint i=0; i<length(); i++) { + if ( at(i) == '%' && i+1<length() ) { + char dig = at(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 a format string 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 QString::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() +*/ + +QString &QString::sprintf( const char* cformat, ... ) +{ + va_list ap; + va_start( ap, cformat ); + + if ( !cformat || !*cformat ) { + // Qt 1.x compat + *this = QString::fromLatin1( "" ); + return *this; + } + QString format = QString::fromLatin1( cformat ); + + static QRegExp *escape = 0; + if (!escape) + escape = new QRegExp( "%#?0?-? ?\\+?'?[0-9*]*\\.?[0-9*]*h?l?L?q?Z?" ); + + QString result; + uint last = 0; + + int len = 0; + int pos; + while ( 1 ) { + pos = escape->match( format, last, &len ); + // 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 ); + // Yes, %-5s really means left adjust in sprintf + + if ( wpos < 0 ) { + QRegExp num( QString::fromLatin1("[0-9]+") ); + QRegExp dot( QString::fromLatin1("\\.") ); + int nlen; + int p = num.match( f, 0, &nlen ); + int q = dot.match( f, 0 ); + if ( q < 0 || (p < q && p >= 0) ) + width = f.mid( p, nlen ).toInt(); + if ( q >= 0 ) { + p = num.match( f, q ); + // "decimals" is used to specify string truncation + if ( p >= 0 ) + decimals = f.mid( p, nlen ).toInt(); + } + } + + if ( format[pos+len] == 's' ) { +#ifndef QT_NO_TEXTCODEC + QString s = QString::fromUtf8(va_arg(ap, char*)); +#else + QString s = QString::fromLatin1(va_arg(ap, char*)); +#endif + if ( decimals <= 0 ) + replacement = s; + else + replacement = 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); + 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; + } + } break; + case 'e': case 'E': case 'f': 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; + } + } 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 ); break; + } + } break; + } + replacement = QString::fromLatin1(out); + } + result += replacement; + } + *this = result; + + va_end( ap ); + return *this; +} + +/*! + Fills the string with \a len characters of value \a c. + + If \a len is negative, the current string length is used. +*/ + +void 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; + } +} + + +/*! + \fn QString QString::copy() const + + \obsolete + + Returns a deep copy of this string. + + Doing this is redundant in Qt 2.x, since QString is implicitly + shared, and so will automatically be deeply copied as necessary. +*/ + +/*! + 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; etc. + + 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. +*/ + +int QString::find( QChar c, int index, bool cs ) const +{ + if ( index < 0 ) + index += length(); + if ( (uint)index >= length() ) // index outside string + return -1; + register const QChar *uc; + uc = unicode()+index; + int n = length()-index; + if ( cs ) { + while ( n-- && *uc != c ) + uc++; + } else { + c = c.lower(); + while ( n-- && uc->lower() != c ) + uc++; + } + if ( uint(uc - unicode()) >= length() ) + return -1; + return (int)(uc - unicode()); +} + +/*! + 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 -2, at the next to last character; etc. + + 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. +*/ + +int QString::find( const QString& str, int index, bool cs ) const +{ + /* + We use some weird 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. + + The hash value of a string is the sum of the cells of its + QChars. + */ + if ( index < 0 ) + index += length(); + int lstr = str.length(); + int lthis = length() - index; + if ( (uint)lthis > length() ) + return -1; + int delta = lthis - lstr; + if ( delta < 0 ) + return -1; + + const QChar *uthis = unicode() + index; + const QChar *ustr = str.unicode(); + uint hthis = 0; + uint hstr = 0; + int i; + if ( cs ) { + for ( i = 0; i < lstr; i++ ) { + hthis += uthis[i].cell(); + hstr += ustr[i].cell(); + } + i = 0; + while ( TRUE ) { + if ( hthis == hstr && ucstrncmp(uthis + i, ustr, lstr) == 0 ) + return index + i; + if ( i == delta ) + return -1; + hthis += uthis[i + lstr].cell(); + hthis -= uthis[i].cell(); + i++; + } + } else { + for ( i = 0; i < lstr; i++ ) { + hthis += uthis[i].lower().cell(); + hstr += ustr[i].lower().cell(); + } + i = 0; + while ( TRUE ) { + if ( hthis == hstr && ucstrnicmp(uthis + i, ustr, lstr) == 0 ) + return index + i; + if ( i == delta ) + return -1; + hthis += uthis[i + lstr].lower().cell(); + hthis -= uthis[i].lower().cell(); + i++; + } + } +#if defined(Q_SPURIOUS_NON_VOID_WARNING) + return -1; +#endif +} + +/*! + \fn int QString::findRev( const char* str, int index ) const + + Equivalent to findRev(QString(str), index). +*/ + +/*! + \fn int QString::find( const char* str, int index ) const + + Equivalent to find(QString(str), index). +*/ + +/*! + Finds the first occurrence of the character \a c, starting at + position \a index and searching backwards. If \a index is -1, + the search starts at the last character; if -2, at the next to + last character; etc. + + 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. +*/ + +int QString::findRev( QChar c, int index, bool cs ) const +{ + QString t( c ); + return findRev( t, index, cs ); +} + +/*! + Finds the first occurrence of the string \a str, starting at + position \a index and searching backwards. If \a index is -1, + the search starts at the last character; -2, at the next to last + character; etc. + + The search is case sensitive if \a cs is TRUE, or case insensitive if \e + cs is FALSE. + + Returns the position of \a str, or -1 if \a str could not be found. +*/ + +int QString::findRev( const QString& str, int index, bool cs ) const +{ + /* + See QString::find() for explanations. + */ + int lthis = length(); + if ( index < 0 ) + index += lthis; + + int lstr = str.length(); + int delta = lthis - lstr; + if ( index < 0 || index > lthis || delta < 0 ) + return -1; + if ( index > delta ) + index = delta; + + const QChar *uthis = unicode(); + const QChar *ustr = str.unicode(); + uint hthis = 0; + uint hstr = 0; + int i; + if ( cs ) { + for ( i = 0; i < lstr; i++ ) { + hthis += uthis[index + i].cell(); + hstr += ustr[i].cell(); + } + i = index; + while ( TRUE ) { + if ( hthis == hstr && ucstrncmp(uthis + i, ustr, lstr) == 0 ) + return i; + if ( i == 0 ) + return -1; + i--; + hthis -= uthis[i + lstr].cell(); + hthis += uthis[i].cell(); + } + } else { + for ( i = 0; i < lstr; i++ ) { + hthis += uthis[index + i].lower().cell(); + hstr += ustr[i].lower().cell(); + } + i = index; + while ( TRUE ) { + if ( hthis == hstr && ucstrnicmp(uthis + i, ustr, lstr) == 0 ) + return i; + if ( i == 0 ) + return -1; + i--; + hthis -= uthis[i + lstr].lower().cell(); + hthis += uthis[i].lower().cell(); + } + } +#if defined(Q_SPURIOUS_NON_VOID_WARNING) + return -1; +#endif +} + + +/*! + 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 + is FALSE. +*/ + +int QString::contains( QChar c, bool cs ) const +{ + int count = 0; + const QChar *uc = unicode(); + if ( !uc ) + return 0; + int n = length(); + if ( cs ) { // case sensitive + while ( n-- ) + if ( *uc++ == c ) + count++; + } else { // case insensitive + c = c.lower(); + while ( n-- ) { + if ( uc->lower() == c ) + count++; + uc++; + } + } + return count; +} + +/*! + \overload +*/ +int QString::contains( const char* str, bool cs ) const +{ + return contains(QString(str),cs); +} + +/*! + \overload int QString::contains (char c, bool cs) const +*/ + +/*! + \overload int QString::find (char c, int index, bool cs) const + +*/ + +/*! + \overload int QString::findRev (char c, int index, bool cs) const + +*/ + +/*! + 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 \e + cs is FALSE. + + This function counts overlapping substrings, for example, "banana" + contains two occurrences of "ana". + + \sa findRev() +*/ + +int QString::contains( const QString &str, bool cs ) const +{ + int count = 0; + const QChar *uc = unicode(); + if ( !uc ) + return 0; + int len = str.length(); + int n = length(); + while ( n-- ) { // counts overlapping strings + // ### Doesn't account for length of this - searches over "end" + if ( cs ) { + if ( ucstrncmp( uc, str.unicode(), len ) == 0 ) + count++; + } else { + if ( ucstrnicmp(uc, str.unicode(), len) == 0 ) + count++; + } + uc++; + } + 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 + 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 QString::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 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 + QString s = "Pineapple"; + QString t = s.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 QString::fromLatin1(""); + } else { + uint l = length(); + if ( len > l ) + len = l; + QString s( len, TRUE ); + memcpy( s.d->unicode, d->unicode+(l-len), len*sizeof(QChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a substring 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+len exceeds + the length of the string. + + Example: + \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 QString::fromLatin1(""); + } else { + if ( len > slen-index ) + len = slen - index; + if ( index == 0 && len == length() ) + 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 and padded by the \a fill character. + + If the length of the string exceeds \a width and \a truncate is FALSE, + 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 + 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 pad + characters followed by the string. + + If the length of the string exceeds \a width and \a truncate is FALSE, + 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 + QString s("pie"); + QString t = s.rightJustify(8, '.'); // t == ".....pie" + \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 new string that is the string converted to lower case. + + Example: + \code + QString s("TeX"); + QString t = s.lower(); // t == "tex" + \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 = p->lower(); + p++; + } + } + } + return s; +} + +/*! + Returns a new string that is the string converted to upper case. + + Example: + \code + QString s("TeX"); + QString t = s.upper(); // t == "TEX" + \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 = p->upper(); + p++; + } + } + } + return s; +} + + +/*! + Returns a new string that has white space removed from the start and the end. + + White space means any character for which QChar::isSpace() returns + TRUE. This includes ASCII characters 9 (TAB), 10 (LF), 11 (VT), 12 + (FF), 13 (CR), and 32 (Space). + + Example: + \code + QString s = " space "; + QString t = s.stripWhiteSpace(); // t == "space" + \endcode + + \sa simplifyWhiteSpace() +*/ + +QString QString::stripWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return *this; + if ( !at(0).isSpace() && !at(length()-1).isSpace() ) + return *this; + + register const QChar *s = unicode(); + QString result = fromLatin1(""); + + 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 + return result; + } + while ( end && s[end].isSpace() ) // skip white space from end + end--; + int l = end - start + 1; + result.setLength( l ); + if ( l ) + memcpy( result.d->unicode, &s[start], sizeof(QChar)*l ); + 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 any character for which QChar::isSpace() returns + TRUE. This includes ASCII characters 9 (TAB), 10 (LF), 11 (VT), 12 + (FF), 13 (CR), and 32 (Space). + + \code + QString s = " lots\t of\nwhite space "; + QString t = s.simplifyWhiteSpace(); // t == "lots of white space" + \endcode + + \sa stripWhiteSpace() +*/ + +QString QString::simplifyWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return *this; + QString result; + result.setLength( length() ); + const QChar *from = unicode(); + const QChar *fromend = from+length(); + int outc=0; + QChar *to = result.d->unicode; + while ( TRUE ) { + 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; +} + + +/*! + Insert \a s into the string before position \a index. + + If \a index is beyond the end of the string, the string is extended with + spaces (ASCII 32) to length \a index and \a s is then appended. + + \code + QString s = "I like fish"; + s.insert( 2, "don't "); // s == "I don't like fish" + s = "x"; + s.insert( 3, "yz" ); // s == "x yz" + \endcode +*/ + +QString &QString::insert( uint index, const QString &s ) +{ + // the sub function takes care of &s == this case. + return insert( index, s.unicode(), s.length() ); +} + +/*! + Insert \a len units of QChar data from \a s into the string before + position \a index. +*/ + +QString &QString::insert( uint index, const QChar* s, uint len ) +{ + if ( len == 0 ) + return *this; + uint olen = length(); + int nlen = olen + len; + + int df = s - d->unicode; // ### pointer subtraction, cast down to int + if ( df >= 0 && (uint)df < 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; +} + +/*! + Insert \a c into the string at (before) 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. + + Example: + \code + QString s = "Ys"; + s.insert( 1, 'e' ); // s == "Yes" + s.insert( 3, '!'); // s == "Yes!" + \endcode + + \sa remove(), replace() +*/ + +QString &QString::insert( uint index, QChar c ) // insert char +{ + QString s( c ); + return insert( index, s ); +} + +/*! + \overload QString& QString::insert( uint index, char c ) +*/ + +/*! + \fn QString &QString::prepend( const QString &s ) + + Prepend \a s to the string. Equivalent to insert(0,s). + + \sa insert() +*/ + +/*! + \fn QString& QString::prepend( char ch ) + Prepends \a ch to the string and returns a reference to the result. + + \sa insert() + */ + +/*! + \fn QString& QString::prepend( QChar ch ) + Prepends \a ch to the string and returns a reference to the result. + + \sa insert() + */ + + +/*! + Removes \a len characters starting at position \a index from the + string and returns a reference to the string. + + If \a index is too big, nothing happens. If \a index is valid, but + \a len is too large, the rest of the string is removed. + + \code + QString s = "Montreal"; + s.remove( 1, 4 ); + // s == "Meal" + \endcode + + \sa insert(), replace() +*/ + +QString &QString::remove( uint index, uint len ) +{ + uint olen = length(); + if ( index + len >= olen ) { // range problems + if ( index < 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; +} + +/*! + Replaces \a len characters starting at position \a index from the + string with \a s, and returns a reference to the string. + + If \a index is too big, nothing is deleted and \a s is inserted at the + end of the string. If \a index is valid, but \a len is too large, \e + str replaces the rest of the string. + + \code + QString s = "Say yes!"; + s.replace( 4, 3, "NO" ); // s == "Say NO!" + \endcode + + \sa insert(), remove() +*/ + +QString &QString::replace( uint index, uint len, const QString &s ) +{ + return replace( index, len, s.unicode(), s.length() ); +} + + +/*! + Replaces \a len characters starting at position \a index by + \a slen units ot QChar data from \a s, and returns a reference to the string. + + \sa insert(), remove() +*/ + +QString &QString::replace( uint index, uint len, const QChar* s, uint slen ) +{ + if ( len == slen && index + len <= length() ) { + // Optimized common case: replace without size change + real_detach(); + memcpy( d->unicode+index, s, len*sizeof(QChar) ); + } else { + int df = s - d->unicode; // ### pointer subtraction, cast down to int + if ( df >= 0 && (uint)df < 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 ); + return *this; + } + + remove( index, len ); + insert( index, s, slen ); + } + return *this; +} + + + +/*! + Finds the first occurrence of the regular expression \a rx, 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; etc. + + Returns the position of the next match, or -1 if \a rx was not found. + + \sa findRev() replace() contains() +*/ + +int QString::find( const QRegExp &rx, int index ) const +{ + if ( index < 0 ) + index += length(); + return rx.match( *this, index ); +} + +/*! + Finds the first occurrence of the regular expression \a rx, starting at + position \a index and searching backwards. If \a index is -1, the + search starts at the last character; if -2, at the next to last + character; etc. + + Returns the position of the next match (backwards), or -1 if \a rx was not + found. + + \sa find() +*/ + +int QString::findRev( const QRegExp &rx, int index ) const +{ + if ( index < 0 ) // neg index ==> start from end + index += length(); + if ( (uint)index > length() ) // bad index + return -1; + while( index >= 0 ) { + if ( rx.match( *this, index ) == index ) + return index; + index--; + } + return -1; +} + +/*! + 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() +*/ + +int QString::contains( const QRegExp &rx ) const +{ + if ( isEmpty() ) + return rx.match( *this ) < 0 ? 0 : 1; + int count = 0; + int index = -1; + int len = length(); + while ( index < len-1 ) { // count overlapping matches + index = rx.match( *this, index+1 ); + if ( index < 0 ) + break; + count++; + } + return count; +} + + +/*! + Replaces every occurrence of \a rx in the string with \a str. + Returns a reference to the string. + + Examples: + \code + QString s = "banana"; + s.replace( QRegExp("a.*a"), "" ); // becomes "b" + + QString s = "banana"; + s.replace( QRegExp("^[bn]a"), " " ); // becomes " nana" + + QString s = "banana"; + s.replace( QRegExp("^[bn]a"), "" ); // NOTE! becomes "" + \endcode + + \sa find() findRev() +*/ + +QString &QString::replace( const QRegExp &rx, const QString &str ) +{ + if ( isEmpty() ) + return *this; + int index = 0; + int slen = str.length(); + int len; + while ( index < (int)length() ) { + index = rx.match( *this, index, &len, FALSE ); + if ( index >= 0 ) { + replace( index, len, str ); + index += slen; + if ( !len ) + break; // Avoid infinite loop on 0-length matches, e.g. [a-z]* + } + else + break; + } + return *this; +} + +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 <code>long</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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 && *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 <code>unsigned long</code> + value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +ulong QString::toULong( bool *ok, int base ) const +{ + const QChar *p = unicode(); + ulong val=0; + int l = length(); + const ulong max_mult = 429496729; // UINT_MAX/10, rounded down + bool is_ok = FALSE; + if ( !p ) + goto bye; + while ( l && p->isSpace() ) // skip leading space + l--,p++; + 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 <code>short</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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 <code>unsigned short</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, or if + it has trailing garbage. +*/ + +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 a <code>int</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +int QString::toInt( bool *ok, int base ) const +{ + return (int)toLong( ok, base ); +} + +/*! + Returns the string converted to an <code>unsigned int</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +uint QString::toUInt( bool *ok, int base ) const +{ + return (uint)toULong( ok, base ); +} + +/*! + Returns the string converted to a <code>double</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no conceivable + errors, and FALSE if the string is not a number at all, or if it has + trailing garbage. +*/ + +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 == '\0' ) ); + return val; +} + +/*! + Returns the string converted to a <code>float</code> value. + + If \a ok is non-null, \a *ok is set to TRUE if there are no + conceivable errors, and FALSE if the string is not a number at all, + or if it has trailing garbage. +*/ + +float QString::toFloat( bool *ok ) const +{ + return (float)toDouble( ok ); +} + + +/*! + Sets the string to the printed value of \a n and returns a + reference to the string. + + The value is converted to \a base notation (default is decimal). + The base must be a value from 2 to 36. +*/ + +QString &QString::setNum( long n, int base ) +{ +#if defined(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 ); +} + +/*! + Sets the string to the printed unsigned value of \a n and + returns a reference to the string. + + The value is converted to \a base notation (default is decimal). + The base must be a value from 2 to 36. +*/ + +QString &QString::setNum( ulong n, int base ) +{ +#if defined(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 ) + Sets the string to the printed value of \a n and returns a reference + to the string. +*/ + +/*! + \fn QString &QString::setNum( uint n, int base ) + Sets the string to the printed unsigned value of \a n and returns a + reference to the string. +*/ + +/*! + \fn QString &QString::setNum( short n, int base ) + Sets the string to the printed value of \a n and returns a reference + to the string. +*/ + +/*! + \fn QString &QString::setNum( ushort n, int base ) + Sets the string to the printed unsigned value of \a n and returns a + reference to the string. +*/ + +/*! Sets the string to the printed value of \a n, formatted in the \a f + format with \a prec precision, and returns a reference to the + string. + + \a f can be 'f', 'F', 'e', 'E', 'g' or 'G', all of which have the + same meaning as for sprintf(). +*/ + +QString &QString::setNum( double n, char f, int prec ) +{ +#if defined(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 buf[120]; // enough for 99 precision? + char *fs = format; // generate format string + *fs++ = '%'; // "%.<prec>l<f>" + if ( prec >= 0 ) { + if ( prec > 99 ) // buf big enough for precision? + prec = 99; + *fs++ = '.'; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + } + *fs++ = 'l'; + *fs++ = f; + *fs = '\0'; + ::sprintf( buf, format, n ); + return setLatin1(buf); +} + +/*! + \overload QString &QString::setNum( float n, char f, int prec ) +*/ + + +/*! + A convenience factory function that returns a string representation + of the number \a n. + + \sa setNum() + */ +QString QString::number( long n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + A convenience factory function that returns a string representation + of the number \a n. + + \sa setNum() + */ +QString QString::number( ulong n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + A convenience factory function that returns a string representation + of the number \a n. + + \sa setNum() + */ +QString QString::number( int n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + A convenience factory function that returns a string representation + of the number \a n. + + \sa setNum() + */ +QString QString::number( uint n, int base ) +{ + QString s; + s.setNum( n, base ); + return s; +} + +/*! + This static function returns the printed value of \a n, formatted in the \f + format with \a prec precision. + + \a f can be 'f', 'F', 'e', 'E', 'g' or 'G', all of which have the + same meaning as for sprintf(). + + \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 2.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 it is a null string, otherwise FALSE. Thus + you can write: + +\code + QString name = getName(); + if ( !name ) + name = "Rodney"; +\endcode + + Note that if you say: + +\code + QString name = getName(); + if ( name ) + doSomethingWith(name); +\endcode + + Then this will call <tt>operator const char*()</tt>, which will do what + you want, but rather inefficiently - you may wish to define the macro + QT_NO_ASCII_CAST when writing code which you wish to strictly remain + Unicode-clean. + + When you want the above semantics, use <tt>!isNull()</tt> + or even <tt>!!</tt>: + +\code + QString name = getName(); + if ( !!name ) + doSomethingWith(name); +\endcode +*/ + + +/*! + \fn QString& QString::append( const QString& str ) + Appends \a str to the string and returns a reference to the result. + Equivalent to operator+=(). + */ + +/*! + \fn QString& QString::append( char ch ) + Appends \a ch to the string and returns a reference to the result. + Equivalent to operator+=(). + */ + +/*! + \fn QString& QString::append( QChar ch ) + Appends \a ch 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; +} + +/*! + 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; +} + +/*! + 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 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 ) { + if ( d->dirtyascii ) + delete [] d->ascii; + else + return d->ascii; + } + Q2HELPER(stat_get_ascii++) + Q2HELPER(stat_get_ascii_size+=d->len) + d->ascii = unicodeToAscii( d->unicode, d->len ); + d->dirtyascii = 0; + return d->ascii; +} + +/*! \obsolete + + This functions simply calls latin1() and returns the result. +*/ +const char* QString::ascii() const +{ + return latin1(); +} + +#ifndef QT_NO_TEXTCODEC +/*! + 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 +{ + static QTextCodec* codec = QTextCodec::codecForMib(106); + return codec + ? codec->fromUnicode(*this) + : QCString(latin1()); +} + +/*! + Returns the unicode string decoded from the + first \a len bytes of \a utf8. If \a len is -1 (the default), the + length of \a utf8 is used. If trailing partial characters are in + \a utf8, they are ignored. + + See QTextCodec for more diverse coding/decoding of Unicode strings. +*/ +QString QString::fromUtf8(const char* utf8, int len) +{ + static QTextCodec* codec = QTextCodec::codecForMib(106); + if ( len < 0 ) len = qstrlen(utf8); + return codec + ? codec->toUnicode(utf8, len) + : QString::fromLatin1(utf8, len); +} +#endif // QT_NO_TEXTCODEC +/*! + Creates a QString from Latin1 text. This is the same as the + QString(const char*) constructor, but you can make that constructor + invisible if you compile with the define QT_NO_CAST_ASCII, in which + case you can explicitly create a QString from Latin-1 text using + this function. +*/ +QString QString::fromLatin1(const char* chars, int len) +{ + uint l; + QChar *uc; + if ( len < 0 ) { + uc = internalAsciiToUnicode(chars,&l); + } else { + 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. + + 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 _WS_X11_ + static QTextCodec* codec = QTextCodec::codecForLocale(); + return codec + ? codec->fromUnicode(*this) + : QCString(latin1()); +#endif +#ifdef _WS_MAC_ + static QTextCodec* codec = QTextCodec::codecForLocale(); + return codec + ? codec->fromUnicode(*this) + : QCString(latin1()); +#endif +#ifdef _WS_WIN_ + return qt_winQString2MB( *this ); +#endif +#ifdef _WS_QWS_ + return utf8(); // ##### if there is ANY 8 bit format supported? +#endif +#endif +} + +/*! + Returns the unicode string decoded from the + first \a len bytes of \a local8Bit. If \a len is -1 (the default), the + length of \a local8Bit is used. If trailing partial characters are in + \a local8Bit, they are ignored. + + \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 _WS_X11_ + static QTextCodec* codec = QTextCodec::codecForLocale(); + if ( len < 0 ) len = qstrlen(local8Bit); + return codec + ? codec->toUnicode(local8Bit, len) + : QString::fromLatin1(local8Bit,len); +#endif +#ifdef _WS_MAC_ + static QTextCodec* codec = QTextCodec::codecForLocale(); + if ( len < 0 ) len = qstrlen(local8Bit); + return codec + ? codec->toUnicode(local8Bit, len) + : QString::fromLatin1(local8Bit,len); +#endif +// Should this be OS_WIN32? +#ifdef _WS_WIN_ + if ( len >= 0 ) { + QCString s(local8Bit,len+1); + return qt_winMB2QString(s); + } + return qt_winMB2QString( local8Bit ); +#endif +#ifdef _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 there. + Note that for new code which you wish to be strictly Unicode-clean, + you can define the macro 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 under operator!(). +*/ + +/*! + \fn QChar QString::at( uint ) const + + Returns the character at \a i, or 0 if \a i is beyond the length + of the string. + + Note: If this QString is not const or const&, the non-const at() + will be used instead, which will expand the string if \a i is beyond + the length of the string. +*/ + +/*! + \fn QChar QString::constref(uint i) const + Equivalent to at(i), this returns the QChar at \a i by value. + + \sa ref() +*/ + +/*! + \fn QChar& QString::ref(uint i) + Returns the QChar at \a i by reference. + + \sa constref() +*/ + +/*! + \fn QChar QString::operator[](int) const + + Returns the character at \a i, or QChar::null if \a i is beyond the + length of the string. + + Note: If this QString is not const or const&, the non-const operator[] + will be used instead, which will expand the string if \a i is beyond + the length of the string. +*/ + +/*! + \fn QCharRef QString::operator[](int) + + Returns an object that references the character at \a i. + This reference + can then be assigned to, or otherwise used immediately, but + becomes invalid once further modifications are made to 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 enlarges + and detaches itself). You will get compilation errors if you try to + use the result as anything but a QChar. +*/ + +/*! + \fn QCharRef QString::at( uint i ) + Returns a reference to the character at \a i, expanding + the string with QChar::null if necessary. The resulting reference + can then be assigned to, or otherwise used immediately, but + becomes invalid once further modifications are made to the string. +*/ + +/*! + 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 unicode characters and copies \a unicode + into the string. If \a unicode is null, nothing is copied, but the + string is resized to \a len anyway. If \a len is zero, 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(); + } + } 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 = 4; + while ( newMax < len ) + newMax *= 2; + 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->dirtyascii = 1; + if ( unicode ) + memcpy( d->unicode, unicode, sizeof(QChar)*len ); + } + return *this; +} + +/*! + Resizes the string to \a len unicode 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 is null, nothing is copied, but the + string is resized to \a len anyway. 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 ) +{ + setUnicode((const QChar*)unicode_as_ushorts, len); + QChar t(0x1234); + if ( unicode_as_ushorts && *((ushort*)&t) == 0x3412 ) { + // Need to byteswap + char* b = (char*)d->unicode; + while ( len-- ) { + char c = b[0]; + b[0] = b[1]; + b[1] = c; + b += sizeof(QChar); + } + } + return *this; +} + + +/*! + Sets this string to \a str, interpreted as a classic Latin 1 C string. + If the \a len argument is negative (default), 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 + deref(); + uint l; + QChar *uc = internalAsciiToUnicode(str,&l); + d = new QStringData(uc,l,l); + } else { + setUnicode( 0, len ); // resize but not copy + QChar *p = d->unicode; + while ( len-- ) + *p++ = *str++; + } + return *this; +} + + +/*! + \fn int QString::compare (const QString & s1, const QString & s2) + + Compare \a s1 to \a s2 returning an integer less than, equal to, or + greater than zero if s1 is, respectively, lexically less than, equal to, + or greater than s2. +*/ + +/*! + Compares this string to \a s, returning an integer less than, equal to, or + greater than zero if it is, respectively, lexically less than, equal to, + or greater than \a s. +*/ +int QString::compare( const QString& s ) const +{ + return ucstrcmp(*this,s); +} + +bool operator==( const QString &s1, const QString &s2 ) +{ + 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 ) +{ return s1==QString(s2); } + +bool operator==( const char *s1, const QString &s2 ) +{ return QString(s1)==s2; } + +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 the two strings are equal, or FALSE if they are different. + A null string is different from an empty, non-null string. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator==( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if the two strings are equal, or FALSE if they are different. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator==( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if the two strings are equal, or FALSE if they are different. + + Equivalent to <code>qstrcmp(s1,s2) == 0</code>. +*/ + +/*! + \fn bool operator!=( const QString &s1, const QString &s2 ) + \relates QString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator!=( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator!=( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if the two strings are different, or FALSE if they are equal. + + Equivalent to <code>qstrcmp(s1,s2) != 0</code>. +*/ + +/*! + \fn bool operator<( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically less than \a s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \< 0</code>. +*/ + +/*! + \fn bool operator<( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically less than \a s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \< 0</code>. +*/ + +/*! + \fn bool operator<=( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically less than or equal to \a s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \<= 0</code>. +*/ + +/*! + \fn bool operator<=( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically less than or equal to \a s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \<= 0</code>. +*/ + +/*! + \fn bool operator>( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically greater than \a s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \> 0</code>. +*/ + +/*! + \fn bool operator>( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically greater than \a s2, otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \> 0</code>. +*/ + +/*! + \fn bool operator>=( const QString &s1, const char *s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically greater than or equal to \a s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \>= 0</code>. +*/ + +/*! + \fn bool operator>=( const char *s1, const QString &s2 ) + \relates QString + Returns TRUE if \a s1 is alphabetically greater than or equal to \a s2, + otherwise FALSE. + + Equivalent to <code>qstrcmp(s1,s2) \>= 0</code>. +*/ + +/*! + \fn QString operator+( const QString &s1, const QString &s2 ) + \relates QString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QString operator+( const QString &s1, const char *s2 ) + \relates QString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QString operator+( const char *s1, const QString &s2 ) + \relates QString + Returns the concatenated string of s1 and s2. +*/ + +/*! + \fn QString operator+( const QString &s, char c ) + \relates QString + Returns the concatenated string of s and c. +*/ + +/*! + \fn QString operator+( char c, const QString &s ) + \relates QString + Returns the concatenated string of c and s. +*/ + + +/***************************************************************************** + QString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \relates QString + Writes a string to the stream. + + \sa \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 { + const char* ub = (const char*)str.unicode(); + if ( ub || s.version() < 3 ) { + if ( QChar::networkOrdered() == + (s.byteOrder()==QDataStream::BigEndian) ) { + s.writeBytes( ub, sizeof(QChar)*str.length() ); + } else { + 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-- ) { + *c++ = ub[1]; + *c++ = ub[0]; + ub+=sizeof(QChar); + } + 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. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>( QDataStream &s, QString &str ) +{ +#ifdef QT_QSTRING_UCS_4 +#warning "operator>> not working properly" +#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 + str.setLength( bytes/2 ); + char* b = (char*)str.d->unicode; + s.readRawBytes( b, bytes ); + if ( QChar::networkOrdered() != + (s.byteOrder()==QDataStream::BigEndian) ) { + bytes /= 2; + while ( bytes-- ) { + char c = b[0]; + b[0] = b[1]; + b[1] = c; + b += 2; + } + } + } else { + str = ""; + } + } + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + QConstString member functions + *****************************************************************************/ + +/*! + \class QConstString qstring.h + \brief A QString which uses 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 user's responsibility to make sure + that the Unicode data must exist for the entire lifetime of the + QConstString object. +*/ + +/*! + 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. + + Note that \a unicode is \e not \e copied. The caller \e must be + able to guarantee that \a unicode will not be deleted or + modified. Since that is generally not the case with \c const strings + (they are references), this constructor demands a non-const pointer + even though it never modifies \a unicode. +*/ +QConstString::QConstString( QChar* unicode, uint length ) : + QString(new QStringData(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 whether the strings starts with \a s, or not. + */ +bool QString::startsWith( const QString& s ) const +{ + for ( int i =0; i < (int) s.length(); i++ ) { + if ( i >= (int) length() || d->unicode[i] != s[i] ) + return FALSE; + } + return TRUE; +} + + + +#if defined(_OS_WIN32_) + +#include <windows.h> + +/*! + Returns a static Windows TCHAR* from a QString, possibly adding NUL. + + The lifetime of the return value is until the next call to this function. +*/ +const void* qt_winTchar(const QString& str_in, bool addnul) +{ + // So that the return value lives long enough. + static QString str; + str = str_in; + +#ifdef UNICODE + static uint buflen = 256; + static TCHAR *buf = new TCHAR[buflen]; + + const QChar* uc = str.unicode(); + +#define EXTEND if (str.length() > buflen) { delete buf; buf = new TCHAR[buflen=str.length()+1]; } + +#if defined(_WS_X11_) || defined(_OS_WIN32_BYTESWAP_) + EXTEND + for ( int i=str.length(); i--; ) + buf[i] = uc[i].row() << 8 | uc[i].cell(); + if ( addnul ) + buf[str.length()] = 0; +#else + // Same endianness of TCHAR + if ( addnul ) { + EXTEND + memcpy(buf,uc,sizeof(TCHAR)*str.length()); + buf[str.length()] = 0; + } else { + return uc; + } +#endif + return buf; +#undef EXTEND + +#else + return str.latin1(); +#endif +} + +/*! + Makes a new null terminated Windows TCHAR* from a QString. +*/ +void* qt_winTchar_new(const QString& str) +{ + TCHAR* result = new TCHAR[str.length()+1]; + memcpy(result, qt_winTchar(str,FALSE), sizeof(TCHAR)*str.length()); + result[str.length()] = 0; + return result; +} + +/*! + Makes a QString from a Windows TCHAR*. +*/ +QString qt_winQString(void* tc) +{ +#ifdef UNICODE + + int len=0; + while ( ((TCHAR*)tc)[len] ) + len++; +#if defined(_WS_X11_) || defined(_OS_WIN32_BYTESWAP_) + QString r; + for ( int i=0; i<len; i++ ) + r += QChar(((TCHAR*)tc)[i]&0xff,((TCHAR*)tc)[i]>>8); + return r; +#else + // Same endianness of TCHAR + return QString((QChar*)tc,len); +#endif +#undef EXTEND +#else + return (TCHAR*)tc; +#endif +} + +QCString qt_winQString2MB( const QString& s, int uclen ) +{ + if ( uclen < 0 ) + uclen = s.length(); + 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 { + // Fail. + qWarning("WideCharToMultiByte cannot convert multibyte text (error %d): %s (UTF8)", + r, s.utf8().data()); + 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 // _OS_WIN32_ diff --git a/qtools/qstring.h b/qtools/qstring.h new file mode 100644 index 0000000..f955f32 --- /dev/null +++ b/qtools/qstring.h @@ -0,0 +1,821 @@ +/**************************************************************************** +** +** +** 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; + +class Q_EXPORT Q_PACKED 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_Dask, // Pd + 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 + }; + + // ****** 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; + QString decomposition() const; + Decomposition decompositionTag() const; + + char latin1() const { return rw ? 0 : cl; } + ushort unicode() const { return (rw << 8) | cl; } +#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; + + uchar& cell() { return cl; } + uchar& row() { return rw; } + uchar cell() const { return cl; } + uchar row() const { return rw; } + + static bool networkOrdered() { return (int)net_ordered == 1; } + + friend inline int operator==( char ch, QChar c ); + friend inline int operator==( QChar c, char ch ); + friend inline int operator==( QChar c1, QChar c2 ); + friend inline int operator!=( QChar c1, QChar c2 ); + friend inline int operator!=( char ch, QChar c ); + friend inline int operator!=( QChar c, char ch ); + friend inline int operator<=( QChar c, char ch ); + friend inline int operator<=( char ch, QChar c ); + friend inline int operator<=( QChar c1, QChar c2 ); + +private: +#if defined(_WS_X11_) || defined(_OS_WIN32_BYTESWAP_) || defined( _WS_QWS_ ) + // XChar2b on X11, ushort on _OS_WIN32_BYTESWAP_ + //### QWS must be defined on a platform by platform basis + uchar rw; + uchar cl; +#if defined(QT_QSTRING_UCS_4) + ushort grp; +#endif + enum { net_ordered = 1 }; +#else + // ushort on _OS_WIN32_ + uchar cl; + uchar rw; +#if defined(QT_QSTRING_UCS_4) + ushort grp; +#endif + enum { net_ordered = 0 }; +#endif +}; + +inline QChar::QChar() +{ + rw = 0; cl = 0; +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( char c ) +{ + rw = 0; cl = (uchar)c; +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( uchar c ) +{ + rw = 0; cl = c; +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( uchar c, uchar r ) +{ + rw = r; cl = c; +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( const QChar& c ) +{ + rw = c.rw; cl = c.cl; +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( ushort rc ) +{ + rw = (uchar)((rc>>8)&0xff); cl = (uchar)(rc&0xff); +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( short rc ) +{ + rw = (uchar)((rc>>8)&0xff); cl = (uchar)(rc&0xff); +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( uint rc ) +{ + rw = (uchar)((rc>>8)&0xff); cl = (uchar)(rc&0xff); +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} +inline QChar::QChar( int rc ) +{ + rw = (uchar)((rc>>8)&0xff); cl = (uchar)(rc&0xff); +#ifdef QT_QSTRING_UCS_4 + grp = 0; +#endif +} + + +inline int operator==( char ch, QChar c ) +{ + return ch == c.cl && !c.rw; +} + +inline int operator==( QChar c, char ch ) +{ + return ch == c.cl && !c.rw; +} + +inline int operator==( QChar c1, QChar c2 ) +{ + return c1.cl == c2.cl + && c1.rw == c2.rw; +} + +inline int operator!=( QChar c1, QChar c2 ) +{ + return c1.cl != c2.cl + || c1.rw != c2.rw; +} + +inline int operator!=( char ch, QChar c ) +{ + return ch != c.cl || c.rw; +} + +inline int operator!=( QChar c, char ch ) +{ + return ch != c.cl || c.rw; +} + +inline int operator<=( QChar c, char ch ) +{ + return !(ch < c.cl || c.rw); +} + +inline int operator<=( char ch, QChar c ) +{ + return ch <= c.cl || c.rw; +} + +inline int operator<=( QChar c1, QChar c2 ) +{ + return c1.rw > c2.rw + ? FALSE + : c1.rw < c2.rw + ? TRUE + : c1.cl <= c2.cl; +} + +inline int operator>=( QChar c, char ch ) { return ch <= c; } +inline int operator>=( char ch, QChar c ) { return c <= ch; } +inline int operator>=( QChar c1, QChar c2 ) { return c2 <= c1; } +inline int operator<( QChar c, char ch ) { return !(ch<=c); } +inline int operator<( char ch, QChar c ) { return !(c<=ch); } +inline int operator<( QChar c1, QChar c2 ) { return !(c2<=c1); } +inline int operator>( QChar c, char ch ) { return !(ch>=c); } +inline int operator>( char ch, QChar c ) { return !(c>=ch); } +inline int operator>( QChar c1, QChar c2 ) { return !(c2>=c1); } + +// internal +struct Q_EXPORT QStringData : public QShared { + QStringData() : + unicode(0), ascii(0), len(0), maxl(0), dirtyascii(0) { ref(); } + QStringData(QChar *u, uint l, uint m) : + unicode(u), ascii(0), len(l), maxl(m), dirtyascii(0) { } + + ~QStringData() { if ( unicode ) delete[] ((char*)unicode); + if ( ascii ) delete[] ascii; } + + void deleteSelf(); + QChar *unicode; + char *ascii; + uint len; + uint maxl:30; + uint dirtyascii:1; +}; + + +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 ); + +#if QT_VERSION >= 300 +#error "fill() Should return *this, or QChar constructor should take count=1" +#endif + void 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; + + QString &sprintf( const char* format, ... ) +#if defined(_CC_GNU_) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#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; + int find( const QRegExp &, int index=0 ) const; +#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; + int findRev( const QRegExp &, int index=-1 ) const; +#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; + int contains( const QRegExp & ) const; + + 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 & ); + QString &prepend( char ); + QString &prepend( QChar ); + QString &prepend( const QString & ); + QString &remove( uint index, uint len ); + QString &replace( uint index, uint len, const QString & ); + QString &replace( uint index, uint len, const QChar*, uint clen ); + QString &replace( const QRegExp &, const QString & ); + + 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 ); + QString &operator+=( QChar c ); + QString &operator+=( char c ); + + // Your compiler is smart enough to use the const one if it can. + 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->dirtyascii=1; + return d->unicode[i]; + } + + const QChar* unicode() const { return d->unicode; } + const char* ascii() const; + const char* latin1() const; + static QString fromLatin1(const char*, int len=-1); +#ifndef QT_NO_TEXTCODEC + QCString utf8() const; + static QString fromUtf8(const char*, int len=-1); +#endif + 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 + + 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); } + +#ifndef QT_NO_DATASTREAM + friend Q_EXPORT QDataStream &operator>>( QDataStream &, QString & ); +#endif + // new functions for BiDi + void compose(); + QChar::Direction basicDirection(); + QString visual(int index = 0, int len = -1); + +#ifndef QT_NO_COMPAT + const char* data() const { return latin1(); } +#endif + + bool startsWith( const QString& ) const; + +private: + QString( int size, bool dummy ); // allocate size incl. \0 + + void deref(); + void real_detach(); + void setLength( uint pos ); + void subat( uint ); + bool findArg(int& pos, int& len) 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; + QString(QStringData* dd, bool /*dummy*/) : d(dd) { } +}; + +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. +#if 1 + 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() { return s.constref(p).lower(); } + QChar upper() { 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(); } + QString decomposition() const { return s.constref(p).decomposition(); } + QChar::Decomposition decompositionTag() const { return s.constref(p).decompositionTag(); } + + // 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( 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() ) + d->deleteSelf(); +} + +inline QString &QString::operator=( QChar c ) +{ return *this = QString(c); } + +inline QString &QString::operator=( char c ) +{ return *this = QString(QChar(c)); } + +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); } + +inline QString &QString::append( const QString & s ) +{ return operator+=(s); } + +inline QString &QString::append( QChar c ) +{ return operator+=(c); } + +inline QString &QString::append( char c ) +{ return operator+=(c); } + +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 QString operator+( const QString &s1, const QString &s2 ) +{ + QString tmp( s1 ); + tmp += s2; + return tmp; +} + +#ifndef QT_NO_CAST_ASCII +Q_EXPORT inline QString operator+( const QString &s1, const char *s2 ) +{ + QString tmp( s1 ); + tmp += QString::fromLatin1(s2); + return tmp; +} + +Q_EXPORT inline QString operator+( const char *s1, const QString &s2 ) +{ + QString tmp = QString::fromLatin1( s1 ); + tmp += s2; + return tmp; +} +#endif + +Q_EXPORT inline QString operator+( const QString &s1, QChar c2 ) +{ + QString tmp( s1 ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline QString operator+( const QString &s1, char c2 ) +{ + QString tmp( s1 ); + tmp += c2; + return tmp; +} + +Q_EXPORT inline QString operator+( QChar c1, const QString &s2 ) +{ + QString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +Q_EXPORT inline QString operator+( char c1, const QString &s2 ) +{ + QString tmp; + tmp += c1; + tmp += s2; + return tmp; +} + +#if defined(_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/qtools/qstringlist.cpp b/qtools/qstringlist.cpp new file mode 100644 index 0000000..ff4f33e --- /dev/null +++ b/qtools/qstringlist.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** +** 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 "qstrlist.h" +#include "qdatastream.h" +#include "qtl.h" + +// NOT REVISED +/*! + \class QStringList qstringlist.h + \brief A list of strings. + + \ingroup qtl + \ingroup tools + \ingroup shared + + QStringList is basically a QValueList of QString objects. As opposed + to QStrList, that stores pointers to characters, QStringList deals + with real QString objects. It is the class of choice whenever you + work with unicode strings. + + Like QString itself, QStringList objects are implicit shared. + Passing them around as value-parameters is both fast and safe. + + Example: + \code + QStringList list; + + // three different ways of appending values: + list.append( "Torben"); + list += "Warwick"; + list << "Matthias" << "Arnt" << "Paul"; + + // sort the list, Arnt's now first + list.sort(); + + // print it out + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + printf( "%s \n", (*it).latin1() ); + } + \endcode + + Convenience methods such as sort(), split(), join() and grep() make + working with QStringList easy. +*/ + +/*! + \fn QStringList::QStringList() + Creates an empty list. +*/ + +/*! \fn QStringList::QStringList( const QStringList& l ) + Creates a copy of the list. This function is very fast since + QStringList is implicit shared. However, for the programmer this + is the same as a deep copy. If this list or the original one or some + other list referencing the same shared data is modified, then the + modifying list makes a copy first. +*/ + +/*! + \fn QStringList::QStringList (const QString & i) + Constructs a string list consisting of the single string \a i. + To make longer lists easily, use: + \code + QString s1,s2,s3; + ... + QStringList mylist = QStringList() << s1 << s2 << s3; + \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 order. + + Sorting is very fast. It uses the Qt Template Library's + efficient HeapSort implementation that operates in O(n*log n). +*/ +void QStringList::sort() +{ + qHeapSort(*this); +} + +/*! + Splits the string \a str using \a sep as separator. Returns the + list of strings. If \a allowEmptyEntries is TRUE, also empty + entries are inserted into the list, else not. So if you have + a string 'abc..d.e.', a list which contains 'abc', 'd', and 'e' + would be returned if \a allowEmptyEntries is FALSE, but + a list containing 'abc', '', 'd', 'e' and '' would be returned if + \a allowEmptyEntries is TRUE. + If \a str doesn't contain \a sep, a stringlist + with one item, which is the same as \a str, is returned. + + \sa join() +*/ + +QStringList QStringList::split( const QChar &sep, const QString &str, bool allowEmptyEntries ) +{ + return split( QString( sep ), str, allowEmptyEntries ); +} + +/*! + Splits the string \a str using \a sep as separator. Returns the + list of strings. If \a allowEmptyEntries is TRUE, also empty + entries are inserted into the list, else not. So if you have + a string 'abc..d.e.', a list which contains 'abc', 'd', and 'e' + would be returned if \a allowEmptyEntries is FALSE, but + a list containing 'abc', '', 'd', 'e' and '' would be returned if + \a allowEmptyEntries is TRUE. + If \a str doesn't contain \a sep, a stringlist + with one item, which is the same as \a str, is returned. + + \sa join() +*/ + +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 ( str.mid( j, i - j ).length() > 0 ) + lst << str.mid( j, i - j ); + else if ( allowEmptyEntries ) + lst << QString::null; + j = i + sep.length(); + i = str.find( sep, 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; +} + +/*! + Splits the string \a str using the regular expression \a sep as separator. Returns the + list of strings. If \a allowEmptyEntries is TRUE, also empty + entries are inserted into the list, else not. So if you have + a string 'abc..d.e.', a list which contains 'abc', 'd', and 'e' + would be returned if \a allowEmptyEntries is FALSE, but + a list containing 'abc', '', 'd', 'e' and '' would be returned if + \a allowEmptyEntries is TRUE. + If \a str doesn't contain \a sep, a stringlist + with one item, which is the same as \a str, is returned. + + \sa join() +*/ + +QStringList QStringList::split( const QRegExp &sep, const QString &str, bool allowEmptyEntries ) +{ + QStringList lst; + + int j = 0; + int len = 0; + int i = sep.match( str, j, &len ); + + while ( i != -1 ) { + if ( str.mid( j, i - j ).length() > 0 ) + lst << str.mid( j, i - j ); + else if ( allowEmptyEntries ) + lst << QString::null; + j = i + len; + i = sep.match( str, j, &len ); + } + + 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; +} + +/*! + Returns a list of all strings containing the substring \a str. + + If \a cs is TRUE, the grep is done case sensitively, else not. +*/ + +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; +} + +/*! + Returns a list of all strings containing a substring that matches + 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; +} + +/*! + Joins the stringlist into a single string with each element + separated by \a sep. + + \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 a QStrList (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/qtools/qstringlist.h b/qtools/qstringlist.h new file mode 100644 index 0000000..03342c5 --- /dev/null +++ b/qtools/qstringlist.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** +** 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 "qregexp.h" +#endif // QT_H + +#ifndef QT_NO_STRINGLIST + +class QStrList; + +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 ); + static QStringList split( const QRegExp &sep, const QString &str, bool allowEmptyEntries = FALSE ); + QString join( const QString &sep ) const; + + QStringList grep( const QString &str, bool cs = TRUE ) const; + QStringList grep( const QRegExp &expr ) const; +}; + +#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/qtools/qstrlist.h b/qtools/qstrlist.h new file mode 100644 index 0000000..c6a1864 --- /dev/null +++ b/qtools/qstrlist.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** +** 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 "qlist.h" +#include "qdatastream.h" +#endif // QT_H + + +#if defined(Q_TEMPLATEDLL) +template class Q_EXPORT QList<char>; +template class Q_EXPORT QListIterator<char>; +#endif + +typedef QList<char> QStrListBase; +typedef QListIterator<char> QStrListIterator; + + +class Q_EXPORT QStrList : public QStrListBase +{ +public: + QStrList( bool deepCopies=TRUE ) { dc = deepCopies; del_item = deepCopies; } + QStrList( const QStrList & ); + ~QStrList() { clear(); } + QStrList& operator=( const QStrList & ); + +private: + QCollection::Item newItem( QCollection::Item d ) { return dc ? qstrdup( (const char*)d ) : d; } + void deleteItem( QCollection::Item d ) { if ( del_item ) delete[] (char*)d; } + int compareItems( QCollection::Item s1, QCollection::Item s2 ) { return qstrcmp((const char*)s1, + (const char*)s2); } +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream &s, QCollection::Item &d ) + { s >> (char *&)d; return s; } + QDataStream &write( QDataStream &s, QCollection::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( QCollection::Item s1, QCollection::Item s2 ) + { return qstricmp((const char*)s1, + (const char*)s2); } +}; + + +inline QStrList & QStrList::operator=( const QStrList &strList ) +{ + clear(); + dc = strList.dc; + del_item = dc; + QStrListBase::operator=(strList); + return *this; +} + +inline QStrList::QStrList( const QStrList &strList ) + : QStrListBase( strList ) +{ + dc = FALSE; + operator=(strList); +} + + +#endif // QSTRLIST_H diff --git a/qtools/qstrvec.h b/qtools/qstrvec.h new file mode 100644 index 0000000..15d3abb --- /dev/null +++ b/qtools/qstrvec.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** +** Definition of QStrVec and QStrIVec classes +** +** Created : 931203 +** +** 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 QSTRVEC_H +#define QSTRVEC_H + +#ifndef QT_H +#include "qstring.h" +#include "qvector.h" +#include "qdatastream.h" +#endif // QT_H + + +#if defined(Q_TEMPLATEDLL) +template class Q_EXPORT QVector<char> +#endif + +typedef QVector<char> QStrVecBase; + + +class Q_EXPORT QStrVec : public QStrVecBase +{ +public: + QStrVec() { dc = TRUE; } + QStrVec( uint size, bool deepc = TRUE ) : QStrVecBase(size) {dc=deepc;} + ~QStrVec() { clear(); } +private: + Item newItem( Item d ) { return dc ? qstrdup( (const char*)d ) : d; } + void deleteItem( Item d ) { if ( dc ) delete[] (char*)d; } + int compareItems( Item s1, Item s2 ) + { return qstrcmp((const char*)s1, + (const char*)s2); } +#ifndef QT_NO_DATASTREAM + QDataStream &read( QDataStream &s, Item &d ) + { s >> (char *&)d; return s; } + QDataStream &write( QDataStream &s, Item d ) const + { return s << (const char*)d; } +#endif + bool dc; +}; + + +class Q_EXPORT QStrIVec : public QStrVec // case insensitive string vec +{ +public: + QStrIVec() {} + QStrIVec( uint size, bool dc = TRUE ) : QStrVec( size, dc ) {} + ~QStrIVec() { clear(); } +private: + int compareItems( Item s1, Item s2 ) + { return qstricmp((const char*)s1, + (const char*)s2); } +}; + + +#endif // QSTRVEC_H diff --git a/qtools/qtextcodec.cpp b/qtools/qtextcodec.cpp new file mode 100644 index 0000000..af43a3a --- /dev/null +++ b/qtools/qtextcodec.cpp @@ -0,0 +1,2019 @@ +/**************************************************************************** +** +** +** Implementation 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. +** +**********************************************************************/ + +#include "qtextcodec.h" +#ifndef QT_NO_TEXTCODEC + +#include "qlist.h" +#ifndef QT_NO_CODECS +#include "qutfcodec.h" +#include "qgbkcodec.h" +#include "qeucjpcodec.h" +#include "qjiscodec.h" +#include "qsjiscodec.h" +#include "qeuckrcodec.h" +#include "qbig5codec.h" +#include "qrtlcodec.h" +#include "qtsciicodec.h" +#endif + +#include "qfile.h" +#include "qstrlist.h" +#include "qstring.h" + +#include <stdlib.h> +#include <ctype.h> +#include <locale.h> + + +static QList<QTextCodec> * all = 0; +static bool destroying_is_ok; // starts out as 0 + +/*! Deletes all the created codecs. + + \warning Do not call this function. + + QApplication calls this just before exiting, to delete any + QTextCodec objects that may be lying around. Since various other + classes hold pointers to QTextCodec objects, it is not safe to call + this function earlier. + + If you are using the utility classes (like QString) but not using + QApplication, calling this function at the very end of your + application can be helpful to chasing down memory leaks, as + QTextCodec objects will not show up. +*/ + +void QTextCodec::deleteAllCodecs() +{ + if ( !all ) + return; + + destroying_is_ok = TRUE; + QList<QTextCodec> * ball = all; + all = 0; + ball->clear(); + delete ball; + destroying_is_ok = FALSE; +} + + +static void setupBuiltinCodecs(); + + +static void realSetup() +{ +#if defined(CHECK_STATE) + if ( destroying_is_ok ) + qWarning( "creating new codec during codec cleanup" ); +#endif + all = new QList<QTextCodec>; + all->setAutoDelete( TRUE ); + setupBuiltinCodecs(); +} + + +static inline void setup() +{ + if ( !all ) + realSetup(); +} + + +class QTextStatelessEncoder: public QTextEncoder { + const QTextCodec* codec; +public: + QTextStatelessEncoder(const QTextCodec*); + QCString fromUnicode(const QString& uc, int& lenInOut); +}; + + +class QTextStatelessDecoder : public QTextDecoder { + const QTextCodec* codec; +public: + QTextStatelessDecoder(const QTextCodec*); + QString toUnicode(const char* chars, int len); +}; + +QTextStatelessEncoder::QTextStatelessEncoder(const QTextCodec* c) : + codec(c) +{ +} + + +QCString QTextStatelessEncoder::fromUnicode(const QString& uc, int& lenInOut) +{ + return codec->fromUnicode(uc,lenInOut); +} + + +QTextStatelessDecoder::QTextStatelessDecoder(const QTextCodec* c) : + codec(c) +{ +} + + +QString QTextStatelessDecoder::toUnicode(const char* chars, int len) +{ + return codec->toUnicode(chars,len); +} + + + +// NOT REVISED +/*! + \class QTextCodec qtextcodec.h + \brief Provides conversion between text encodings. + + By making objects of subclasses of QTextCodec, support for + new text encodings can be added to Qt. + + The abstract virtual functions describe the encoder to the + system and the coder is used as required in the different + text file formats supported QTextStream and, under X11 for the + locale-specific character input and output (under Windows NT + codecs are not needed for GUI I/O since the system works + with Unicode already, and Windows 95/98 has built-in convertors + for the 8-bit local encoding). + + More recently created QTextCodec objects take precedence + over earlier ones. + + To add support for another 8-bit encoding to Qt, make a subclass + or QTextCodec and implement at least the following methods: + <dl> + <dt>\c const char* name() const + <dd>Return the official name for the encoding. + <dt>\c int mibEnum() const + <dd>Return the MIB enum for the encoding if it is listed in the + <a href=ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets> + IANA character-sets encoding file</a>. + </dl> + If the encoding is multi-byte then it will have "state"; that is, + the interpretation of some bytes will be dependent on some preceding + bytes. For such an encoding, you will need to implement + <dl> + <dt> \c QTextDecoder* makeDecoder() const + <dd>Return a QTextDecoder that remembers incomplete multibyte + sequence prefixes or other required state. + </dl> + If the encoding does \e not require state, you should implement: + <dl> + <dt> \c QString toUnicode(const char* chars, int len) const + <dd>Converts \e len characters from \e chars to Unicode. + </dl> + The base QTextCodec class has default implementations of the above + two functions, <i>but they are mutually recursive</i>, so you must + re-implement at least one of them, or both for improved efficiency. + + For conversion from Unicode to 8-bit encodings, it is rarely necessary + to maintain state. However, two functions similar to the two above + are used for encoding: + <dl> + <dt> \c QTextEncoder* makeEncoder() const + <dd>Return a QTextDecoder. + <dt> \c QCString fromUnicode(const QString& uc, int& lenInOut ) const; + <dd>Converts \e lenInOut characters (of type QChar) from the start + of the string \a uc, returning a QCString result, and also returning + the \link QCString::length() length\endlink + of the result in lenInOut. + </dl> + Again, these are mutually recursive so only one needs to be implemented, + or both if better efficiency is possible. + + Finally, you must implement: + <dl> + <dt> \c int heuristicContentMatch(const char* chars, int len) const + <dd>Gives a value indicating how likely it is that \e len characters + from \e chars are in the encoding. + </dl> + A good model for this function is the + QWindowsLocalCodec::heuristicContentMatch function found in the Qt sources. + + A QTextCodec subclass might have improved performance if you also + re-implement: + <dl> + <dt> \c bool canEncode( QChar ) const + <dd>Test if a Unicode character can be encoded. + <dt> \c bool canEncode( const QString& ) const + <dd>Test if a string of Unicode characters can be encoded. + <dt> \c int heuristicNameMatch(const char* hint) const + <dd>Test if a possibly non-standard name is referring to the codec. + </dl> +*/ + + +/*! + Constructs a QTextCodec, making it of highest precedence. + The QTextCodec should always be constructed on the heap + (with new), and once constructed it becomes the responsibility + of Qt to delete it (which is done at QApplication destruction). +*/ +QTextCodec::QTextCodec() +{ + setup(); + all->insert(0,this); +} + + +/*! + Destructs the QTextCodec. Note that you should not delete + codecs yourself - once created they become the responsibility + of Qt to delete. +*/ +QTextCodec::~QTextCodec() +{ + if ( !destroying_is_ok ) + qWarning("QTextCodec::~QTextCodec() called by application"); + if ( all ) + all->remove( this ); +} + + +/*! + Returns a value indicating how likely this decoder is + for decoding some format that has the given name. + + A good match returns a positive number around + the length of the string. A bad match is negative. + + The default implementation calls simpleHeuristicNameMatch() + with the name of the codec. +*/ +int QTextCodec::heuristicNameMatch(const char* hint) const +{ + return simpleHeuristicNameMatch(name(),hint); +} + + +// returns a string cotnaining the letters and numbers from input, +// with a space separating run of a character class. e.g. "iso8859-1" +// becomes "iso 8859 1" +static QString lettersAndNumbers( const char * input ) +{ + QString result; + QChar c; + + while( input && *input ) { + c = *input; + if ( c.isLetter() || c.isNumber() ) + result += c.lower(); + if ( input[1] ) { + // add space at character class transition, except + // transition from upper-case to lower-case letter + QChar n( input[1] ); + if ( c.isLetter() && n.isLetter() ) { + if ( c == c.lower() && n == n.upper() ) + result += ' '; + } else if ( c.category() != n.category() ) { + result += ' '; + } + } + input++; + } + return result.simplifyWhiteSpace(); +} + +/*! + A simple utility function for heuristicNameMatch() - it + does some very minor character-skipping + so that almost-exact matches score high. +*/ +int QTextCodec::simpleHeuristicNameMatch(const char* name, const char* hint) +{ + // if they're the same, return a perfect score. + if ( name && hint && qstrcmp( name, hint ) == 0 ) + return qstrlen( hint ); + + // if the letters and numbers are the same, we have an "almost" + // perfect match. + QString h( lettersAndNumbers( hint ) ); + QString n( lettersAndNumbers( name ) ); + if ( h == n ) + return qstrlen( hint )-1; + + if ( h.stripWhiteSpace() == n.stripWhiteSpace() ) + return qstrlen( hint )-2; + + // could do some more here, but I don't think it's worth it + + return 0; +} + + +/*! + Returns the QTextCodec \a i places from the more recently + inserted, or NULL if there is no such QTextCodec. Thus, + codecForIndex(0) returns the most recently created QTextCodec. +*/ +QTextCodec* QTextCodec::codecForIndex(int i) +{ + setup(); + return (uint)i >= all->count() ? 0 : all->at(i); +} + + +/*! + Returns the QTextCodec which matches the + \link QTextCodec::mibEnum() MIBenum\endlink \a mib. +*/ +QTextCodec* QTextCodec::codecForMib(int mib) +{ + setup(); + QListIterator<QTextCodec> i(*all); + QTextCodec* result; + for ( ; (result=i); ++i ) { + if ( result->mibEnum()==mib ) + break; + } + return result; +} + + + + + +#ifdef _OS_WIN32_ +class QWindowsLocalCodec: public QTextCodec +{ +public: + QWindowsLocalCodec(); + ~QWindowsLocalCodec(); + + QString toUnicode(const char* chars, int len) const; + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + const char* name() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; +}; + +QWindowsLocalCodec::QWindowsLocalCodec() +{ +} + +QWindowsLocalCodec::~QWindowsLocalCodec() +{ +} + + +QString QWindowsLocalCodec::toUnicode(const char* chars, int len) const +{ + if ( len == 1 && chars ) { // Optimization; avoids allocation + char c[2]; + c[0] = *chars; + c[1] = 0; + return qt_winMB2QString( c, 2 ); + } + if ( len < 0 ) + return qt_winMB2QString( chars ); + QCString s(chars,len+1); + return qt_winMB2QString(s); +} + +QCString QWindowsLocalCodec::fromUnicode(const QString& uc, int& lenInOut ) const +{ + QCString r = qt_winQString2MB( uc, lenInOut ); + lenInOut = r.length(); + return r; +} + + +const char* QWindowsLocalCodec::name() const +{ + return "System"; +} + +int QWindowsLocalCodec::mibEnum() const +{ + return 0; +} + + +int QWindowsLocalCodec::heuristicContentMatch(const char* chars, int len) const +{ + // ### Not a bad default implementation? + QString t = toUnicode(chars,len); + int l = t.length(); + QCString mb = fromUnicode(t,l); + int i=0; + while ( i < len ) + if ( chars[i] == mb[i] ) + i++; + return i; +} + +#else + +/* locale names mostly copied from XFree86 */ +static const char * const iso8859_2locales[] = { + "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr", + "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro", + "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk", + "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 }; + +static const char * const iso8859_3locales[] = { + "eo", 0 }; + +static const char * const iso8859_5locales[] = { + "bg", "bg_BG", "bulgarian", "mk", "mk_MK", + "sp", "sp_YU", 0 }; + +static const char * const iso8859_6locales[] = { + "ar_AA", "ar_SA", "arabic", 0 }; + +static const char * const iso8859_7locales[] = { + "el", "el_GR", "greek", 0 }; + +static const char * const iso8859_8locales[] = { + "hebrew", "iw", "iw_IL", 0 }; + +static const char * const iso8859_9locales[] = { + "tr", "tr_TR", "turkish", 0 }; + +static const char * const iso8859_15locales[] = { + "fr", "fi", "french", "finnish", 0 }; + + +static bool try_locale_list( const char * const locale[], const char * lang ) +{ + int i; + for( i=0; locale[i] && qstrcmp(locale[i], lang); i++ ) + { } + return locale[i] != 0; +} + +// For the probably_koi8_locales we have to look. the standard says +// these are 8859-5, but almsot all Russion users uses KOI8-R and +// incorrectly set $LANG to ru_RU. We'll check tolower() to see what +// tolower() thinks ru_RU means. + +// If you read the history, it seems that many Russians blame ISO and +// Peristroika for the confusion. +// +// The real bug is that some programs break if the user specifies +// ru_RU.KOI8-R. + +static const char * const probably_koi8_rlocales[] = { + "ru", "ru_SU", "ru_RU", "russian", 0 }; + +// this means ANY of these locale aliases. if they're aliases for +// different locales, the code breaks. +static QTextCodec * ru_RU_codec = 0; + +static QTextCodec * ru_RU_hack( const char * i ) { + if ( ! ru_RU_codec ) { + QCString origlocale = setlocale( LC_CTYPE, i ); + // unicode koi8r latin5 name + // 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU + // 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU + int latin5 = tolower( 0xCE ); + int koi8r = tolower( 0xE0 ); + if ( koi8r == 0xC0 && latin5 != 0xEE ) { + ru_RU_codec = QTextCodec::codecForName( "KOI8-R" ); + } else if ( koi8r != 0xC0 && latin5 == 0xEE ) { + ru_RU_codec = QTextCodec::codecForName( "ISO 8859-5" ); + } else { + // something else again... let's assume... *throws dice* + ru_RU_codec = QTextCodec::codecForName( "KOI8-R" ); + qWarning( "QTextCodec: using KOI8-R, probe failed (%02x %02x %s)", + koi8r, latin5, i ); + } + setlocale( LC_CTYPE, origlocale.data() ); + } + return ru_RU_codec; +} + +#endif + +static QTextCodec * localeMapper = 0; + +/*! Returns a pointer to the codec most suitable for this locale. */ + +QTextCodec* QTextCodec::codecForLocale() +{ + if ( localeMapper ) + return localeMapper; + + setup(); + +#ifdef _OS_WIN32_ + localeMapper = new QWindowsLocalCodec; +#else + // Very poorly defined and followed standards causes lots of code + // to try to get all the cases... + + char * lang = qstrdup( getenv("LANG") ); + + char * p = lang ? strchr( lang, '.' ) : 0; + if ( !p || *p != '.' ) { + // Some versions of setlocale return encoding, others not. + char *ctype = qstrdup( setlocale( LC_CTYPE, 0 ) ); + // Some Linux distributions have broken locales which will return + // "C" for LC_CTYPE + if ( qstrcmp( ctype, "C" ) == 0 ) { + delete [] ctype; + } else { + if ( lang ) + delete [] lang; + lang = ctype; + p = lang ? strchr( lang, '.' ) : 0; + } + } + + if( p && *p == '.' ) { + // if there is an encoding and we don't know it, we return 0 + // User knows what they are doing. Codecs will believe them. + localeMapper = codecForName( lang ); + if ( !localeMapper ) { + // Use or codec disagree. + localeMapper = codecForName( p+1 ); + } + } + if ( !localeMapper || !(p && *p == '.') ) { + // if there is none, we default to 8859-1 + // We could perhaps default to 8859-15. + if ( try_locale_list( iso8859_2locales, lang ) ) + localeMapper = codecForName( "ISO 8859-2" ); + else if ( try_locale_list( iso8859_3locales, lang ) ) + localeMapper = codecForName( "ISO 8859-3" ); + else if ( try_locale_list( iso8859_5locales, lang ) ) + localeMapper = codecForName( "ISO 8859-5" ); + else if ( try_locale_list( iso8859_6locales, lang ) ) + localeMapper = codecForName( "ISO 8859-6" ); + else if ( try_locale_list( iso8859_7locales, lang ) ) + localeMapper = codecForName( "ISO 8859-7" ); + else if ( try_locale_list( iso8859_8locales, lang ) ) + localeMapper = codecForName( "ISO 8859-8" ); + else if ( try_locale_list( iso8859_9locales, lang ) ) + localeMapper = codecForName( "ISO 8859-9" ); + else if ( try_locale_list( iso8859_15locales, lang ) ) + localeMapper = codecForName( "ISO 8859-15" ); + else if ( try_locale_list( probably_koi8_rlocales, lang ) ) + localeMapper = ru_RU_hack( lang ); + else if (!lang || !(localeMapper = codecForName(lang) )) + localeMapper = codecForName( "ISO 8859-1" ); + } + delete[] lang; +#endif + + return localeMapper; +} + + +/*! + Searches all installed QTextCodec objects, returning the one + which best matches given name. Returns NULL if no codec has + a match closeness above \a accuracy. + + \sa heuristicNameMatch() +*/ +QTextCodec* QTextCodec::codecForName(const char* hint, int accuracy) +{ + setup(); + QListIterator<QTextCodec> i(*all); + QTextCodec* result = 0; + int best=accuracy; + for ( QTextCodec* cursor; (cursor=i); ++i ) { + int s = cursor->heuristicNameMatch(hint); + if ( s > best ) { + best = s; + result = cursor; + } + } + return result; +} + + +/*! + Searches all installed QTextCodec objects, returning the one + which most recognizes the given content. May return 0. + + Note that this is often a poor choice, since character + encodings often use most of the available character sequences, + and so only by linguistic analysis could a true match be made. + + \sa heuristicContentMatch() +*/ +QTextCodec* QTextCodec::codecForContent(const char* chars, int len) +{ + setup(); + QListIterator<QTextCodec> i(*all); + QTextCodec* result = 0; + int best=0; + for ( QTextCodec* cursor; (cursor=i); ++i ) { + int s = cursor->heuristicContentMatch(chars,len); + if ( s > best ) { + best = s; + result = cursor; + } + } + return result; +} + + +/*! + \fn const char* QTextCodec::name() const + Subclasses of QTextCodec must reimplement this function. It returns + the name of the encoding supported by the subclass. When choosing + a name for an encoding, consider these points: + <ul> + <li>On X11, heuristicNameMatch( const char * hint ) + is used to test if a the QTextCodec + can convert between Unicode and the encoding of a font + with encoding \e hint, such as "iso8859-1" for Latin-1 fonts, + "koi8-r" for Russian KOI8 fonts. + The default algorithm of heuristicNameMatch() uses name(). + <li>Some applications may use this function to present + encodings to the end user. + </ul> +*/ + +/*! + \fn int QTextCodec::mibEnum() const + + Subclasses of QTextCodec must reimplement this function. It returns the + MIBenum (see + <a href="ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets"> + the IANA character-sets encoding file</a> for more information). + It is important that each QTextCodec subclass return the correct unique + value for this function. +*/ + + +/*! + \fn int QTextCodec::heuristicContentMatch(const char* chars, int len) const + + Subclasses of QTextCodec must reimplement this function. It examines + the first \a len bytes of \a chars and returns a value indicating how + likely it is that the string is a prefix of text encoded in the + encoding of the subclass. Any negative return value indicates that the text + is detectably not in the encoding (eg. it contains undefined characters). + A return value of 0 indicates that the text should be decoded with this + codec rather than as ASCII, but there + is no particular evidence. The value should range up to \a len. Thus, + most decoders will return -1, 0, or -\a len. + + The characters are not null terminated. + + \sa codecForContent(). +*/ + + +/*! + Creates a QTextDecoder which stores enough state to decode chunks + of char* data to create chunks of Unicode data. The default implementation + creates a stateless decoder, which is sufficient for only the simplest + encodings where each byte corresponds to exactly one Unicode character. + + The caller is responsible for deleting the returned object. +*/ +QTextDecoder* QTextCodec::makeDecoder() const +{ + return new QTextStatelessDecoder(this); +} + + +/*! + Creates a QTextEncoder which stores enough state to encode chunks + of Unicode data as char* data. The default implementation + creates a stateless encoder, which is sufficient for only the simplest + encodings where each Unicode character corresponds to exactly one char. + + The caller is responsible for deleting the returned object. +*/ +QTextEncoder* QTextCodec::makeEncoder() const +{ + return new QTextStatelessEncoder(this); +} + + +/*! + Subclasses of QTextCodec must reimplement this function or + makeDecoder(). It converts the first \a len characters of \a chars + to Unicode. + + The default implementation makes a decoder with makeDecoder() and + converts the input with that. Note that the default makeDecoder() + implementation makes a decoder that simply calls + this function, hence subclasses \e must reimplement one function or + the other to avoid infinite recursion. +*/ +QString QTextCodec::toUnicode(const char* chars, int len) const +{ + QTextDecoder* i = makeDecoder(); + QString result = i->toUnicode(chars,len); + delete i; + return result; +} + + +/*! + Subclasses of QTextCodec must reimplement either this function or + makeEncoder(). It converts the first \a lenInOut characters of \a + uc from Unicode to the encoding of the subclass. If \a lenInOut + is negative or too large, the length of \a uc is used instead. + + The value returned is the property of the caller, which is + responsible for deleting it with "delete []". The length of the + resulting Unicode character sequence is returned in \a lenInOut. + + The default implementation makes an encoder with makeEncoder() and + converts the input with that. Note that the default makeEncoder() + implementation makes an encoder that simply calls + this function, hence subclasses \e must reimplement one function or + the other to avoid infinite recursion. +*/ + +QCString QTextCodec::fromUnicode(const QString& uc, int& lenInOut) const +{ + QTextEncoder* i = makeEncoder(); + QCString result = i->fromUnicode(uc, lenInOut); + delete i; + return result; +} + +/*! + \overload QCString QTextCodec::fromUnicode(const QString& uc) const +*/ +QCString QTextCodec::fromUnicode(const QString& uc) const +{ + int l = uc.length(); + return fromUnicode(uc,l); +} + +/*! + \overload QString QTextCodec::toUnicode(const QByteArray& a, int len) const +*/ +QString QTextCodec::toUnicode(const QByteArray& a, int len) const +{ + return toUnicode(a.data(),len); +} + +/*! + \overload QString QTextCodec::toUnicode(const QByteArray& a) const +*/ +QString QTextCodec::toUnicode(const QByteArray& a) const +{ + return toUnicode(a.data(),a.size()); +} + +/*! + \overload QString QTextCodec::toUnicode(const char* chars) const +*/ +QString QTextCodec::toUnicode(const char* chars) const +{ + return toUnicode(chars,qstrlen(chars)); +} + +/*! + Returns TRUE if the unicode character \a ch can be fully encoded + with this codec. The default implementation tests if the result of + toUnicode(fromUnicode(ch)) is the original \a ch. Subclasses may be + able to improve the efficiency. +*/ +bool QTextCodec::canEncode( QChar ch ) const +{ + return toUnicode(fromUnicode(ch)) == ch; +} + +/*! + Returns TRUE if the unicode string \a s can be fully encoded + with this codec. The default implementation tests if the result of + toUnicode(fromUnicode(s)) is the original \a s. Subclasses may be + able to improve the efficiency. +*/ +bool QTextCodec::canEncode( const QString& s ) const +{ + return toUnicode(fromUnicode(s)) == s; +} + + + +/*! + \class QTextEncoder qtextcodec.h + \brief State-based encoder + + A QTextEncoder converts Unicode into another format, remembering + any state that is required between calls. + + \sa QTextCodec::makeEncoder() +*/ + +/*! + Destructs the encoder. +*/ +QTextEncoder::~QTextEncoder() +{ +} +/*! + \fn QCString QTextEncoder::fromUnicode(const QString& uc, int& lenInOut) + + Converts \a lenInOut characters (not bytes) from \a uc, producing + a QCString. \a lenInOut will also be set to the + \link QCString::length() length\endlink of the result (in bytes). + + The encoder is free to record state to use when subsequent calls are + made to this function (for example, it might change modes with escape + sequences if needed during the encoding of one string, then assume that + mode applies when a subsequent call begins). +*/ + +/*! + \class QTextDecoder qtextcodec.h + \brief State-based decoder + + A QTextEncoder converts a text format into Unicode, remembering + any state that is required between calls. + + \sa QTextCodec::makeEncoder() +*/ + + +/*! + Destructs the decoder. +*/ +QTextDecoder::~QTextDecoder() +{ +} + +/*! + \fn QString QTextDecoder::toUnicode(const char* chars, int len) + + Converts the first \a len bytes at \a chars to Unicode, returning the + result. + + If not all characters are used (eg. only part of a multi-byte + encoding is at the end of the characters), the decoder remembers + enough state to continue with the next call to this function. +*/ + +#define CHAINED 0xffff + +struct QMultiByteUnicodeTable { + // If multibyte, ignore unicode and index into multibyte + // with the next character. + QMultiByteUnicodeTable() : unicode(0xfffd), multibyte(0) { } + + ~QMultiByteUnicodeTable() + { + if ( multibyte ) + delete [] multibyte; + } + + ushort unicode; + QMultiByteUnicodeTable* multibyte; +}; + +static int getByte(char* &cursor) +{ + int byte = 0; + if ( *cursor ) { + if ( cursor[1] == 'x' ) + byte = strtol(cursor+2,&cursor,16); + else if ( cursor[1] == 'd' ) + byte = strtol(cursor+2,&cursor,10); + else + byte = strtol(cursor+2,&cursor,8); + } + return byte&0xff; +} + +#ifndef QT_NO_CODECS +class QTextCodecFromIOD; + +class QTextCodecFromIODDecoder : public QTextDecoder { + const QTextCodecFromIOD* codec; + QMultiByteUnicodeTable* mb; +public: + QTextCodecFromIODDecoder(const QTextCodecFromIOD* c); + QString toUnicode(const char* chars, int len); +}; + +class QTextCodecFromIOD : public QTextCodec { + friend class QTextCodecFromIODDecoder; + + QCString n; + + // If from_unicode_page[row()][cell()] is 0 and from_unicode_page_multibyte, + // use from_unicode_page_multibyte[row()][cell()] as string. + char** from_unicode_page; + char*** from_unicode_page_multibyte; + char unkn; + + // Only one of these is used + ushort* to_unicode; + QMultiByteUnicodeTable* to_unicode_multibyte; + int max_bytes_per_char; + QStrList aliases; + + bool stateless() const { return !to_unicode_multibyte; } + +public: + QTextCodecFromIOD(QIODevice* iod) + { + from_unicode_page = 0; + to_unicode_multibyte = 0; + to_unicode = 0; + from_unicode_page_multibyte = 0; + max_bytes_per_char = 1; + + const int maxlen=100; + char line[maxlen]; + char esc='\\'; + bool incmap = FALSE; + while (iod->readLine(line,maxlen) > 0) { + if (0==qstrnicmp(line,"<code_set_name>",15)) + n = line+15; + else if (0==qstrnicmp(line,"<escape_char>",13)) + esc = line[14]; + else if (0==qstrnicmp(line,"% alias ",8)) { + aliases.append(line+8); + } else if (0==qstrnicmp(line,"CHARMAP",7)) { + if (!from_unicode_page) { + from_unicode_page = new char*[256]; + for (int i=0; i<256; i++) + from_unicode_page[i]=0; + } + if (!to_unicode) { + to_unicode = new ushort[256]; + } + incmap = TRUE; + } else if (0==qstrnicmp(line,"END CHARMAP",11)) + break; + else if (incmap) { + char* cursor = line; + int byte,unicode=-1; + ushort* mb_unicode=0; + const int maxmb=8; // more -> we'll need to improve datastructures + char mb[maxmb+1]; + int nmb=0; + + while (*cursor && *cursor!=' ') + cursor++; + while (*cursor && *cursor!=esc) + cursor++; + byte = getByte(cursor); + + if ( *cursor == esc ) { + if ( !to_unicode_multibyte ) { + to_unicode_multibyte = new QMultiByteUnicodeTable[256]; + for (int i=0; i<256; i++) { + to_unicode_multibyte[i].unicode = to_unicode[i]; + to_unicode_multibyte[i].multibyte = 0; + } + delete [] to_unicode; + to_unicode = 0; + } + QMultiByteUnicodeTable* mbut = to_unicode_multibyte+byte; + mb[nmb++] = byte; + while ( nmb < maxmb && *cursor == esc ) { + // Always at least once + + mbut->unicode = CHAINED; + byte = getByte(cursor); + mb[nmb++] = byte; + if (!mbut->multibyte) { + mbut->multibyte = + new QMultiByteUnicodeTable[256]; + } + mbut = mbut->multibyte+byte; + mb_unicode = & mbut->unicode; + } + + if ( nmb > max_bytes_per_char ) + max_bytes_per_char = nmb; + } + while (*cursor && (*cursor!='<' || cursor[1]!='U')) + cursor++; + if ( *cursor ) + unicode = strtol(cursor+2,&cursor,16); + if (unicode >= 0 && unicode <= 0xffff) + { + QChar ch((ushort)unicode); + if (!from_unicode_page[ch.row()]) { + from_unicode_page[ch.row()] = new char[256]; + for (int i=0; i<256; i++) + from_unicode_page[ch.row()][i]=0; + } + if ( mb_unicode ) { + from_unicode_page[ch.row()][ch.cell()] = 0; + if (!from_unicode_page_multibyte) { + from_unicode_page_multibyte = new char**[256]; + for (int i=0; i<256; i++) + from_unicode_page_multibyte[i]=0; + } + if (!from_unicode_page_multibyte[ch.row()]) { + from_unicode_page_multibyte[ch.row()] = new char*[256]; + for (int i=0; i<256; i++) + from_unicode_page_multibyte[ch.row()][i] = 0; + } + mb[nmb++] = 0; + from_unicode_page_multibyte[ch.row()][ch.cell()] + = qstrdup(mb); + *mb_unicode = unicode; + } else { + from_unicode_page[ch.row()][ch.cell()] = (char)byte; + if ( to_unicode ) + to_unicode[byte] = unicode; + else + to_unicode_multibyte[byte].unicode = unicode; + } + } else { + } + } + } + n = n.stripWhiteSpace(); + + unkn = '?'; // ##### Might be a bad choice. + } + + ~QTextCodecFromIOD() + { + if ( from_unicode_page ) { + for (int i=0; i<256; i++) + if (from_unicode_page[i]) + delete [] from_unicode_page[i]; + } + if ( from_unicode_page_multibyte ) { + for (int i=0; i<256; i++) + if (from_unicode_page_multibyte[i]) + for (int j=0; j<256; j++) + if (from_unicode_page_multibyte[i][j]) + delete [] from_unicode_page_multibyte[i][j]; + } + if ( to_unicode ) + delete [] to_unicode; + if ( to_unicode_multibyte ) + delete [] to_unicode_multibyte; + } + + bool ok() const + { + return !!from_unicode_page; + } + + QTextDecoder* makeDecoder() const + { + if ( stateless() ) + return QTextCodec::makeDecoder(); + else + return new QTextCodecFromIODDecoder(this); + } + + const char* name() const + { + return n; + } + + int mibEnum() const + { + return 0; // #### Unknown. + } + + int heuristicContentMatch(const char*, int) const + { + return 0; + } + + int heuristicNameMatch(const char* hint) const + { + int bestr = QTextCodec::heuristicNameMatch(hint); + QStrListIterator it(aliases); + char* a; + while ((a=it.current())) { + ++it; + int r = simpleHeuristicNameMatch(a,hint); + if (r > bestr) + bestr = r; + } + return bestr; + } + + QString toUnicode(const char* chars, int len) const + { + const uchar* uchars = (const uchar*)chars; + QString result; + QMultiByteUnicodeTable* multibyte=to_unicode_multibyte; + if ( multibyte ) { + while (len--) { + QMultiByteUnicodeTable& mb = multibyte[*uchars]; + if ( mb.multibyte ) { + // Chained multi-byte + multibyte = mb.multibyte; + } else { + result += QChar(mb.unicode); + multibyte=to_unicode_multibyte; + } + uchars++; + } + } else { + while (len--) + result += QChar(to_unicode[*uchars++]); + } + return result; + } + + QCString fromUnicode(const QString& uc, int& lenInOut) const + { + if (lenInOut > (int)uc.length()) + lenInOut = uc.length(); + int rlen = lenInOut*max_bytes_per_char; + QCString rstr(rlen); + char* cursor = rstr.data(); + char* s=0; + int l = lenInOut; + int lout = 0; + for (int i=0; i<l; i++) { + QChar ch = uc[i]; + if ( ch == QChar::null ) { + // special + *cursor++ = 0; + } else if ( from_unicode_page[ch.row()] && + from_unicode_page[ch.row()][ch.cell()] ) + { + *cursor++ = from_unicode_page[ch.row()][ch.cell()]; + lout++; + } else if ( from_unicode_page_multibyte && + from_unicode_page_multibyte[ch.row()] && + (s=from_unicode_page_multibyte[ch.row()][ch.cell()]) ) + { + while (*s) { + *cursor++ = *s++; + lout++; + } + } else { + *cursor++ = unkn; + lout++; + } + } + *cursor = 0; + lenInOut = lout; + return rstr; + } +}; + +QTextCodecFromIODDecoder::QTextCodecFromIODDecoder(const QTextCodecFromIOD* c) : + codec(c) +{ + mb = codec->to_unicode_multibyte; +} + +QString QTextCodecFromIODDecoder::toUnicode(const char* chars, int len) +{ + const uchar* uchars = (const uchar*)chars; + QString result; + while (len--) { + QMultiByteUnicodeTable& t = mb[*uchars]; + if ( t.multibyte ) { + // Chained multi-byte + mb = t.multibyte; + } else { + if ( t.unicode ) + result += QChar(t.unicode); + mb=codec->to_unicode_multibyte; + } + uchars++; + } + return result; +} + +/*! + Reads a POSIX2 charmap definition from \a iod. + The parser recognizes the following lines: +<pre> + <code_set_name> <i>name</i> + <escape_char> <i>character</i> + % alias <i>alias</i> + CHARMAP + <<i>token</i>> /x<i>hexbyte</i> <U<i>unicode</i>> ... + <<i>token</i>> /d<i>decbyte</i> <U<i>unicode</i>> ... + <<i>token</i>> /<i>octbyte</i> <U<i>unicode</i>> ... + <<i>token</i>> /<i>any</i>/<i>any</i>... <U<i>unicode</i>> ... + END CHARMAP +</pre> + + The resulting QTextCodec is returned (and also added to the + global list of codecs). The name() of the result is taken + from the code_set_name. + + Note that a codec constructed in this way uses much more memory + and is slower than a hand-written QTextCodec subclass, since + tables in code are in memory shared by all applications simultaneously + using Qt. + + \sa loadCharmapFile() +*/ +QTextCodec* QTextCodec::loadCharmap(QIODevice* iod) +{ + QTextCodecFromIOD* r = new QTextCodecFromIOD(iod); + if ( !r->ok() ) { + delete r; + r = 0; + } + return r; +} + +/*! + A convenience function for loadCharmap(). +*/ +QTextCodec* QTextCodec::loadCharmapFile(QString filename) +{ + QFile f(filename); + if (f.open(IO_ReadOnly)) { + QTextCodecFromIOD* r = new QTextCodecFromIOD(&f); + if ( !r->ok() ) + delete r; + else + return r; + } + return 0; +} +#endif //QT_NO_CODECS + + +/*! + Returns a string representing the current language. +*/ + +const char* QTextCodec::locale() +{ + static QCString lang; + if ( lang.isEmpty() ) { + lang = getenv( "LANG" ); //########Windows?? + if ( lang.isEmpty() ) + lang = "C"; + } + return lang; +} + + + +#ifndef QT_NO_CODECS + +class QSimpleTextCodec: public QTextCodec +{ +public: + QSimpleTextCodec( int ); + ~QSimpleTextCodec(); + + QString toUnicode(const char* chars, int len) const; + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + const char* name() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; + + int heuristicNameMatch(const char* hint) const; + +private: + int forwardIndex; +}; + + +#define LAST_MIB 2259 + +static struct { + const char * cs; + int mib; + Q_UINT16 values[128]; +} unicodevalues[] = { + // from RFC 1489, ftp://ftp.isi.edu/in-notes/rfc1489.txt + { "KOI8-R", 2084, + { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, + 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248, + 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, + 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } }, + // /**/ - The BULLET OPERATOR is confused. Some people think + // it should be 0x2022 (BULLET). + + // next bits generated from tables on the Unicode 2.0 CD. we can + // use these tables since this is part of the transition to using + // unicode everywhere in qt. + + // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo 0x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; for a in 8859-* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ; cat /tmp/digits ) | sort | uniq -w4 | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done + + // then I inserted the files manually. + { "ISO 8859-1", 4, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, + { "ISO 8859-2", 5, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, + 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, + 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, + { "ISO 8859-3", 6, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7, + 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B, + 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, + 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C, + 0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, + 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, + 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9} }, + { "ISO 8859-4", 7, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, + 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, + 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, + 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, + 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, + 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9} }, + { "ISO 8859-5", 8, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F} }, + { "ISO 8859-6-I", 82, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F, + 0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, + 0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, + 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, + 0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "ISO 8859-7", 10, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, + { "ISO 8859-8-I", 85, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x203E, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "ISO 8859-9", 12, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, + { "ISO 8859-10", 13, + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, + 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, + 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, + 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, + 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, + 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138} }, + { "ISO 8859-13", 0, // ############# what is the mib? + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, + 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019} }, + { "ISO 8859-14", 0, // ############# what is the mib? + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, + 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, + 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, + 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF} }, + { "ISO 8859-15", 0, // ############# what is the mib? + { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, + 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, + 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, + + // next bits generated again from tables on the Unicode 3.0 CD. + + // $ for a in CP* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ) | sort | sed -e 's/#UNDEF.*$/0xFFFD/' | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done + + { "CP 874", 0, //### what is the mib? + { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "CP 1250", 2250, + { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, + { "CP 1251", 2251, + { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F} }, + { "CP 1252", 2252, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, + { "CP 1253", 2253, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, + { "CP 1254", 2254, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, + { "CP 1255", 2255, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0xFFFD, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD} }, + { "CP 1256", 2256, + { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2} }, + { "CP 1257", 2257, + { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0x00A8, 0x02C7, 0x00B8, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0x00AF, 0x02DB, 0xFFFD, + 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0xFFFD, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9} }, + { "CP 1258", 2258, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0xFFFD, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0xFFFD, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF} }, + + // this one is generated from the charmap file located in /usr/share/i18n/charmaps + // on most Linux distributions. The thai character set tis620 is byte by byte equivalent + // to iso8859-11, so we name it 8859-11 here, but recognise the name tis620 too. + + // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; ( cut -c25- < TIS-620 ; cat /tmp/digits ) | awk '/^x[89ABCDEF]/{ print $1, $2 }' | sed -e 's/<U/0x/' -e 's/>//' | sort | uniq -w4 | cut -c5- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/tis-620 + { "ISO 8859-11", 2259, // Thai character set mib enum taken from tis620 (which is byte by byte equivalent) + { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + +}; + + +static const QSimpleTextCodec * reverseOwner = 0; +static QArray<char> * reverseMap = 0; + + +QSimpleTextCodec::QSimpleTextCodec( int i ) + : QTextCodec(), forwardIndex( i ) +{ +} + + +QSimpleTextCodec::~QSimpleTextCodec() +{ + if ( reverseOwner == this ) { + delete reverseMap; + reverseMap = 0; + reverseOwner = 0; + } +} + +// what happens if strlen(chars)<len? what happens if !chars? if len<1? +QString QSimpleTextCodec::toUnicode(const char* chars, int len) const +{ + QString r; + const unsigned char * c = (const unsigned char *)chars; + for( int i=0; i<len && c[i]; i++ ) { // Note: NUL ends string + if ( c[i] > 127 ) + r[i] = unicodevalues[forwardIndex].values[c[i]-128]; + else + r[i] = c[i]; + } + return r; +} + + +QCString QSimpleTextCodec::fromUnicode(const QString& uc, int& len ) const +{ + if ( reverseOwner != this ) { + int m = 0; + int i = 0; + while( i < 128 ) { + if ( unicodevalues[forwardIndex].values[i] > m && + unicodevalues[forwardIndex].values[i] < 0xfffd ) + m = unicodevalues[forwardIndex].values[i]; + i++; + } + m++; + if ( !reverseMap ) + reverseMap = new QArray<char>( m ); + if ( m > (int)(reverseMap->size()) ) + reverseMap->resize( m ); + for( i = 0; i < 128 && i < m; i++ ) + (*reverseMap)[i] = (char)i; + for( ;i < m; i++ ) + (*reverseMap)[i] = '?'; + for( i=128; i<256; i++ ) { + int u = unicodevalues[forwardIndex].values[i-128]; + if ( u < m ) + (*reverseMap)[u] = (char)(unsigned char)(i); + } + reverseOwner = this; + } + if ( len <0 || len > (int)uc.length() ) + len = uc.length(); + QCString r( len+1 ); + int i; + int u; + for( i=0; i<len; i++ ) { + u = uc[i].cell() + 256* uc[i].row(); + r[i] = u < 128 ? u : ( + ( u < (int)reverseMap->size() ) ? (*reverseMap)[u] : '?' ); + } + r[len] = 0; + return r; +} + + +const char* QSimpleTextCodec::name() const +{ + return unicodevalues[forwardIndex].cs; +} + + +int QSimpleTextCodec::mibEnum() const +{ + return unicodevalues[forwardIndex].mib; +} + +int QSimpleTextCodec::heuristicNameMatch(const char* hint) const +{ + if ( hint[0]=='k' ) { + // Help people with messy fonts + if ( QCString(hint) == "koi8-1" ) + return QTextCodec::heuristicNameMatch("koi8-r")-1; + if ( QCString(hint) == "koi8-ru" ) + return QTextCodec::heuristicNameMatch("koi8-r")-1; + } else if ( hint[0] == 't' && QCString(name()) == "ISO 8859-11" ) { + // 8859-11 and tis620 are byte by bute equivalent + int i = simpleHeuristicNameMatch("tis-620", hint); + if( i ) return i; + } + return QTextCodec::heuristicNameMatch(hint); +} + +int QSimpleTextCodec::heuristicContentMatch(const char* chars, int len) const +{ + if ( len<1 || !chars ) + return -1; + int i = 0; + const uchar * c = (const unsigned char *)chars; + int r = 0; + while( i<len && c && *c ) { + if ( *c >= 128 ) { + if ( unicodevalues[forwardIndex].values[(*c)-128] == 0xfffd ) + return -1; + } + if ( (*c >= ' ' && *c < 127) || + *c == '\n' || *c == '\t' || *c == '\r' ) + r++; + i++; + c++; + } + if ( mibEnum()==4 ) + r+=1; + return r; +} + + +static void setupBuiltinCodecs() +{ + int i = 0; + do { + (void)new QSimpleTextCodec( i ); + } while( unicodevalues[i++].mib != LAST_MIB ); + + (void)new QEucJpCodec; + (void)new QSjisCodec; + (void)new QJisCodec; + (void)new QEucKrCodec; + (void)new QGbkCodec; + (void)new QBig5Codec; + (void)new QUtf8Codec; + (void)new QUtf16Codec; + (void)new QHebrewCodec; + (void)new QArabicCodec; + (void)new QTsciiCodec; +} + +#else + +class QLatin1Codec: public QTextCodec +{ +public: + QLatin1Codec(); + ~QLatin1Codec(); + + QString toUnicode(const char* chars, int len) const; + QCString fromUnicode(const QString& uc, int& lenInOut ) const; + + const char* name() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; + + int heuristicNameMatch(const char* hint) const; + +private: + int forwardIndex; +}; + + +QLatin1Codec::QLatin1Codec() + : QTextCodec() +{ +} + + +QLatin1Codec::~QLatin1Codec() +{ +} + +// what happens if strlen(chars)<len? what happens if !chars? if len<1? +QString QLatin1Codec::toUnicode(const char* chars, int len) const +{ + QString r; + const unsigned char * c = (const unsigned char *)chars; + for( int i=0; i<len && c[i]; i++ ) { // Note: NUL ends string + r[i] = c[i]; + } + return r; +} + + +QCString QLatin1Codec::fromUnicode(const QString& uc, int& len ) const +{ + if ( len <0 || len > (int)uc.length() ) + len = uc.length(); + QCString r( len+1 ); + int i; + int u; + for( i=0; i<len; i++ ) { + u = uc[i].cell() + 256* uc[i].row(); + r[i] = u < 255 ? u : '?'; + } + r[len] = 0; + return r; +} + + +const char* QLatin1Codec::name() const +{ + return "iso8859-1"; +} + + +int QLatin1Codec::mibEnum() const +{ + return 4; +} + +int QLatin1Codec::heuristicNameMatch(const char* hint) const +{ + return QTextCodec::heuristicNameMatch(hint); +} + +int QLatin1Codec::heuristicContentMatch(const char* chars, int len) const +{ + if ( len<1 || !chars ) + return -1; + int i = 0; + const uchar * c = (const unsigned char *)chars; + int r = 0; + while( i<len && c && *c ) { + if ( *c >= 0x80 && *c < 0xa0 ) + return -1; + if ( (*c >= ' ' && *c < 127) || + *c == '\n' || *c == '\t' || *c == '\r' ) + r++; + i++; + c++; + } + return r; +} + + + +static void setupBuiltinCodecs() +{ + (void)new QLatin1Codec; +} +#endif // QT_NO_CODECS + +#endif // QT_NO_TEXTCODEC diff --git a/qtools/qtextcodec.h b/qtools/qtextcodec.h new file mode 100644 index 0000000..18ece20 --- /dev/null +++ b/qtools/qtextcodec.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** +** 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 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 + 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 deleteAllCodecs(); + + static const char* locale(); + + virtual const char* name() const = 0; + 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 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; + +protected: + QTextCodec(); + static int simpleHeuristicNameMatch(const char* name, const char* hint); +}; +#endif // QT_NO_TEXTCODEC +#endif // QTEXTCODEC_H diff --git a/qtools/qtextstream.cpp b/qtools/qtextstream.cpp new file mode 100644 index 0000000..774b730 --- /dev/null +++ b/qtools/qtextstream.cpp @@ -0,0 +1,2145 @@ +/**************************************************************************** +** +** +** Implementation 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. +** +**********************************************************************/ + +#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(_OS_WIN32_) +#include <windows.h> +#endif + +// NOT REVISED +/*! + \class QTextStream qtextstream.h + + \brief The QTextStream class provides basic functions for reading and + writing text using a QIODevice. + + \ingroup io + + \define endl + \define bin + \define oct + \define dec + \define hex + \define flush + \define ws + + The text stream class has a functional interface that is very + similar to that of the standard C++ iostream class. The difference + between iostream and QTextStream is that our stream operates on a + QIODevice, which is easily subclassed, while iostream operates on + FILE * pointers, which can not be subclassed. + + Qt provides several global functions similar to the ones in iostream: + <ul> + <li> \c bin sets the QTextStream to read/write binary numbers + <li> \c oct sets the QTextStream to read/write octal numbers + <li> \c dec sets the QTextStream to read/write decimal numbers + <li> \c hex sets the QTextStream to read/write hexadecimal numbers + <li> \c endl forces a line break + <li> \c flush forces the QIODevice to flush any buffered data + <li> \c ws eats any available white space (on input) + <li> \c reset resets the QTextStream to its default mode (see reset()). + </ul> + + \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, ie. the sequence "0100" will be interpreted as + 64. + + The QTextStream class reads and writes text and it is not + appropriate for dealing with binary data (but QDataStream is). + + By default output of Unicode text (ie. 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, but otherwise the local + 8-bit encoding is used. + + \sa QDataStream +*/ + +/* + \class QTSManip qtextstream.h + + \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(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. + +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: + QTextStreamPrivate(): decoder( 0 ), sourceType( NotSet ) {} + ~QTextStreamPrivate() { delete decoder; } + + QTextDecoder *decoder; //??? + 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; // no device set + fstrm = owndev = FALSE; + mapper = 0; + d = new QTextStreamPrivate; + doUnicodeHeader = TRUE; //default to autodetect + latin1 = TRUE; // ### should use local? + internalOrder = QChar::networkOrdered(); //default to network order +} + +/*! + 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; // set device + 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(); + uint size() const; + int at() const; + bool at( int pos ); + int readBlock( char *p, uint len ); + int writeBlock( const char *p, uint 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(CHECK_STATE) + qWarning( "QStringBuffer::open: No string" ); +#endif + return FALSE; + } + if ( isOpen() ) { // buffer already open +#if defined(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() +{ +} + +uint QStringBuffer::size() const +{ + return s ? s->length()*sizeof(QChar) : 0; +} + +int QStringBuffer::at() const +{ + return ioIndex; +} + +bool QStringBuffer::at( int pos ) +{ +#if defined(CHECK_STATE) + if ( !isOpen() ) { + qWarning( "QStringBuffer::at: Buffer is not open" ); + return FALSE; + } +#endif + if ( (uint)pos >= s->length()*2 ) { +#if defined(CHECK_RANGE) + qWarning( "QStringBuffer::at: Index %d out of range", pos ); +#endif + return FALSE; + } + ioIndex = pos; + return TRUE; +} + + +int QStringBuffer::readBlock( char *p, uint len ) +{ +#if defined(CHECK_STATE) + 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 ( (uint)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; +} + +int QStringBuffer::writeBlock( const char *p, uint len ) +{ +#if defined(CHECK_NULL) + if ( p == 0 && len != 0 ) + qWarning( "QStringBuffer::writeBlock: Null pointer error" ); +#endif +#if defined(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(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 *((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(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 a Unicode QString through an + internal device. + + 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 since 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 a byte array through an + internal QBuffer device. + + 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 \e fh + through an internal QFile device. + + Example: + \code + QTextStream cout( stdout, IO_WriteOnly ); + QTextStream cin ( stdin, IO_ReadOnly ); + QTextStream cerr( stderr, IO_WriteOnly ); + \endcode +*/ + +QTextStream::QTextStream( FILE *fh, int mode ) +{ + init(); + setEncoding( Locale ); //### + dev = new QFile; + ((QFile *)dev)->open( mode, fh ); + fstrm = owndev = TRUE; + reset(); + d->sourceType = QTextStreamPrivate::File; +} + +/*! + Destructs 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() ); +} + + +/*! + \fn Encoding QTextStream::encoding() const + + Returns the encoding mode of the stream. + + \sa setEncoding() +*/ + +/*! + Tries to read len characters from the stream and stores them in \a buf. + Returns the number of characters really read. + Attention: 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[rnum] = d->ungetcBuf.constref(rnum); + 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(); //network order + } else if ( c1 == 0xff && c2 == 0xfe ) { + mapper = 0; + latin1 = FALSE; + internalOrder = !QChar::networkOrdered(); //reverse network order + } else { + if ( c2 != EOF ) { + dev->ungetch( c2 ); + ungetHack = c1; + } else { + dev->ungetch( c1 ); + // note that a small possible bug might hide here + // 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. whether or not this is a bug depends on + // taste. I can't really decide. + } + } + } + + if ( mapper ) { + if ( !d->decoder ) + d->decoder = mapper->makeDecoder(); + while( rnum < len ) { + QString s; + while ( s.isEmpty() ) { + // TODO: can this getch() call be optimized to read + // more than one character after another? YES! + int c; + if ( ungetHack == EOF ) { + c = dev->getch(); + } else { + c = ungetHack; + ungetHack = EOF; + } + if ( c == EOF ) + return rnum; + char b = c; + s = d->decoder->toUnicode( &b, 1 ); + } + uint i = 0; + while( rnum < len && i < s.length() ) + buf[rnum++] = s.constref(i++); + if ( s.length() > i ) + // could be = but append is clearer + d->ungetcBuf.append( s.mid( i ) ); + } + } else 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[rnum++] = (char)c; + } else { + if ( (QChar)ungetHack != QEOF ) + buf[rnum++] = (char)ungetHack; + uint rlen = len - rnum; + char *cbuf = new char[rlen]; + rlen = dev->readBlock( cbuf, rlen ); + uint i = 0; + while( i < rlen ) + buf[rnum++] = cbuf[i++]; + 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 ( isNetworkOrder() ) + buf[rnum++] = QChar( c2, c1 ); + else + buf[rnum++] = QChar( c1, c2 ); + } else { + uint rlen = 2 * ( len-rnum ); + char *cbuf = new char[rlen]; // for paranoids: overflow possible + if ( (QChar)ungetHack != QEOF ) { + rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); + cbuf[0] = (char)ungetHack; + } else { + rlen = dev->readBlock( cbuf, rlen ); + } + // is this right? we can't use an odd number of bytes, but + // if there -is- an odd number, with this code we'll never + // get to EOF. + if ( (rlen & 1) == 1 ) + dev->ungetch( cbuf[--rlen] ); + uint i = 0; + if ( isNetworkOrder() ) { + while( i < rlen ) { + buf[rnum++] = QChar( cbuf[i+1], cbuf[i] ); + i+=2; + } + } else { + while( i < rlen ) { + buf[rnum++] = QChar( cbuf[i], cbuf[i+1] ); + i+=2; + } + } + delete[] cbuf; + } + } + return rnum; +} + + +/*! + Puts one character to the stream. +*/ +void QTextStream::ts_putc( QChar c ) +{ + if ( mapper ) { + int len = 1; + QString s = c; + QCString block = mapper->fromUnicode( s, len ); + dev->writeBlock( block, len ); + } else 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 ) { + dev->writeBlock( (char*)&c, sizeof(QChar) ); + } else if ( isNetworkOrder() ) { + dev->putch(c.row()); + dev->putch(c.cell()); + } else { + dev->putch(c.cell()); + dev->putch(c.row()); + } + } +} + +/*! + Puts one character to 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 \e len bytes from the stream into \e e s and returns a reference to + the stream. + + The buffer \e s must be preallocated. + + \note No Encoding is done by this function. + + \warning The behaviour 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 \e len bytes from \e s to the stream and returns a reference to + the stream. + + \note 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 ); + } + //All QCStrings and const char* are defined to be in Latin1 + 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 ) +{ + if ( !mapper && !latin1 && 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. + + <ul> + <li> All flags are set to 0. + <li> The field width is set to 0. + <li> The fill character is set to ' ' (space). + <li> The precision is set to 6. + </ul> + + \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 + 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 bool QTextStream::eof() const + + \obsolete + + This function has been renamed to atEnd(). + + \sa QIODevice::atEnd() +*/ + +/***************************************************************************** + QTextStream read functions + *****************************************************************************/ + + +/*! + Reads a \c char 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 \c char 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(c) ) { + val <<= 4; + if ( ts_isdigit(c) ) + val += c - '0'; + else + val += 10 + tolower(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(c) == 'x' ) + val = (long)input_hex(); + else if ( tolower(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 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(); + + while ( TRUE ) { + + 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(_CC_EGG_) + return 0.0; +#endif +} + + +/*! + Reads a signed \c short integer from the stream and returns a reference to + the stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( signed short &i ) +{ + CHECK_STREAM_PRECOND + i = (signed short)input_int(); + return *this; +} + + +/*! + Reads an unsigned \c short integer from the stream and returns a reference to + the stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned short &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned short)input_int(); + return *this; +} + + +/*! + Reads a signed \c int from the stream and returns a reference to the + stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( signed int &i ) +{ + CHECK_STREAM_PRECOND + i = (signed int)input_int(); + return *this; +} + + +/*! + Reads an unsigned \c int from the stream and returns a reference to the + stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned int &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned int)input_int(); + return *this; +} + + +/*! + Reads a signed \c long int from the stream and returns a reference to the + stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( signed long &i ) +{ + CHECK_STREAM_PRECOND + i = (signed long)input_int(); + return *this; +} + + +/*! + Reads an unsigned \c long int from the stream and returns a reference to the + stream. See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( unsigned long &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned long)input_int(); + return *this; +} + + +/*! + Reads a \c float from the stream and returns a reference to the stream. + See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( float &f ) +{ + CHECK_STREAM_PRECOND + f = (float)input_double(); + return *this; +} + + +/*! + Reads a \c double from the stream and returns a reference to the stream. + See flags() for an explanation of expected input format. +*/ + +QTextStream &QTextStream::operator>>( double &f ) +{ + CHECK_STREAM_PRECOND + f = input_double(); + return *this; +} + + +/*! + Reads a word from the stream and returns a reference to the stream. +*/ + +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; +} + +/*! + Reads a word from the stream and returns a reference to the stream. +*/ + +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; +} + +/*! + Reads a word from the stream and returns a reference to the stream. +*/ + +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(CHECK_STATE) + if ( !dev ) { + qWarning( "QTextStream::readLine: No device" ); + return QString::null; + } +#endif + QChar c = ts_getc(); + if ( c == QEOF ) + return QString::null; + + QString result( "" ); + while ( c != QEOF && c != '\n' ) { + result += c; + c = ts_getc(); + } + + int len = (int)result.length(); + if ( len && result[len-1] == '\r' ) + result.truncate(len-1); // (if there are two \r, let one stay) + + return result; +} + + +/*! + Reads the entire stream and returns a string containing the text. + + \sa QIODevice::readLine() +*/ + +QString QTextStream::read() +{ +#if defined(CHECK_STATE) + if ( !dev ) { + qWarning( "QTextStream::readLine: No device" ); + return QString::null; + } +#endif + QString result; + const uint bufsize = 512; + QChar buf[bufsize]; + uint i, num, start; + bool skipped_cr = FALSE; + + while ( 1 ) { + num = ts_getbuf(buf,bufsize); + // do a s/\r\n/\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 += '\r'; + } + skipped_cr = FALSE; + } + } + } + if ( start < num ) + result += QString( &buf[start], i-start ); + if ( num != bufsize ) // if ( EOF ) + break; + } + return result; +} + + + +/***************************************************************************** + QTextStream write functions + *****************************************************************************/ + +/*! + Writes a \c char 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 char hexdigits_lower[] = "0123456789abcdef"; + static char hexdigits_upper[] = "0123456789ABCDEF"; + CHECK_STREAM_PRECOND + char buf[76]; + register char *p; + int len; + 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; +} + + +/*! + Writes a \c short integer 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 ); +} + + +/*! + Writes an \c unsigned \c short integer 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 ); +} + + +/*! + Writes an \c int 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 ); +} + + +/*! + Writes an \c unsigned \c int 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 ); +} + + +/*! + Writes a \c long \c int 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 ); +} + + +/*! + Writes an \c unsigned \c long \c int 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 ); +} + + +/*! + Writes a \c float to the stream and returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( float f ) +{ + return *this << (double)f; +} + + +/*! + Writes a \c double 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; +} + + +/*! + Writes a string to the stream and returns a reference to the stream. +*/ + +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]; + 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; +} + +/*! + Writes \a s to the stream and returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( const QCString & s ) +{ + return operator<<(s.data()); +} + +/*! + Writes \a s to the stream and returns a reference to the stream. +*/ + +QTextStream &QTextStream::operator<<( const QString& s ) +{ + CHECK_STREAM_PRECOND + uint len = s.length(); + 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(), len ); + return *this; +} + + +/*! + Writes a pointer to the stream and returns a reference to the stream. + + The \e 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. + + The meaning of the flags are: + <ul> + <li> \e skipws - Not currently used - whitespace always skipped + <li> \e left - Numeric fields are left-aligned + <li> \e right - Not currently used (by default numerics are right aligned) + <li> \e internal - Put any padding spaces between +/- and value + <li> \e bin - Output \e and input only in binary + <li> \e oct - Output \e and input only in octal + <li> \e dec - Output \e and input only in decimal + <li> \e hex - Output \e and input only in hexadecimal + <li> \e showbase - Annotate numeric outputs with 0b, 0, or 0x if in + \e bin, \e oct, or \e hex format + <li> \e showpoint - Not currently used + <li> \e uppercase - Use 0B and 0X rather than 0b and 0x + <li> \e showpos - Show + for positive numeric values + <li> \e scientific - Use scientific notation for floating point values + <li> \e fixed - Use fixed-point notation for floating point values + </ul> + + Note that unless \e bin, \e oct, \e dec, or \e hex is set, the input base is + octal if the value starts with 0, hexadecimal if it starts with 0x, binary + if the value starts with 0b, and decimal otherwise. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::flags( int f ) + Sets the stream flags to \e f. + Returns the previous stream flags. + + \sa setf(), unsetf(), flags() +*/ + +/*! + \fn int QTextStream::setf( int bits ) + Sets the stream flag bits \e bits. + Returns the previous stream flags. + + Equivalent to <code>flags( flags() | bits )</code>. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::setf( int bits, int mask ) + Sets the stream flag bits \e bits with a bit mask \e mask. + Returns the previous stream flags. + + Equivalent to <code>flags( (flags() & ~mask) | (bits & mask) )</code>. + + \sa setf(), unsetf() +*/ + +/*! + \fn int QTextStream::unsetf( int bits ) + Clears the stream flag bits \e bits. + Returns the previous stream flags. + + Equivalent to <code>flags( flags() & ~mask )</code>. + + \sa setf() +*/ + +/*! + \fn int QTextStream::width() const + Returns the field width. The default value is 0. +*/ + +/*! + \fn int QTextStream::width( int w ) + Sets the field width to \e w. Returns the previous field width. +*/ + +/*! + \fn int QTextStream::fill() const + Returns the fill character. The default value is ' ' (space). +*/ + +/*! + \fn int QTextStream::fill( int f ) + Sets the fill character to \e 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 ) + Sets the precision to \e 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 + \brief A convenience class for input streams. + + For simple tasks, code should be simple. Hence this + class is a shorthand to avoid passing the \e mode argument + to the normal QTextStream constructors. + + This 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( QString *s ) + + Constructs a stream to read from 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 qtextstream.h + \brief A convenience class for output streams. + + For simple tasks, code should be simple. Hence this + class is a shorthand to avoid passing the \e mode argument + to the normal QTextStream constructors. + + 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: + <ul> + <li> \c Locale Using local file format (Latin1 if locale is not + set), but autodetecting Unicode(utf16) on input. + <li> \c Unicode Using 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). + <li> \c UnicodeUTF8 Using Unicode(utf8) for input and output. If you use it + for input it will autodetect utf16 and use it instead of utf8. + <li> \c Latin1 ISO-8859-1. Will not autodetect utf16. + <li> \c UnicodeNetworkOrder Using network order Unicode(utf16) for + input and output. Useful when reading Unicode data that does not + start with the byte order marker. + <li> \c UnicodeReverse Using reverse network order Unicode(utf16) + for input and output. Useful when reading Unicode data that does not + start with the byte order marker, or writing data that should be + read by buggy Windows applications. + <li> \c RawUnicode Like Unicode, but does not write the byte order + marker, nor does it autodetect the byte order. Only useful when + writing to non-persistent storage used by a single process. + </ul> + + \c Locale and all Unicode encodings, except \c RawUnicode, will look + at the first two bytes in a input stream to determine the byte + order. The initial byte order marker will be stripped off before data is read. + + \note This function should be called before any data is read to/written from the stream. + \sa setCodec() +*/ + +void QTextStream::setEncoding( Encoding e ) +{ + if ( d->sourceType == QTextStreamPrivate::String ) + return; // QString does not need any encoding + switch ( e ) { + case Unicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + break; + case UnicodeUTF8: + mapper = QTextCodec::codecForMib( 106 ); + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + break; + case UnicodeNetworkOrder: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = QChar::networkOrdered(); + break; + case UnicodeReverse: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = !QChar::networkOrdered(); //reverse network ordered + break; + case RawUnicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = FALSE; + internalOrder = TRUE; + break; + case Locale: + latin1 = TRUE; // fallback to Latin 1 + mapper = QTextCodec::codecForLocale(); +#if defined(_OS_WIN32_) + if ( GetACP() == 1252 ) + mapper = 0; // Optimized latin1 processing +#endif + if ( mapper && mapper->mibEnum() == 4 ) + mapper = 0; // Optimized latin1 processing + doUnicodeHeader = TRUE; // If it reads as Unicode, accept it + break; + case Latin1: + mapper = 0; + doUnicodeHeader = FALSE; + latin1 = TRUE; + break; + } +} + + +/*! + Sets the codec for this stream to \a codec. Will not try to autodetect Unicode. + + \note This function should be called before any data is read to/written from the stream. + \sa setEncoding() +*/ + +void QTextStream::setCodec( QTextCodec *codec ) +{ + if ( d->sourceType == QTextStreamPrivate::String ) + return; // QString does not need any codec + mapper = codec; + doUnicodeHeader = FALSE; +} + +#endif // QT_NO_TEXTSTREAM diff --git a/qtools/qtextstream.h b/qtools/qtextstream.h new file mode 100644 index 0000000..d7adbd3 --- /dev/null +++ b/qtools/qtextstream.h @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** +** 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 ); + void setCodec( QTextCodec* ); + // Encoding encoding() const { return cmode; } + + 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<<( 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; + bool isNetworkOrder() { return internalOrder == QChar::networkOrdered(); } + + int fflags; + int fwidth; + int fillchar; + int fprec; + bool fstrm; + bool owndev; + QTextCodec *mapper; + QTextStreamPrivate * d; + QChar ungetcBuf; + bool latin1; + bool internalOrder; + bool doUnicodeHeader; + void *reserved_ptr; + + QChar eat_ws(); + 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( QString* s ) : + QTextStream(s,IO_ReadOnly) { } + QTextIStream( QByteArray ba ) : + QTextStream(ba,IO_ReadOnly) { } + QTextIStream( FILE *f ) : + QTextStream(f,IO_ReadOnly) { } +}; + +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) { } +}; + +/***************************************************************************** + 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); +} + + +#ifndef QT_ALTERNATE_QTSMANIP + +// These will go away in Qt 3.0, as they conflict with std libs +// +// If you get conflicts now, #define QT_ALTERNATE_QTSMANIP before +// including this file. + +Q_EXPORT inline QTSManip setw( int w ) +{ + QTSMFI func = &QTextStream::width; + return QTSManip(func,w); +} + +Q_EXPORT inline QTSManip setfill( int f ) +{ + QTSMFI func = &QTextStream::fill; + return QTSManip(func,f); +} + +Q_EXPORT inline QTSManip setprecision( int p ) +{ + QTSMFI func = &QTextStream::precision; + return QTSManip(func,p); +} +#endif + +#endif // QT_NO_TEXTSTREAM +#endif // QTEXTSTREAM_H diff --git a/qtools/qtl.h b/qtools/qtl.h new file mode 100644 index 0000000..bd72e7d --- /dev/null +++ b/qtools/qtl.h @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** +** 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 "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 T> +inline void qSwap( T& _value1, T& _value2 ) +{ + T tmp = _value1; + _value1 = _value2; + _value2 = tmp; +} + + +template <class InputIterator> +inline 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> +inline void qHeapSortPushDown( Value* 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 ( heap[r] > heap[ 2*r ] ) + qSwap( heap[r], heap[ 2*r ] ); + // That's it ... + r = last; + } else { // Node has two children + if ( heap[r] > heap[ 2*r ] && heap[ 2*r ] <= heap[ 2*r+1 ] ) { + // Swap with left child + qSwap( heap[r], heap[ 2*r ] ); + r *= 2; + } else if ( heap[r] > heap[ 2*r+1 ] && + heap[ 2*r+1 ] < heap[ 2*r ] ) { + // Swap with right child + qSwap( heap[r], heap[ 2*r+1 ] ); + r = 2*r+1; + } else { + // We are done + r = last; + } + } + } +} + + +template <class InputIterator, class Value> +inline 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> +inline 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> +inline void qHeapSort( Container &c ) +{ + if ( c.isEmpty() ) + 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()), c.count() ); +} + +#endif diff --git a/qtools/qtools.pro.in b/qtools/qtools.pro.in new file mode 100644 index 0000000..17c6626 --- /dev/null +++ b/qtools/qtools.pro.in @@ -0,0 +1,71 @@ +TEMPLATE = lib +CONFIG = warn_on staticlib $extraopts +HEADERS = qarray.h \ + qbuffer.h \ + qcollection.h \ + qconfig.h \ + qcstring.h \ + qdatastream.h \ + qdatetime.h \ + qdict.h \ + qdir.h \ + qfeatures.h \ + qfile.h \ + qfiledefs_p.h \ + qfileinfo.h \ + qgarray.h \ + qfeatures.h \ + qgdict.h \ + qgeneric.h \ + qglist.h \ + qglobal.h \ + qgvector.h \ + qintdict.h \ + qiodevice.h \ + qlist.h \ + qptrdict.h \ + qqueue.h \ + qregexp.h \ + qshared.h \ + qsortedlist.h \ + qstack.h \ + qstring.h \ + qstringlist.h \ + qstrlist.h \ + qstrvec.h \ + qtextstream.h \ + qtl.h \ + qvaluelist.h \ + qvector.h +SOURCES = qbuffer.cpp \ + qcollection.cpp \ + qcstring.cpp \ + qdatastream.cpp \ + qdatetime.cpp \ + qdir.cpp \ + qfile.cpp \ + qfileinfo.cpp \ + qgarray.cpp \ + qgdict.cpp \ + qglist.cpp \ + qglobal.cpp \ + qgvector.cpp \ + qiodevice.cpp \ + qregexp.cpp \ + qstring.cpp \ + qtextstream.cpp \ + qtextcodec.cpp \ + qstringlist.cpp + +unix:SOURCES += qfile_unix.cpp \ + qdir_unix.cpp \ + qfileinfo_unix.cpp + +win32:SOURCES += qfile_win32.cpp \ + qdir_win32.cpp \ + qfileinfo_win32.cpp + +INCLUDEPATH = . +TMAKE_CXXFLAGS = -DQT_NO_CODECS -DQT_LITE_UNICODE +win32:TMAKE_CXXFLAGS += -DQT_NODLL +OBJECTS_DIR = ../objects diff --git a/qtools/qvaluelist.h b/qtools/qvaluelist.h new file mode 100644 index 0000000..a1014ed --- /dev/null +++ b/qtools/qvaluelist.h @@ -0,0 +1,449 @@ +/**************************************************************************** +** +** +** 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 "qshared.h" +#include "qdatastream.h" +#endif // QT_H + +#if defined(_CC_MSVC_) +#pragma warning(disable:4284) // "return type for operator -> is not a UDT" +#endif + +template <class T> +class Q_EXPORT 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 Q_EXPORT QValueListIterator +{ + public: + /** + * Typedefs + */ + typedef QValueListNode<T>* NodePtr; + + /** + * 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; } + + // Compilers are too dumb to understand this for QValueList<int> + //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; + } +}; + +template<class T> +class Q_EXPORT QValueListConstIterator +{ + public: + /** + * Typedefs + */ + typedef QValueListNode<T>* NodePtr; + + /** + * 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; } + + // Compilers are too dumb to understand this for QValueList<int> + //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 Q_EXPORT QValueListPrivate : public QShared +{ +public: + /** + * Typedefs + */ + typedef QValueListIterator<T> Iterator; + typedef QValueListConstIterator<T> ConstIterator; + typedef QValueListNode<T> Node; + typedef QValueListNode<T>* NodePtr; + + /** + * Functions + */ + QValueListPrivate() { node = new Node; node->next = node->prev = node; nodes = 0; } + 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++ ); + } + + 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() { + NodePtr p = node->next; + while( p != node ) { + NodePtr x = p->next; + delete p; + p = x; + } + delete node; + } + + Iterator insert( 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; + } + + Iterator remove( Iterator it ) { + 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 ); + } + + NodePtr find( 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; + } + + int findIndex( 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; + } + + uint 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; + } + + void remove( const T& x ) { + Iterator first = Iterator( node->next ); + Iterator last = Iterator( node ); + while( first != last) { + if ( *first == x ) + first = remove( first ); + else + ++first; + } + } + + NodePtr at( uint i ) const { + ASSERT( i <= nodes ); + NodePtr p = node->next; + for( uint x = 0; x < i; ++x ) + p = p->next; + return p; + } + + void clear() { + nodes = 0; + NodePtr p = node->next; + while( p != node ) { + NodePtr next = p->next; + delete p; + p = next; + } + node->next = node->prev = node; + } + + NodePtr node; + uint nodes; +}; + +template <class T> +class Q_EXPORT QValueList +{ +public: + /** + * Typedefs + */ + typedef QValueListIterator<T> Iterator; + typedef QValueListConstIterator<T> ConstIterator; + typedef T ValueType; + + /** + * API + */ + QValueList() { sh = new QValueListPrivate<T>; } + QValueList( const QValueList<T>& l ) { sh = l.sh; sh->ref(); } + ~QValueList() { sh->derefAndDelete(); } + + QValueList<T>& operator= ( const QValueList<T>& l ) + { + l.sh->ref(); + sh->derefAndDelete(); + sh = l.sh; + return *this; + } + + QValueList<T> operator+ ( const QValueList<T>& l ) const + { + QValueList<T> l2( *this ); + for( ConstIterator it = l.begin(); it != l.end(); ++it ) + l2.append( *it ); + return l2; + } + + QValueList<T>& operator+= ( const QValueList<T>& l ) + { + for( ConstIterator it = l.begin(); it != l.end(); ++it ) + append( *it ); + return *this; + } + + bool operator== ( const QValueList<T>& l ) const + { + if ( count() != l.count() ) + return FALSE; + ConstIterator it2 = begin(); + ConstIterator it = l.begin(); + for( ; it != l.end(); ++it, ++it2 ) + if ( !( *it == *it2 ) ) + return FALSE; + return TRUE; + } + + bool operator!= ( const QValueList<T>& l ) const { return !( *this == l ); } + + Iterator begin() { detach(); return Iterator( sh->node->next ); } + ConstIterator begin() const { return ConstIterator( sh->node->next ); } + Iterator end() { detach(); return Iterator( sh->node ); } + ConstIterator end() const { return ConstIterator( sh->node ); } + Iterator fromLast() { detach(); return Iterator( sh->node->prev ); } + ConstIterator fromLast() const { return ConstIterator( sh->node->prev ); } + + bool isEmpty() const { return ( sh->nodes == 0 ); } + + Iterator insert( Iterator it, const T& x ) { detach(); return sh->insert( it, x ); } + + 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 ); } + void remove( const T& x ) { detach(); sh->remove( x ); } + + T& first() { detach(); return sh->node->next->data; } + const T& first() const { return sh->node->next->data; } + T& last() { detach(); return sh->node->prev->data; } + const T& last() const { return sh->node->prev->data; } + + T& operator[] ( uint i ) { detach(); return sh->at(i)->data; } + const T& operator[] ( uint i ) const { return sh->at(i)->data; } + Iterator at( uint i ) { detach(); return Iterator( sh->at(i) ); } + ConstIterator at( uint i ) const { return ConstIterator( sh->at(i) ); } + Iterator find ( const T& x ) { detach(); return Iterator( sh->find( sh->node->next, x) ); } + ConstIterator find ( const T& x ) const { return ConstIterator( sh->find( sh->node->next, x) ); } + Iterator find ( Iterator it, const T& x ) { detach(); return Iterator( sh->find( it.node, x ) ); } + ConstIterator find ( ConstIterator it, const T& x ) const { return ConstIterator( sh->find( it.node, x ) ); } + int findIndex( const T& x ) const { return sh->findIndex( sh->node->next, x) ; } + uint contains( const T& x ) const { return sh->contains( x ); } + + uint count() const { return sh->nodes; } + + void clear() { if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QValueListPrivate<T>; } } + + + QValueList<T>& operator+= ( const T& x ) + { + append( x ); + return *this; + } + QValueList<T>& operator<< ( const T& x ) + { + append( x ); + return *this; + } + + +protected: + /** + * Helpers + */ + void detach() { if ( sh->count > 1 ) { sh->deref(); sh = new QValueListPrivate<T>( *sh ); } } + + /** + * Variables + */ + QValueListPrivate<T>* sh; +}; + +#ifndef QT_NO_DATASTREAM +template<class T> +inline 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 ); + } + return s; +} + +template<class T> +inline QDataStream& operator<<( QDataStream& s, const QValueList<T>& l ) +{ + s << (Q_UINT32)l.count(); + QValueListConstIterator<T> it = l.begin(); + for( ; it != l.end(); ++it ) + s << *it; + return s; +} +#endif // QT_NO_DATASTREAM +#endif // QVALUELIST_H diff --git a/qtools/qvector.h b/qtools/qvector.h new file mode 100644 index 0000000..36f0be7 --- /dev/null +++ b/qtools/qvector.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** +** Definition of QVector template/macro 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 QVECTOR_H +#define QVECTOR_H + +#ifndef QT_H +#include "qgvector.h" +#endif // QT_H + + +template<class type> class QVector : public QGVector +{ +public: + QVector() {} + QVector( uint size ) : QGVector(size) {} + QVector( const QVector<type> &v ) : QGVector(v) {} + ~QVector() { clear(); } + QVector<type> &operator=(const QVector<type> &v) + { return (QVector<type>&)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); } +private: + void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } +}; + + +#endif // QVECTOR_H diff --git a/src/classdef.cpp b/src/classdef.cpp index 6a505ec..9289375 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -50,10 +50,20 @@ ClassDef::ClassDef( : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm)) { //name=n; + + QCString compoundName; + switch(ct) + { + case Class: compoundName="class"; break; + case Struct: compoundName="struct"; break; + case Union: compoundName="union"; break; + case Interface: compoundName="interface"; break; + case Exception: compoundName="exception"; break; + } if (fName) fileName=stripExtension(fName); else - fileName="class_"+nameToFile(nm); + fileName=compoundName+"_"+nameToFile(nm); if (lref) { //url=(QCString)"doxygen=\""+lref+":\" href=\""+fileName; @@ -66,7 +76,7 @@ ClassDef::ClassDef( exampleList = new ExampleList; exampleDict = new ExampleDict(29); } - memListFileName="class_"+nameToFile(nm)+"-members"; + memListFileName=compoundName+"_"+nameToFile(nm)+"-members"; inherits = new BaseClassList; inherits->setAutoDelete(TRUE); inheritedBy = new BaseClassList; @@ -195,6 +205,7 @@ void ClassDef::addMembersToMemberGroup() addMemberListToGroup(&priStaticAttribs); addMemberListToGroup(&friends); addMemberListToGroup(&related); + addMemberListToGroup(&properties); } // adds new member definition to the class @@ -228,6 +239,10 @@ void ClassDef::insertMember(MemberDef *md) dcopMethods.append(md); md->setSectionList(&dcopMethods); break; + case MemberDef::Property: + properties.append(md); + md->setSectionList(&properties); + break; case MemberDef::Slot: // Qt specific switch (md->protection()) { @@ -363,6 +378,12 @@ void ClassDef::insertMember(MemberDef *md) { switch (md->memberType()) { + case MemberDef::Property: + if (Config::sortMembersFlag) + propertyMembers.inSort(md); + else + propertyMembers.append(md); + break; case MemberDef::Signal: // fall through case MemberDef::DCOP: if (Config::sortMembersFlag) @@ -521,6 +542,7 @@ void ClassDef::computeAnchors() setAnchors('t',&proTypes); setAnchors('u',&priTypes); setAnchors('v',&dcopMethods); + setAnchors('w',&properties); } void ClassDef::distributeMemberGroupDocumentation() @@ -789,6 +811,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.startDotGraph(); parseText(ol,theTranslator->trClassDiagram(name())); ol.endDotGraph(inheritanceGraph); + if (Config::generateLegend) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -821,6 +844,7 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.startDotGraph(); parseText(ol,theTranslator->trCollaborationDiagram(name())); ol.endDotGraph(usageImplGraph); + if (Config::generateLegend) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -870,6 +894,7 @@ void ClassDef::writeDocumentation(OutputList &ol) pubSlots.writeDeclarations(ol,this,0,0,0,theTranslator->trPublicSlots(),0); signals.writeDeclarations(ol,this,0,0,0,theTranslator->trSignals(),0); dcopMethods.writeDeclarations(ol,this,0,0,0,theTranslator->trDCOPMethods(),0); + properties.writeDeclarations(ol,this,0,0,0,theTranslator->trProperties(),0); // static public members pubStaticMembers.writeDeclarations(ol,this,0,0,0,theTranslator->trStaticPublicMembers(),0); @@ -1051,6 +1076,16 @@ void ClassDef::writeDocumentation(OutputList &ol) variableMembers.writeDocumentation(ol,name(),this); } + propertyMembers.countDocMembers(); + if (propertyMembers.totalCount()>0) + { + ol.writeRuler(); + ol.startGroupHeader(); + parseText(ol,theTranslator->trPropertyDocumentation()); + ol.endGroupHeader(); + propertyMembers.writeDocumentation(ol,name(),this); + } + ol.startTextBlock(); // write the list of used files (not for man pages) @@ -1355,6 +1390,7 @@ void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup) pubSlots.writePlainDeclarations(ol,this,0,0,0); signals.writePlainDeclarations(ol,this,0,0,0); dcopMethods.writePlainDeclarations(ol,this,0,0,0); + properties.writePlainDeclarations(ol,this,0,0,0); pubStaticMembers.writePlainDeclarations(ol,this,0,0,0); pubStaticAttribs.writePlainDeclarations(ol,this,0,0,0); proTypes.writePlainDeclarations(ol,this,0,0,0); @@ -1808,6 +1844,7 @@ void ClassDef::generateXMLSection(QTextStream &t,MemberList *ml,const char *type void ClassDef::generateXML(QTextStream &t) { + if (name().find('@')!=-1) return; // skip anonymous compounds t << " <compounddef id=\"" << getOutputFileBase() << "\" type=\""; switch(compType) @@ -1893,6 +1930,7 @@ void ClassDef::generateXML(QTextStream &t) generateXMLSection(t,&pubSlots,"public-slot"); generateXMLSection(t,&signals,"signal"); generateXMLSection(t,&dcopMethods,"dcop-func"); + generateXMLSection(t,&properties,"property"); generateXMLSection(t,&pubStaticMembers,"public-static-func"); generateXMLSection(t,&pubStaticAttribs,"public-static-attrib"); generateXMLSection(t,&proTypes,"protected-type"); diff --git a/src/classdef.h b/src/classdef.h index dd4b16f..2bb6a66 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -169,6 +169,7 @@ class ClassDef : public Definition MemberList signals; MemberList friends; MemberList dcopMethods; + MemberList properties; /* member list by types */ MemberList constructors; @@ -178,6 +179,7 @@ class ClassDef : public Definition MemberList functionMembers; MemberList relatedMembers; MemberList variableMembers; + MemberList propertyMembers; /* user defined member groups */ MemberGroupList *memberGroupList; @@ -417,7 +417,8 @@ static bool getLink(const char *className, QCString m=removeRedundantWhiteSpace(memberName); QCString c=className; //printf("Trying `%s'::`%s'\n",c.data(),m.data()); - if (getDefs(c,m,"()",md,cd,fd,nd,gd) && md->isLinkable()) + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) && + md->isLinkable()) { //printf("Found!\n"); if (g_exampleBlock) diff --git a/src/config.h b/src/config.h index 724f02b..a85fc68 100644 --- a/src/config.h +++ b/src/config.h @@ -1,4 +1,4 @@ -/* This file was generated by configgen on Sun Oct 1 13:51:26 2000 +/* This file was generated by configgen on Tue Oct 10 22:16:03 2000 * from config_templ.h * * DO NOT EDIT! @@ -74,6 +74,7 @@ struct Config static bool warningFlag; // generate warnings flag static bool warningUndocFlag; // generate undocumented warnings static QCString warnFormat; // format of the warning messages + static QCString warnLogFile; // log file to write warning to static QStrList inputSources; // list of input files static QStrList filePatternList; // list of file patterns static bool recursiveFlag; // scan directories recursively @@ -133,6 +134,7 @@ struct Config static QCString dotPath; // path to the dot tool static int maxDotGraphWidth; // max dot graph width static int maxDotGraphHeight; // max dot graph height + static bool generateLegend; // generate legend page static bool searchEngineFlag; // generate search engine flag static QCString cgiName; // the name of the CGI binary static QCString cgiURL; // the absolute URL to the CGI binary diff --git a/src/config.l b/src/config.l index 204531f..86b6578 100644 --- a/src/config.l +++ b/src/config.l @@ -1,4 +1,4 @@ -/* This file was generated by configgen on Sun Oct 1 13:51:26 2000 +/* This file was generated by configgen on Tue Oct 10 22:16:03 2000 * from config_templ.l * * DO NOT EDIT! @@ -111,6 +111,7 @@ bool Config::quietFlag = FALSE; bool Config::warningFlag = TRUE; bool Config::warningUndocFlag = TRUE; QCString Config::warnFormat = "$file:$line: $text"; +QCString Config::warnLogFile; QStrList Config::inputSources; QStrList Config::filePatternList; bool Config::recursiveFlag = FALSE; @@ -170,6 +171,7 @@ bool Config::gfxHierarchyFlag = TRUE; QCString Config::dotPath; int Config::maxDotGraphWidth = 1024; int Config::maxDotGraphHeight = 1024; +bool Config::generateLegend = TRUE; bool Config::searchEngineFlag = FALSE; QCString Config::cgiName = "search.cgi"; QCString Config::cgiURL; @@ -370,6 +372,7 @@ static void readIncludeFile(const char *incName) <Start>"WARNINGS"[ \t]*"=" { BEGIN(GetBool); b=&Config::warningFlag; } <Start>"WARN_IF_UNDOCUMENTED"[ \t]*"=" { BEGIN(GetBool); b=&Config::warningUndocFlag; } <Start>"WARN_FORMAT"[ \t]*"=" { BEGIN(GetString); s=&Config::warnFormat; s->resize(0); } +<Start>"WARN_LOGFILE"[ \t]*"=" { BEGIN(GetString); s=&Config::warnLogFile; s->resize(0); } <Start>"INPUT"[ \t]*"=" { BEGIN(GetStrList); l=&Config::inputSources; l->clear(); elemStr=""; } <Start>"INPUT"[ \t]*"+=" { BEGIN(GetStrList); l=&Config::inputSources; elemStr=""; } <Start>"FILE_PATTERNS"[ \t]*"=" { BEGIN(GetStrList); l=&Config::filePatternList; l->clear(); elemStr=""; } @@ -443,6 +446,7 @@ static void readIncludeFile(const char *incName) <Start>"DOT_PATH"[ \t]*"=" { BEGIN(GetString); s=&Config::dotPath; s->resize(0); } <Start>"MAX_DOT_GRAPH_WIDTH"[ \t]*"=" { BEGIN(GetString); s=&maxDotGraphWidthString; s->resize(0); } <Start>"MAX_DOT_GRAPH_HEIGHT"[ \t]*"=" { BEGIN(GetString); s=&maxDotGraphHeightString; s->resize(0); } +<Start>"GENERATE_LEGEND"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateLegend; } <Start>"SEARCHENGINE"[ \t]*"=" { BEGIN(GetBool); b=&Config::searchEngineFlag; } <Start>"CGI_NAME"[ \t]*"=" { BEGIN(GetString); s=&Config::cgiName; s->resize(0); } <Start>"CGI_URL"[ \t]*"=" { BEGIN(GetString); s=&Config::cgiURL; s->resize(0); } @@ -614,6 +618,7 @@ void dumpConfig() printf("warningFlag=`%d'\n",Config::warningFlag); printf("warningUndocFlag=`%d'\n",Config::warningUndocFlag); printf("warnFormat=`%s'\n",Config::warnFormat.data()); + printf("warnLogFile=`%s'\n",Config::warnLogFile.data()); printf("# configuration options related to the input files\n"); { char *is=Config::inputSources.first(); @@ -781,6 +786,7 @@ void dumpConfig() printf("dotPath=`%s'\n",Config::dotPath.data()); printf("maxDotGraphWidth=`%d'\n",Config::maxDotGraphWidth); printf("maxDotGraphHeight=`%d'\n",Config::maxDotGraphHeight); + printf("generateLegend=`%d'\n",Config::generateLegend); printf("# Configuration::addtions related to the search engine \n"); printf("searchEngineFlag=`%d'\n",Config::searchEngineFlag); printf("cgiName=`%s'\n",Config::cgiName.data()); @@ -837,6 +843,7 @@ void Config::init() Config::warningFlag = TRUE; Config::warningUndocFlag = TRUE; Config::warnFormat = "$file:$line: $text"; + Config::warnLogFile.resize(0); Config::inputSources.clear(); Config::filePatternList.clear(); Config::recursiveFlag = FALSE; @@ -896,6 +903,7 @@ void Config::init() Config::dotPath.resize(0); Config::maxDotGraphWidth = 1024; Config::maxDotGraphHeight = 1024; + Config::generateLegend = TRUE; Config::searchEngineFlag = FALSE; Config::cgiName = "search.cgi"; Config::cgiURL.resize(0); @@ -1405,6 +1413,17 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; + t << "# The WARN_LOGFILE tag can be used to specify a file to which warning \n"; + t << "# and error messages should be written. If left blank the output is written \n"; + t << "# to stderr. \n"; + t << "\n"; + } + t << "WARN_LOGFILE = "; + writeStringValue(t,Config::warnLogFile); + t << "\n"; + if (!sl) + { + t << "\n"; } t << "#---------------------------------------------------------------------------\n"; t << "# configuration options related to the input files\n"; @@ -2141,6 +2160,17 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; + t << "# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will \n"; + t << "# generate a legend page explaining the meaning of the various boxes and \n"; + t << "# arrows in the dot generated graphs. \n"; + t << "\n"; + } + t << "GENERATE_LEGEND = "; + writeBoolValue(t,Config::generateLegend); + t << "\n"; + if (!sl) + { + t << "\n"; } t << "#---------------------------------------------------------------------------\n"; t << "# Configuration::addtions related to the search engine \n"; @@ -2420,6 +2450,7 @@ void substituteEnvironmentVars() substEnvVarsInStrList( Config::sectionFilterList ); substEnvVarsInStrList( Config::aliasList ); substEnvVarsInString( Config::warnFormat ); + substEnvVarsInString( Config::warnLogFile ); substEnvVarsInStrList( Config::inputSources ); substEnvVarsInStrList( Config::filePatternList ); substEnvVarsInStrList( Config::excludeSources ); @@ -92,12 +92,12 @@ static QCString sectionRef; static bool insideVerbatim = FALSE; static bool insidePre = FALSE; static int depthIf; -//static int currentListIndentLevel; -static QStack<char> currentListIndent; static QCString curImageName; static QCString curImageCaption; static QCString internalRefFile; static QCString internalRefAnchor; +static QStack<char> currentListIndent; // indent stack of all list items +static bool insideItemList = FALSE; //----------------------------------------------------------------------------- @@ -456,6 +456,32 @@ static void showUntil(OutputList &ol,const char *key) //----------------------------------------------------------------- +static bool inBlock() +{ + return inParamBlock || inRetValBlock || inSeeBlock || inReturnBlock || inAuthorBlock || + inVersionBlock || inSinceBlock || inDateBlock || inWarningBlock || inRemarkBlock || + inAttentionBlock || inBugBlock || inNoteBlock || + inParBlock || inExceptionBlock || inDeprecatedBlock || inPreBlock || + inPostBlock || inInvarBlock; +} + +static void endBlock() +{ + if (inParamBlock || inRetValBlock || inExceptionBlock) + { + outDoc->endDescTableData(); + outDoc->endDescTable(); + } + outDoc->endDescList(); + currentListIndent.pop(); + inParamBlock=inRetValBlock=inSeeBlock=inReturnBlock=inAuthorBlock= + inVersionBlock=inSinceBlock=inDateBlock=inBugBlock=inNoteBlock=inWarningBlock= + inParBlock=inExceptionBlock=inDeprecatedBlock=inPreBlock=inPostBlock= + inInvarBlock=inRemarkBlock=inAttentionBlock=FALSE; +} + +//----------------------------------------------------------------- + struct IndentInfo { public: @@ -477,8 +503,7 @@ struct IndentInfo bool enumerated; }; -static QStack<IndentInfo> listIndentStack; -static bool insideItemList = FALSE; +static QStack<IndentInfo> listIndentStack; // indent stack of - items static void addListItemMarker(const char *marker,int dashPos,bool enumerated) { @@ -504,6 +529,7 @@ static void addListItemMarker(const char *marker,int dashPos,bool enumerated) //printf("list marker found at column %d enumerated %d\n",indent,enumerated); if (!insideItemList) { + currentListIndent.push(enumerated ? "O" : "U"); listIndentStack.push(new IndentInfo(indent,enumerated)); listIndentStack.top()->startList(); listIndentStack.top()->writeItem(); @@ -528,6 +554,7 @@ static void addListItemMarker(const char *marker,int dashPos,bool enumerated) } else if (pPrevInfo->indent<indent) // start sub item list { + currentListIndent.push(enumerated ? "O" : "U"); listIndentStack.push(new IndentInfo(indent,enumerated)); listIndentStack.top()->startList(); listIndentStack.top()->writeItem(); @@ -536,6 +563,7 @@ static void addListItemMarker(const char *marker,int dashPos,bool enumerated) { pPrevInfo->endList(); listIndentStack.pop(); + currentListIndent.pop(); delete pPrevInfo; // safe guard against wrong indenting if (listIndentStack.isEmpty()) @@ -558,35 +586,27 @@ static void forceEndItemList() IndentInfo *info; while ((info=listIndentStack.pop())!=0) { - info->endList(); delete info; } - insideItemList=FALSE; -} - -//----------------------------------------------------------------- - -static bool inBlock() -{ - return inParamBlock || inRetValBlock || inSeeBlock || inReturnBlock || inAuthorBlock || - inVersionBlock || inSinceBlock || inDateBlock || inWarningBlock || inRemarkBlock || - inAttentionBlock || inBugBlock || inNoteBlock || - inParBlock || inExceptionBlock || inDeprecatedBlock || inPreBlock || - inPostBlock || inInvarBlock; -} - -static void endBlock() -{ - if (inParamBlock || inRetValBlock || inExceptionBlock) + while (!currentListIndent.isEmpty()) + { + char c=*currentListIndent.pop(); + switch(c) { - outDoc->endDescTableData(); - outDoc->endDescTable(); + case 'O': outDoc->endEnumList(); break; + case 'U': outDoc->endItemList(); break; + case 'D': + if (inBlock()) + { + currentListIndent.push("D"); // hack! + endBlock(); + } + else + outDoc->endDescription(); + break; } - outDoc->endDescList(); - inParamBlock=inRetValBlock=inSeeBlock=inReturnBlock=inAuthorBlock= - inVersionBlock=inSinceBlock=inDateBlock=inBugBlock=inNoteBlock=inWarningBlock= - inParBlock=inExceptionBlock=inDeprecatedBlock=inPreBlock=inPostBlock= - inInvarBlock=inRemarkBlock=inAttentionBlock=FALSE; + } + insideItemList=FALSE; } //----------------------------------------------------------------- @@ -999,6 +1019,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") endArgumentList(); if (b) endBlock(); inParBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); outDoc->docify(title); @@ -1018,6 +1039,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inWarningBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trWarning()+": "); @@ -1036,6 +1058,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inRemarkBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trRemarks()+": "); @@ -1054,6 +1077,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inAttentionBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trAttention()+": "); @@ -1072,6 +1096,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inBugBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trBugsAndLimitations()+": "); @@ -1090,6 +1115,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inNoteBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trNote()+": "); @@ -1108,6 +1134,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inPreBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trPrecondition()+": "); @@ -1126,6 +1153,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inPostBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trPostcondition()+": "); @@ -1144,6 +1172,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inInvarBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trInvariant()+": "); @@ -1162,6 +1191,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inVersionBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trVersion()+": "); @@ -1180,6 +1210,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inSinceBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trSince()+": "); @@ -1198,6 +1229,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inDateBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trDate()+": "); @@ -1220,6 +1252,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") ASSERT(item!=0); endArgumentList(); if (inBlock()) endBlock(); + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); outDoc->writeObjectLink(0,"todo",item->listAnchor,theTranslator->trTodo()+": "); @@ -1228,6 +1261,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") outDoc->writeDescItem(); internalParseDocument(item->text); outDoc->endDescList(); + currentListIndent.pop(); } } <DocScan>"\\test "[0-9]+ { // this tag is generated in an earlier pass @@ -1240,6 +1274,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") ASSERT(item!=0); endArgumentList(); if (inBlock()) endBlock(); + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); outDoc->writeObjectLink(0,"test",item->listAnchor,theTranslator->trTest()+": "); @@ -1248,6 +1283,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") outDoc->writeDescItem(); internalParseDocument(item->text); outDoc->endDescList(); + currentListIndent.pop(); } } <DocScan>{CMD}"deprecated"/{BN} { @@ -1256,6 +1292,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inDeprecatedBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trDeprecated()+": "); @@ -1276,6 +1313,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") tagText=tagText.left(tagText.length()-1); endArgumentList(); if (inBlock()) endBlock(); + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(tagName+": "); @@ -1284,6 +1322,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") outDoc->writeDescItem(); scanString(tagText); outDoc->endDescList(); + currentListIndent.pop(); } <DocScan>{CMD}"author"/{BN} { endArgumentList(); @@ -1291,6 +1330,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inAuthorBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trAuthors()+": "); @@ -1309,6 +1349,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inReturnBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trReturns()+": "); @@ -1323,6 +1364,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inSeeBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trSeeAlso()+": "); @@ -1346,6 +1388,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inParamBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trParameters()+": "); @@ -1371,6 +1414,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inRetValBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trReturnValues()+": "); @@ -1396,6 +1440,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") { if (inBlock()) endBlock(); inExceptionBlock=TRUE; + currentListIndent.push("D"); outDoc->startDescList(); outDoc->startBold(); scanString(theTranslator->trExceptions()+": "); @@ -1819,7 +1864,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") "Warning in the documentation of this entity:\nMore </ol> tags than <ol> tags in the documentation of this entity." ); } - else if (currentListIndent.top()!="O") + else if (*currentListIndent.top()!='O') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe </ol> tag does not end a <ol> tag." @@ -1841,7 +1886,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") "Warning in the documentation of this entity:\nMore </ul> tags than <ul> tags." ); } - else if (currentListIndent.top()!="U") + else if (*currentListIndent.top()!='U') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe </ul> tag does not end a <ul> tag." @@ -1855,7 +1900,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <DocScan>"<"{LI}{ATTR}">" { if (/*currentListIndent.isEmpty() ||*/ //DvH: I removed this check because I use this in the manual (the <ul> is in a \htmlonly block!) - currentListIndent.top()=="D") + !currentListIndent.isEmpty() && *currentListIndent.top()=='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe <li> tag can only be used inside a <ul> ... </ul> or a <ol> ... </ol> block." @@ -1882,7 +1927,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") "Warning in the documentation of this entity:\nMore </dl> tags than <dl> tags in the documentation." ); } - else if (currentListIndent.top()!="D") + else if (*currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe </dl> tag does not end a <dl> tag in the documentation." @@ -1896,7 +1941,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <DocScan>"<"{DT}{ATTR}">" { if (currentListIndent.isEmpty() || - currentListIndent.top()!="D") + *currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe <dt> tag can only be used inside a <dl> ... </dl> block." @@ -1910,7 +1955,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") <DocScan>"</"{DT}{ATTR}">" <DocScan>"<"{DD}{ATTR}">" { if (currentListIndent.isEmpty() || - currentListIndent.top()!="D") + *currentListIndent.top()!='D') { warn(yyFileName,yyLineNr, "Warning in the documentation of this entity:\nThe <dd> tag can only be used inside a <dl> ... </dl> block." diff --git a/src/doxygen.cpp b/src/doxygen.cpp index e01ef56..621039d 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -1174,7 +1174,7 @@ static MemberDef *addVariableToFile( NamespaceDef *nd = 0; if (!scope.isEmpty()) { - QCString nscope=removeAnnonymousScopes(scope); + QCString nscope=removeAnonymousScopes(scope); if (!nscope.isEmpty()) { nd = getResolvedNamespace(nscope); @@ -1219,7 +1219,7 @@ static MemberDef *addVariableToFile( MemberDef *md; for (mni.toFirst();(md=mni.current());++mni) { - QCString nscope=removeAnnonymousScopes(scope); + QCString nscope=removeAnonymousScopes(scope); NamespaceDef *nd=0; if (!nscope.isEmpty()) { @@ -1395,6 +1395,8 @@ void buildVarList(Entry *root) mtype=MemberDef::Typedef; else if (type.left(7)=="friend ") mtype=MemberDef::Friend; + else if (root->mtype==Property) + mtype=MemberDef::Property; else mtype=MemberDef::Variable; @@ -1811,7 +1813,7 @@ static void buildMemberList(Entry *root) NamespaceDef *nd = 0; if (root->parent->section == Entry::NAMESPACE_SEC ) { - QCString nscope=removeAnnonymousScopes(root->parent->name); + QCString nscope=removeAnonymousScopes(root->parent->name); if (!nscope.isEmpty()) { nd = getResolvedNamespace(nscope); @@ -3044,7 +3046,7 @@ static void findMember(Entry *root,QCString funcDecl,QCString related,bool overl //printf("result: scope=%s\n",scopeName.data()); } - namespaceName=removeAnnonymousScopes(namespaceName); + namespaceName=removeAnonymousScopes(namespaceName); //printf("namespaceName=`%s' className=`%s'\n",namespaceName.data(),className.data()); // merge class and namespace scopes again scopeName.resize(0); @@ -4135,9 +4137,8 @@ static void generateFileSources() for (;(fd=fni.current());++fni) { bool src = !fd->isReference() && - (Config::verbatimHeaderFlag - //fd->generateSource() - || Config::sourceBrowseFlag); + fd->name().right(4)!=".doc" && fd->name().right(4)!=".txt" && + (Config::verbatimHeaderFlag || Config::sourceBrowseFlag); if (src) { msg("Generating code for file %s...\n",fd->name().data()); @@ -6044,8 +6045,11 @@ int main(int argc,char **argv) msg("Generating page index...\n"); writePageIndex(*outputList); - msg("Generating graph info page...\n"); - writeGraphInfo(*outputList); + if (Config::generateLegend) + { + msg("Generating graph info page...\n"); + writeGraphInfo(*outputList); + } msg("Generating search index...\n"); generateSearchIndex(); diff --git a/src/doxygen.dtd b/src/doxygen.dtd index a479ee5..62727b8 100644 --- a/src/doxygen.dtd +++ b/src/doxygen.dtd @@ -1,4 +1,4 @@ -<?xml encoding="ISO-8859-1"?> +<?xml version="1.0" encoding="ISO-8859-1"?> <!-- DTD describing the grammar used in doxygen's XML output --> <!-- standard character entities --> @@ -50,6 +50,8 @@ |friend |related |define|prototype|typedef|enum|func|var + |dcop-func + |property ) #REQUIRED ' > diff --git a/src/doxygen.pro.in b/src/doxygen.pro.in index 30312b7..66d57a0 100644 --- a/src/doxygen.pro.in +++ b/src/doxygen.pro.in @@ -15,7 +15,7 @@ # TMake project file for doxygen TEMPLATE = doxygen.t -CONFIG = console qt warn_on $extraopts +CONFIG = console warn_on $extraopts HEADERS = doxygen.h scanner.h doc.h classdef.h classlist.h memberdef.h \ membername.h index.h memberlist.h definition.h \ entry.h logos.h instdox.h message.h code.h \ @@ -27,7 +27,7 @@ HEADERS = doxygen.h scanner.h doc.h classdef.h classlist.h memberdef.h \ translator_it.h formula.h debug.h membergroup.h htmlhelp.h \ translator_ru.h translator_pl.h dot.h rtfgen.h xml.h xml_dtd.h \ reflist.h page.h sortdict.h translator_hu.h translator_kr.h \ - translator_ro.h translator_si.h + translator_ro.h translator_si.h translator_cn.h SOURCES = doxygen.cpp scanner.cpp doc.cpp classdef.cpp classlist.cpp \ memberdef.cpp membername.cpp index.cpp memberlist.cpp \ entry.cpp logos.cpp instdox.cpp message.cpp code.cpp \ @@ -39,7 +39,11 @@ SOURCES = doxygen.cpp scanner.cpp doc.cpp classdef.cpp classlist.cpp \ version.cpp language.cpp definition.cpp formula.cpp debug.cpp \ membergroup.cpp htmlhelp.cpp dot.cpp rtfgen.cpp xml.cpp \ reflist.cpp +unix:LIBS += -L../qtools -lqtools win32:INCLUDEPATH += . -win32:LIBS += shell32.lib +win32:LIBS += qtools.lib shell32.lib +win32:TMAKE_LFLAGS += /LIBPATH:..\qtools +win32:TMAKE_CXXFLAGS += -DQT_NODLL +INCLUDEPATH += ../qtools TARGET = ../bin/doxygen OBJECTS_DIR = ../objects diff --git a/src/doxytag.pro.in b/src/doxytag.pro.in index 1032443..d91378d 100644 --- a/src/doxytag.pro.in +++ b/src/doxytag.pro.in @@ -15,11 +15,15 @@ # TMake project file for doxytag TEMPLATE = doxytag.t -CONFIG = console warn_on qt $extraopts +CONFIG = console warn_on $extraopts HEADERS = suffixtree.h searchindex.h logos.h version.h SOURCES = doxytag.cpp suffixtree.cpp searchindex.cpp \ logos.cpp version.cpp -TARGET = ../bin/doxytag -win32:INCLUDEPATH += . -#unix:INCLUDEPATH += /usr/include +unix:LIBS += -L../qtools -lqtools +win32:INCLUDEPATH += . +win32:LIBS += qtools.lib +win32:TMAKE_LFLAGS += /LIBPATH:..\qtools +win32:TMAKE_CXXFLAGS += -DQT_NODLL +INCLUDEPATH += ../qtools OBJECTS_DIR = ../objects +TARGET = ../bin/doxytag diff --git a/src/entry.h b/src/entry.h index 27035e2..c836d87 100644 --- a/src/entry.h +++ b/src/entry.h @@ -23,7 +23,7 @@ enum Protection { Public, Protected, Private } ; enum Specifier { Normal, Virtual, Pure } ; -enum MethodTypes { Method, Signal, Slot, DCOP }; +enum MethodTypes { Method, Signal, Slot, DCOP, Property }; struct BaseInfo { @@ -162,7 +162,7 @@ class Entry int section; // entry type (see Sections); Protection protection; // class protection - MethodTypes mtype; // signal, slot or dcop method? + MethodTypes mtype; // signal, slot, (dcop) method, or property? bool stat; // static ? bool explicitExternal; // explicitly defined as external? bool proto; // prototype ? diff --git a/src/filedef.cpp b/src/filedef.cpp index 3d20233..6ce4c86 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -220,6 +220,7 @@ void FileDef::writeDocumentation(OutputList &ol) //incDepGraph.writeGraph(Config::htmlOutputDir,fd->getOutputFileBase()); } + //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile()); if (generateSourceFile()) { ol.disableAllBut(OutputGenerator::Html); diff --git a/src/groupdef.cpp b/src/groupdef.cpp index eb0611f..5476dc1 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -285,7 +285,7 @@ void GroupDef::writeDocumentation(OutputList &ol) while (nd) { ol.startMemberItem(0); - ol.docify("namespace"); + ol.docify("namespace "); ol.insertMemberAlign(); ol.writeObjectLink(nd->getReference(),nd->getOutputFileBase(),0,nd->name()); ol.endMemberItem(FALSE); diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 40eed09..1b93b5a 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -89,7 +89,7 @@ void HtmlGenerator::init() exit(1); } writeLogo(Config::htmlOutputDir); - writeNullImage(Config::htmlOutputDir); + //writeNullImage(Config::htmlOutputDir); } void HtmlGenerator::writeStyleSheetFile(QFile &file) diff --git a/src/index.cpp b/src/index.cpp index 9bd0e37..f470341 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -320,6 +320,7 @@ void writeGraphicalClassHierarchy(OutputList &ol) //---------------------------------------------------------------------------- + void countFiles(int &htmlFiles,int &files) { htmlFiles=0; @@ -334,13 +335,18 @@ void countFiles(int &htmlFiles,int &files) { bool doc = fd->isLinkableInProject(); bool src = fd->generateSourceFile(); - if (doc || src) - { - htmlFiles++; - } - if (doc) + bool nameOk = fd->name().right(4)!=".doc" && + fd->name().right(4)!=".txt"; + if (nameOk) { - files++; + if (doc || src) + { + htmlFiles++; + } + if (doc) + { + files++; + } } } } @@ -416,7 +422,10 @@ void writeFileIndex(OutputList &ol) //printf("Found filedef %s\n",fd->name().data()); bool doc = fd->isLinkableInProject(); bool src = fd->generateSourceFile(); - if ((doc || src) && !fd->isReference()) + bool nameOk = fd->name().right(4)!=".doc" && + fd->name().right(4)!=".txt"; + if (nameOk && (doc || src) && + !fd->isReference()) { QCString path; if (Config::fullPathNameFlag) @@ -1223,11 +1232,6 @@ void writeNamespaceMemberList(OutputList &ol,bool useSections) first=FALSE; } } - else if (first) - { - first=FALSE; - ol.startItemList(); - } ol.writeListItem(); ol.docify(md->name()); if (md->isFunction()) ol.docify("()"); diff --git a/src/language.cpp b/src/language.cpp index 4fca8c7..e7a9576 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -35,6 +35,7 @@ #include "translator_kr.h" #include "translator_ro.h" #include "translator_si.h" +#include "translator_cn.h" #endif #define L_EQUAL(a) !stricmp(langName,a) @@ -120,6 +121,10 @@ bool setTranslator(const char *langName) { theTranslator=new TranslatorSlovene; } + else if (L_EQUAL("chinese")) + { + theTranslator=new TranslatorChinese; + } #endif else // use the default language (i.e. english) { diff --git a/src/logos.cpp b/src/logos.cpp index f598435..92bc08e 100644 --- a/src/logos.cpp +++ b/src/logos.cpp @@ -22,13 +22,13 @@ #include <qdir.h> -unsigned char null_data[] = { - 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0xff, - 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b -}; -unsigned int null_len = 43; +//unsigned char null_data[] = { +// 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0xff, +// 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, +// 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, +// 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b +//}; +//unsigned int null_len = 43; unsigned char logo_data[] = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x6e, 0x00, 0x35, 0x00, 0xe7, 0x00, @@ -3139,18 +3139,18 @@ unsigned char doxfont_data[] = { }; unsigned int doxfont_len = 32760; -void writeNullImage(const char *dir) -{ - QCString fileName=(QCString)dir+"/null.gif"; - QFile f(fileName); - if (f.open(IO_WriteOnly)) - f.writeBlock((char *)null_data,null_len); - else - { - fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data()); - } - f.close(); -} +//void writeNullImage(const char *dir) +//{ +// QCString fileName=(QCString)dir+"/null.gif"; +// QFile f(fileName); +// if (f.open(IO_WriteOnly)) +// f.writeBlock((char *)null_data,null_len); +// else +// { +// fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data()); +// } +// f.close(); +//} void writeLogo(const char *dir) { diff --git a/src/logos.h b/src/logos.h index 5dbdf22..d8f84a5 100644 --- a/src/logos.h +++ b/src/logos.h @@ -19,7 +19,7 @@ #define LOGOS_H extern void writeLogo(const char *dir); -extern void writeNullImage(const char *dir); +//extern void writeNullImage(const char *dir); extern void writeSearchButton(const char *dir); extern void writeDoxFont(const char *dir); extern void removeDoxFont(const char *dir); diff --git a/src/mangen.cpp b/src/mangen.cpp index cd5718c..852a0f4 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -73,10 +73,29 @@ void ManGenerator::init() void ManGenerator::startFile(const char *name,const char *,bool) { QCString fileName=name; + + // TODO: do something sensible here. if (fileName.left(6)=="class_") { fileName=fileName.right(fileName.length()-6); } + else if (fileName.left(10)=="interface_") + { + fileName=fileName.right(fileName.length()-10); + } + else if (fileName.left(7)=="struct_") + { + fileName=fileName.right(fileName.length()-7); + } + else if (fileName.left(6)=="union_") + { + fileName=fileName.right(fileName.length()-6); + } + else if (fileName.left(10)=="exception_") + { + fileName=fileName.right(fileName.length()-10); + } + int i; if ((i=fileName.findRev('.'))!=-1) { diff --git a/src/memberdef.cpp b/src/memberdef.cpp index f9a8ff9..1c2e940 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -1411,6 +1411,7 @@ void MemberDef::generateXML(QTextStream &t,Definition *def) { case Define: t << "definedef"; xmlType=define_t; break; case EnumValue: // fall through + case Property: // fall through case Variable: t << "variabledef"; xmlType=variable_t; break; case Typedef: t << "typedef"; xmlType=typedef_t; break; case Enumeration: t << "enumdef"; xmlType=enum_t; break; @@ -1423,7 +1424,8 @@ void MemberDef::generateXML(QTextStream &t,Definition *def) } t << " id=\""; t << def->getOutputFileBase() - << ":" + << "__" // can we change this to a non ID char? + // : do not seem allowed for some parsers! << anchor(); t << "\""; if (xmlType==function_t && virtualness()!=Normal) @@ -1444,15 +1446,13 @@ void MemberDef::generateXML(QTextStream &t,Definition *def) (xmlType!=function_t || !type.isEmpty()) // Type is optional here. ) { + QCString typeStr = replaceAnonymousScopes(type); + if (xmlType==typedef_t && typeStr.left(8)=="typedef ") + typeStr=typeStr.right(typeStr.length()-8); + if (xmlType==function_t && typeStr.left(8)=="virtual ") + typeStr=typeStr.right(typeStr.length()-8); t << " <type>"; - if (xmlType==typedef_t && type.left(8)=="typedef ") - linkifyText(TextGeneratorXMLImpl(t),scopeName,name(), - type.right(type.length()-8)); // strip "typedef " - else if (xmlType==function_t && type.left(8)=="virtual ") - linkifyText(TextGeneratorXMLImpl(t),scopeName,name(), - type.right(type.length()-8)); // strip "virtual " - else - linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),type); + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),typeStr); t << "</type>" << endl; } @@ -1560,6 +1560,7 @@ void MemberDef::generateXML(QTextStream &t,Definition *def) { case Define: t << "definedef"; break; case EnumValue: // fall through + case Property: // fall through case Variable: t << "variabledef"; break; case Typedef: t << "typedef"; break; case Enumeration: t << "enumdef"; break; diff --git a/src/memberdef.h b/src/memberdef.h index a0c655e..bee7ca4 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -58,7 +58,8 @@ class MemberDef : public Definition Signal, Slot, Friend, - DCOP + DCOP, + Property }; enum @@ -111,6 +112,7 @@ class MemberDef : public Definition bool isDefine() const { return mtype==Define; } bool isFriend() const { return mtype==Friend; } bool isDCOP() const { return mtype==DCOP; } + bool isProperty() const { return mtype==Property; } bool isRelated() const { return related; } bool isStatic() const { return stat; } bool isInline() const { return (memSpec&Entry::Inline)!=0; } @@ -132,8 +134,8 @@ class MemberDef : public Definition void setMemberSpecifiers(int s) { memSpec=s; } void mergeMemberSpecifiers(int s) { memSpec|=s; } void setInitializer(const char *i) { init=i; - init=init.stripWhiteSpace(); - initLines=init.contains('\n'); + init=init.stripWhiteSpace(); + initLines=init.contains('\n'); } void setBitfields(const char *s) { bitfields = s; } void setMaxInitLines(int lines) { if (lines!=-1) maxInitLines=lines; } diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 60a4e90..3e7b7a0 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -70,7 +70,9 @@ void MemberList::countDecMembers(bool inGroup,bool countSubGroups,bool sectionPe { switch(md->memberType()) { - case MemberDef::Variable: varCnt++,m_count++; break; + case MemberDef::Variable: // fall through + case MemberDef::Property: varCnt++,m_count++; + break; case MemberDef::Function: // fall through case MemberDef::Signal: // fall through case MemberDef::DCOP: // fall through @@ -346,13 +348,13 @@ void MemberList::writePlainDeclarations(OutputList &ol, typeDecl.enable(OutputGenerator::Man); enumMemCount++; } - } - if (fmdl->count()>MAX_ENUM_VALUES_FOR_ONE_LINE) - { - typeDecl.pushGeneratorState(); - typeDecl.disableAllBut(OutputGenerator::Html); - typeDecl.lineBreak(); - typeDecl.popGeneratorState(); + if (fmdl->count()>MAX_ENUM_VALUES_FOR_ONE_LINE) + { + typeDecl.pushGeneratorState(); + typeDecl.disableAllBut(OutputGenerator::Html); + typeDecl.lineBreak(); + typeDecl.popGeneratorState(); + } } typeDecl.docify(" }"); md->setEnumDecl(typeDecl); @@ -496,7 +498,8 @@ void MemberList::writePlainDeclarations(OutputList &ol, MemberListIterator mli(*this); for ( ; (md=mli.current()) ; ++mli ) { - if (md->isVariable() && inGroup==md->visibleMemberGroup(sectionPerType)) + if ((md->isVariable() || md->isProperty()) && + inGroup==md->visibleMemberGroup(sectionPerType)) { md->writeDeclaration(ol,cd,nd,fd,gd,inGroup); } diff --git a/src/message.cpp b/src/message.cpp index 9554c02..112d5af 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -28,6 +28,8 @@ static int warnFormatOrder; // 1 = $file,$line,$text // 5 = $text,$file,$line // 6 = $line,$file,$text +static FILE *warnFile = stderr; + void initWarningFormat() { int filePos = Config::warnFormat.find("$file"); @@ -78,6 +80,11 @@ void initWarningFormat() // replace(QRegExp("\\$text"),"%s"). // replace(QRegExp("\\$line"),"%d")+ // '\n'; + + if (!Config::warnLogFile.isEmpty()) + { + warnFile = fopen(Config::warnLogFile,"w"); + } } @@ -104,12 +111,12 @@ void warn(const char *file,int line,const char *fmt, ...) va_end(args); switch(warnFormatOrder) { - case 1: fprintf(stderr,outputFormat,file,line,text); break; - case 2: fprintf(stderr,outputFormat,text,line,file); break; - case 3: fprintf(stderr,outputFormat,line,text,file); break; - case 4: fprintf(stderr,outputFormat,file,text,line); break; - case 5: fprintf(stderr,outputFormat,text,file,line); break; - case 6: fprintf(stderr,outputFormat,line,file,text); break; + case 1: fprintf(warnFile,outputFormat,file,line,text); break; + case 2: fprintf(warnFile,outputFormat,text,line,file); break; + case 3: fprintf(warnFile,outputFormat,line,text,file); break; + case 4: fprintf(warnFile,outputFormat,file,text,line); break; + case 5: fprintf(warnFile,outputFormat,text,file,line); break; + case 6: fprintf(warnFile,outputFormat,line,file,text); break; default: printf("Error: warning format has not been initialized!\n"); } @@ -122,7 +129,7 @@ void warn_cont(const char *fmt, ...) { va_list args; va_start(args, fmt); - vfprintf(stderr, fmt, args); + vfprintf(warnFile, fmt, args); va_end(args); } } @@ -139,12 +146,12 @@ void warn_undoc(const char *file,int line,const char *fmt, ...) va_end(args); switch(warnFormatOrder) { - case 1: fprintf(stderr,outputFormat,file,line,text); break; - case 2: fprintf(stderr,outputFormat,text,line,file); break; - case 3: fprintf(stderr,outputFormat,line,text,file); break; - case 4: fprintf(stderr,outputFormat,file,text,line); break; - case 5: fprintf(stderr,outputFormat,text,file,line); break; - case 6: fprintf(stderr,outputFormat,line,file,text); break; + case 1: fprintf(warnFile,outputFormat,file,line,text); break; + case 2: fprintf(warnFile,outputFormat,text,line,file); break; + case 3: fprintf(warnFile,outputFormat,line,text,file); break; + case 4: fprintf(warnFile,outputFormat,file,text,line); break; + case 5: fprintf(warnFile,outputFormat,text,file,line); break; + case 6: fprintf(warnFile,outputFormat,line,file,text); break; default: printf("Error: warning format has not been initialized!\n"); } @@ -155,6 +162,6 @@ void err(const char *fmt, ...) { va_list args; va_start(args, fmt); - vfprintf(stderr, fmt, args); + vfprintf(warnFile, fmt, args); va_end(args); } diff --git a/src/message.h b/src/message.h index 87022f6..df2bc94 100644 --- a/src/message.h +++ b/src/message.h @@ -18,6 +18,8 @@ #ifndef MESSAGE_H #define MESSAGE_H +#include <stdio.h> + extern void msg(const char *fmt, ...); extern void warn(const char *file,int line,const char *fmt, ...); extern void warn_cont(const char *fmt, ...); diff --git a/src/scanner.l b/src/scanner.l index c63de52..a12189b 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -519,6 +519,16 @@ TITLE [tT][iI][tT][lL][eE] unput(*yytext); BEGIN( FindMembers ); } +<FindMembers>{B}*("properties"|"__property"){BN}*":"{BN}* { // IDL or Borland C++ builder property + current->mtype = mtype = Property; + current->protection = protection = Public ; + current->type.resize(0); + current->name.resize(0); + current->args.resize(0); + current->argList->clear(); + lineCount() ; + } + <FindMembers>{B}*"k_dcop"{BN}*":"{BN}* { current->mtype = mtype = DCOP; current->protection = protection = Public ; current->type.resize(0); @@ -566,9 +576,7 @@ TITLE [tT][iI][tT][lL][eE] current->argList->clear(); lineCount(); } -<FindMembers>{B}*"properties"{B}":" { /* M$-IDL only: ignored */ } -<FindMembers>{B}*"methods"{B}":" { /* M$-IDL only: ignored */ } -<FindMembers>{B}*"public"{BN}*":"{BN}* { +<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* { current->protection = protection = Public ; current->mtype = mtype = Method; current->type.resize(0); diff --git a/src/translator.h b/src/translator.h index 5808ae1..4849c95 100644 --- a/src/translator.h +++ b/src/translator.h @@ -566,7 +566,9 @@ class Translator virtual QCString trGeneratedBy() { return "Generated by"; } - // new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// /*! used as the title of page containing all the index of all namespaces. */ virtual QCString trNamespaceList() @@ -607,7 +609,6 @@ class Translator bool isTemplate) { QCString result=(QCString)clName+" "; - if (isTemplate) result+=" Template"; switch(compType) { case ClassDef::Class: result+=" Class"; break; @@ -616,6 +617,7 @@ class Translator case ClassDef::Interface: result+=" Interface"; break; case ClassDef::Exception: result+=" Exception"; break; } + if (isTemplate) result+=" Template"; result+=" Reference"; return result; } @@ -1086,6 +1088,20 @@ class Translator return "DCOP Methods"; } +////////////////////////////////////////////////////////////////////////// +// new since 1.2.2 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for IDL properties */ + virtual QCString trProperties() + { + return "Properties"; + } + /*! Used as a section header for IDL property documentation */ + virtual QCString trPropertyDocumentation() + { + return "Property Documentation"; + } }; #endif diff --git a/src/translator_cn.h b/src/translator_cn.h new file mode 100644 index 0000000..9343695 --- /dev/null +++ b/src/translator_cn.h @@ -0,0 +1,707 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef TRANSLATOR_CN_H +#define TRANSLATOR_CN_H + +#include "translator.h" + +/*! + If you want insert a space whenever Chinese meets English charactors, set + CN_SPC to " ", else null. +*/ +#define CN_SPC + +class TranslatorChinese : public Translator +{ + public: + QCString idLanguage() + { return "chinese"; } + QCString idLanguageCharset() + { return "gb2312"; } + QCString latexBabelPackage() + { return "chinese"; } + QCString trRelatedFunctions() + { return "Ïà¹Øº¯Êý"; } + QCString trRelatedSubscript() + { return "£¨×¢Ò⣺ÕâЩ²»ÊdzÉÔ±º¯Êý£©"; } + QCString trDetailedDescription() + { return "ÏêϤÃèÊö"; } + QCString trMemberTypedefDocumentation() + { return "³ÉÔ±ÀàÐͶ¨ÒåÎĵµ"; } + QCString trMemberEnumerationDocumentation() + { return "³ÉԱö¾ÙÀàÐÍÎĵµ"; } + QCString trEnumerationValueDocumentation() + { return "³ÉԱö¾ÙÖµÎĵµ"; } + QCString trMemberFunctionDocumentation() + { return "³ÉÔ±º¯ÊýÎĵµ"; } + QCString trMemberDataDocumentation() + { return "³ÉÔ±Êý¾ÝÎĵµ"; } + QCString trMore() + { return "¸ü¶à..."; } + QCString trListOfAllMembers() + { return "ËùÓгÉÔ±µÄÁÐ±í¡£"; } + QCString trMemberList() + { return "³ÉÔ±Áбí"; } + QCString trThisIsTheListOfAllMembers() + { return "³ÉÔ±µÄÍêÕûÁÐ±í£¬ÕâЩ³ÉÔ±ÊôÓÚ"CN_SPC; } + QCString trIncludingInheritedMembers() + { return "£¬°üÀ¨ËùÓм̳жøÀ´µÄ³ÉÔ±"; } + QCString trGeneratedAutomatically(const char *s) + { QCString result; + if (s) result=(QCString)"Ϊ"CN_SPC+s+"£¬"; + result+="ÓÉ"CN_SPC"Doyxgen"CN_SPC"ͨ¹ý·ÖÎöÔ´´úÂë×Ô¶¯Éú³É¡£"; + return result; + } + QCString trEnumName() + { return "ö¾ÙÃû³Æ"; } + QCString trEnumValue() + { return "ö¾ÙÖµ"; } + QCString trDefinedIn() + { return "¶¨ÒåÓÚ"CN_SPC; } + QCString trVerbatimText(const char *f) + { return (QCString)"ÕâÊÇÍ·Îļþ"CN_SPC+f+CN_SPC"µÄÔ´´úÂë¡£"; } + QCString trModules() + { return "Ä£¿é"; } + QCString trClassHierarchy() + { return "Àà¼Ì³Ð¹Øϵ"; } + QCString trCompoundList() + { return "×éºÏÀàÐÍÁбí"; } + QCString trFileList() + { return "ÎļþÁбí"; } + QCString trHeaderFiles() + { return "Í·Îļþ"; } + QCString trCompoundMembers() + { return "×éºÏÀàÐͳÉÔ±"; } + QCString trFileMembers() + { return "Îļþ³ÉÔ±"; } + QCString trRelatedPages() + { return "Ïà¹ØÒ³Ãæ"; } + QCString trExamples() + { return "ʾÀý"; } + QCString trSearch() + { return "ËÑË÷"; } + QCString trClassHierarchyDescription() + { return "´ËÁбí»ù±¾°´×Öµä˳ÐòÅÅÐò£º"; } + QCString trFileListDescription(bool extractAll) + { + QCString result="ÕâÀïÁгöËùÓÐ"; + if (!extractAll) result+="Îĵµ»¯µÄ"; + result+="Îļþ£¬¸½´ø¼òҪ˵Ã÷£º"; + return result; + } + QCString trCompoundListDescription() + { return "ÕâÀïÁгöËùÓÐÀà¡¢½á¹¹¡¢ÁªºÏÒÔ¼°½Ó¿Ú¶¨Ò壬¸½´ø¼òҪ˵Ã÷£º"; + } + QCString trCompoundMembersDescription(bool extractAll) + { + QCString result="ÕâÀïÁгöËùÓÐ"; + if (!extractAll) result+="Îĵµ»¯µÄ"; + result+="Àà³ÉÔ±£¬¸½´ø"; + if (extractAll) result+="ËùÔÚÀàµÄÎĵµµÄÁ´½Ó£º"; + else result+="ËùÔÚÀàµÄÁ´½Ó£º"; + return result; + } + QCString trFileMembersDescription(bool extractAll) + { + QCString result="ÕâÀïÁгöËùÓÐ"; + if (!extractAll) result+="Îĵµ»¯µÄ"; + result+="Îļþ³ÉÔ±£¬¸½´ø"; + if (extractAll) result+="ËùÔÚÎļþµÄÎĵµµÄÁ´½Ó£º"; + else result+="ËùÔÚÎļþµÄÁ´½Ó£º"; + return result; + } + QCString trHeaderFilesDescription() + { return "ÕâÀïÁгö×é³ÉAPIµÄÍ·Îļþ£º"; } + QCString trExamplesDescription() + { return "ÕâÀïÁгöËùÓÐʾÀý£º"; } + QCString trRelatedPagesDescription() + { return "ÕâÀïÁгöËùÓÐÏà¹ØµÄÒ³Ã棺"; } + QCString trModulesDescription() + { return "ÕâÀïÁгöËùÓÐÄ£¿é"; } + QCString trNoDescriptionAvailable() + { return "ÎÞ¿ÉÓÃÎĵµ"; } + + QCString trDocumentation() + { return "Îĵµ"; } + QCString trModuleIndex() + { return "Ä£¿éË÷Òý"; } + QCString trHierarchicalIndex() + { return "¼Ì³Ð¹ØϵË÷Òý"; } + QCString trCompoundIndex() + { return "×éºÏÀàÐÍË÷Òý"; } + QCString trFileIndex() + { return "ÎļþË÷Òý"; } + QCString trModuleDocumentation() + { return "Ä£¿éÎĵµ"; } + QCString trClassDocumentation() + { return "ÀàÎĵµ"; } + QCString trFileDocumentation() + { return "ÎļþÎĵµ"; } + QCString trExampleDocumentation() + { return "ʾÀýÎĵµ"; } + QCString trPageDocumentation() + { return "Ò³ÃæÎĵµ"; } + QCString trReferenceManual() + { return "²Î¿¼ÊÖ²á"; } + + QCString trDefines() + { return "ºê¶¨Òå"; } + QCString trFuncProtos() + { return "º¯ÊýÔÐÍ"; } + QCString trTypedefs() + { return "ÀàÐͶ¨Òå"; } + QCString trEnumerations() + { return "ö¾Ù"; } + QCString trFunctions() + { return "º¯Êý"; } + QCString trVariables() + { return "±äÁ¿"; } + QCString trEnumerationValues() + { return "ö¾ÙÖµ"; } + QCString trAuthor() + { return "×÷Õß"; } + QCString trDefineDocumentation() + { return "ºê¶¨ÒåÎĵµ"; } + QCString trFunctionPrototypeDocumentation() + { return "º¯ÊýÔÐÍÎĵµ"; } + QCString trTypedefDocumentation() + { return "ÀàÐͶ¨ÒåÎĵµ"; } + QCString trEnumerationTypeDocumentation() + { return "ö¾ÙÀàÐÍÎĵµ"; } + QCString trFunctionDocumentation() + { return "º¯ÊýÎĵµ"; } + QCString trVariableDocumentation() + { return "±äÁ¿Îĵµ"; } + QCString trCompounds() + { return "×éºÏÀàÐÍ"; } + QCString trFiles() + { return "Îļþ"; } + QCString trGeneratedAt(const char *date,const char *projName) + { + QCString result=(QCString)"Generated at "+date; + if (projName) result+=(QCString)" for "+projName; + result+=(QCString)" by"; + return result; + } + QCString trWrittenBy() + { + return "written by"; + } + QCString trClassDiagram(const char *clName) + { + return (QCString)"¼Ì³Ðͼ£¬Àà"CN_SPC+clName; + } + QCString trForInternalUseOnly() + { return "½öÏÞÄÚ²¿Ê¹Óá£"; } + QCString trReimplementedForInternalReasons() + { return "ÓÉÓÚÄÚ²¿ÔÒò±»ÖØÔØ£»µ«²»Ó°ÏìAPI"; + } + QCString trWarning() + { return "¾¯¸æ"; } + QCString trBugsAndLimitations() + { return "BUG"CN_SPC"Óë¾ÖÏÞ"; } + QCString trVersion() + { return "°æ±¾"; } + QCString trDate() + { return "ÈÕÆÚ"; } + QCString trAuthors() + { return "×÷Õß"; } + QCString trReturns() + { return "·µ»Ø"; } + QCString trSeeAlso() + { return "²Î¼û"; } + QCString trParameters() + { return "²ÎÊý"; } + QCString trExceptions() + { return "Òì³£"; } + QCString trGeneratedBy() + { return "ÖÆ×÷Õß"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990307 +////////////////////////////////////////////////////////////////////////// + + QCString trNamespaceList() + { return "ÃüÃû¿Õ¼äÁбí"; } + QCString trNamespaceListDescription(bool extractAll) + { + QCString result="ÕâÀïÁгöËùÓÐ"; + if (!extractAll) result+="Îĵµ»¯µÄ"; + result+="ÃüÃû¿Õ¼ä¶¨Ò壬¸½´ø¼òҪ˵Ã÷£º"; + return result; + } + QCString trFriends() + { return "ÓÑÔª"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990405 +////////////////////////////////////////////////////////////////////////// + + QCString trRelatedFunctionDocumentation() + { return "ÓÑÔª¼°Ïà¹Øº¯ÊýÎĵµ"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990425 +////////////////////////////////////////////////////////////////////////// + + QCString trCompoundReference(const char *clName, + ClassDef::CompoundType compType, + bool isTemplate) + // used as the title of the HTML page of a class/struct/union + { + QCString result=(QCString)clName; + if (isTemplate) result+=CN_SPC"Ä£°å"; + switch(compType) + { + case ClassDef::Class: result+="Àà"; break; + case ClassDef::Struct: result+="½á¹¹"; break; + case ClassDef::Union: result+="ÁªºÏ"; break; + case ClassDef::Interface: result+="½Ó¿Ú"; break; + case ClassDef::Exception: result+="Òì³£"; break; + } + result+="²Î¿¼"; + return result; + } + QCString trFileReference(const char *fileName) + // used as the title of the HTML page of a file + { + QCString result=fileName; + result+=CN_SPC"Îļþ²Î¿¼"; + return result; + } + QCString trNamespaceReference(const char *namespaceName) + // used as the title of the HTML page of a namespace + { + QCString result=namespaceName; + result+=CN_SPC"ÃüÃû¿Õ¼ä²Î¿¼"; + return result; + } + + // these are for the member sections of a class, struct or union + QCString trPublicMembers() + { return "¹«ÓгÉÔ±"; } + QCString trPublicSlots() + { return "¹«ÓвÛ"; } + QCString trSignals() + { return "ÐźÅ"; } + QCString trStaticPublicMembers() + { return "¾²Ì¬¹«ÓгÉÔ±"; } + QCString trProtectedMembers() + { return "±£»¤³ÉÔ±"; } + QCString trProtectedSlots() + { return "±£»¤²Û"; } + QCString trStaticProtectedMembers() + { return "¾²Ì¬±£»¤³ÉÔ±"; } + QCString trPrivateMembers() + { return "˽ÓгÉÔ±"; } + QCString trPrivateSlots() + { return "˽ÓвÛ"; } + QCString trStaticPrivateMembers() + { return "¾²Ì¬Ë½ÓгÉÔ±"; } + // end of member sections + + QCString trWriteList(int numEntries) + { + // this function is used to produce a comma-separated list of items. + // use generateMarker(i) to indicate where item i should be put. + QCString result; + int i; + // the inherits list contain `numEntries' classes + for (i=0;i<numEntries;i++) + { + // use generateMarker to generate placeholders for the class links! + result+=generateMarker(i); // generate marker for entry i in the list + // (order is left to right) + + if (i!=numEntries-1) // not the last entry, so we need a separator + { + if (i<numEntries-2) // not the fore last entry + result+="¡¢"; + else // the fore last entry + result+=CN_SPC"¼°"CN_SPC; + } + } + return result; + } + + QCString trInheritsList(int numEntries) + // used in class documentation to produce a list of base classes, + // if class diagrams are disabled. + { + return "¼Ì³Ð×Ô"CN_SPC+trWriteList(numEntries)+"¡£"; + } + QCString trInheritedByList(int numEntries) + // used in class documentation to produce a list of super classes, + // if class diagrams are disabled. + { + return "±»"CN_SPC+trWriteList(numEntries)+CN_SPC"¼Ì³Ð."; + } + QCString trReimplementedFromList(int numEntries) + // used in member documentation blocks to produce a list of + // members that are hidden by this one. + { + return "ÖØÔØ"CN_SPC+trWriteList(numEntries)+"¡£"; + } + QCString trReimplementedInList(int numEntries) + { + // used in member documentation blocks to produce a list of + // all member that overwrite the implementation of this member. + return "±»"CN_SPC+trWriteList(numEntries)+CN_SPC"ÖØÔØ¡£"; + } + + QCString trNamespaceMembers() + // This is put above each page as a link to all members of namespaces. + { return "ÃüÃû¿Õ¼ä³ÉÔ±"; } + QCString trNamespaceMemberDescription(bool extractAll) + // This is an introduction to the page with all namespace members + { + QCString result="ÕâÀïÁгöÁËËùÓÐ"; + if (!extractAll) result+="Îĵµ»¯µÄ"; + result+="ÃüÃû¿Õ¼ä³ÉÔ±£¬¸½´ø"; + if (extractAll) + result+="ËùÔÚÀàµÄÎĵµµÄÁ´½Ó£º"; + else + result+="ËùÔÚÀàµÄÁ´½Ó£º"; + return result; + } + QCString trNamespaceIndex() + // This is used in LaTeX as the title of the chapter with the + // index of all namespaces. + { return "ÃüÃû¿Õ¼äË÷Òý"; } + QCString trNamespaceDocumentation() + // This is used in LaTeX as the title of the chapter containing + // the documentation of all namespaces. + { return "ÃüÃû¿Õ¼äÎĵµ"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990728 +////////////////////////////////////////////////////////////////////////// + + /*! This is put at the bottom of a class documentation page and is + * followed by a list of files that were used to generate the page. + */ + QCString trGeneratedFromFiles(ClassDef::CompoundType compType, + bool) + { // here s is one of " Class", " Struct" or " Union" + // single is true implies a single file + QCString result=(QCString)"¸Ã"; + switch(compType) + { + case ClassDef::Class: result+="Àà"; break; + case ClassDef::Struct: result+="½á¹¹"; break; + case ClassDef::Union: result+="ÁªºÏ"; break; + case ClassDef::Interface: result+="½Ó¿Ú"; break; + case ClassDef::Exception: result+="Òì³£"; break; + } + result+="µÄÎĵµÓÉÒÔÏÂÎļþÉú³É£º"; + return result; + } + + /*! This is in the (quick) index as a link to the alphabetical compound + * list. + */ + QCString trAlphabeticalList() + { return "°´×Öµä˳ÐòÅÅÐòµÄÁбí"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990901 +////////////////////////////////////////////////////////////////////////// + + /*! This is used as the heading text for the retval command. */ + QCString trReturnValues() + { return "·µ»ØÖµ"; } + + /*! This is in the (quick) index as a link to the main page (index.html) + */ + QCString trMainPage() + { return "Ê×Ò³"; } + + /*! This is used in references to page that are put in the LaTeX + * documentation. It should be an abbreviation of the word page. + */ + QCString trPageAbbreviation() + { return "p."; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-991106 +////////////////////////////////////////////////////////////////////////// + + QCString trSources() + { + return "Ô´´úÂë"; + } + QCString trDefinedAtLineInSourceFile() + { + return "ÔÚÎļþ"CN_SPC"@1"CN_SPC"µÚ"CN_SPC"@0"CN_SPC"Ðж¨Òå¡£"; + } + QCString trDefinedInSourceFile() + { + return "ÔÚÎļþ"CN_SPC"@0"CN_SPC"Öж¨Òå¡£"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-991205 +////////////////////////////////////////////////////////////////////////// + + QCString trDeprecated() + { + return "Deprecated"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.0.0 +////////////////////////////////////////////////////////////////////////// + + /*! this text is put before a collaboration diagram */ + QCString trCollaborationDiagram(const char *clName) + { + return (QCString)clName+CN_SPC"ºÏ×÷ͼ£º"; + } + /*! this text is put before an include dependency graph */ + QCString trInclDepGraph(const char *fName) + { + return (QCString)fName+CN_SPC"°üº¬/ÒÀÀµ¹Øϵͼ£º"; + } + /*! header that is put before the list of constructor/destructors. */ + QCString trConstructorDocumentation() + { + return "¹¹Ôì¼°Îö¹¹º¯ÊýÎĵµ"; + } + /*! Used in the file documentation to point to the corresponding sources. */ + QCString trGotoSourceCode() + { + return "ä¯ÀÀ¸ÃÎļþµÄÔ´´úÂë¡£"; + } + /*! Used in the file sources to point to the corresponding documentation. */ + QCString trGotoDocumentation() + { + return "ä¯ÀÀ¸ÃÎļþµÄÎĵµ¡£"; + } + /*! Text for the \pre command */ + QCString trPrecondition() + { + return "Ç°ÌáÌõ¼þ"; + } + /*! Text for the \post command */ + QCString trPostcondition() + { + return "Postcondition"; + } + /*! Text for the \invariant command */ + QCString trInvariant() + { + return "Invariant"; + } + /*! Text shown before a multi-line variable/enum initialization */ + QCString trInitialValue() + { + return "³õʼ»¯ÐòÁУº"; + } + /*! Text used the source code in the file index */ + QCString trCode() + { + return "´úÂë"; + } + QCString trGraphicalHierarchy() + { + return "Àà¼Ì³Ð¹Øϵͼ"; + } + QCString trGotoGraphicalHierarchy() + { + return "ä¯ÀÀÀà¼Ì³Ð¹Øϵͼ"; + } + QCString trGotoTextualHierarchy() + { + return "ä¯ÀÀÀà¼Ì³Ð¹Øϵ±í"; + } + QCString trPageIndex() + { + return "Ò³ÃæË÷Òý"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.0 +////////////////////////////////////////////////////////////////////////// + + QCString trNote() + { + return "×¢½â"; + } + QCString trPublicTypes() + { + return "¹«ÓÐÀàÐÍ"; + } + QCString trPublicAttribs() + { + return "¹«ÓÐÊôÐÔ"; + } + QCString trStaticPublicAttribs() + { + return "¾²Ì¬¹«ÓÐÊôÐÔ"; + } + QCString trProtectedTypes() + { + return "±£»¤ÀàÐÍ"; + } + QCString trProtectedAttribs() + { + return "±£»¤ÊôÐÔ"; + } + QCString trStaticProtectedAttribs() + { + return "¾²Ì¬±£»¤ÊôÐÔ"; + } + QCString trPrivateTypes() + { + return "˽ÓÐÀàÐÍ"; + } + QCString trPrivateAttribs() + { + return "˽ÓÐÊôÐÔ"; + } + QCString trStaticPrivateAttribs() + { + return "¾²Ì¬Ë½ÓÐÊôÐÔ"; + } + + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.3 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a todo item */ + QCString trTodo() + { + return "TODO"; + } + /*! Used as the header of the todo list */ + QCString trTodoList() + { + return "TODO"CN_SPC"Áбí"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.4 +////////////////////////////////////////////////////////////////////////// + + QCString trReferencedBy() + { + return "²Î¿¼×Ô"; + } + QCString trRemarks() + { + return "ÆÀÂÛ"; + } + QCString trAttention() + { + return "×¢Òâ"; + } + QCString trInclByDepGraph() + { + return "´Ëͼչʾֱ½Ó»ò¼ä½Ó°üº¬¸ÃÎļþµÄÎļþ£º"; + } + QCString trSince() + { + return "×Ô´Ó"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.5 +////////////////////////////////////////////////////////////////////////// + + /*! title of the graph legend page */ + QCString trLegendTitle() + { + return "ͼÀý"; + } + /*! page explaining how the dot graph's should be interpreted */ + QCString trLegendDocs() + { + return + "±¾Ò³ÏòÄúչʾÈçºÎÀí½âÓÉ"CN_SPC"Doxygen"CN_SPC"Éú³ÉµÄͼÐΡ£<p>\n" + "Ç뿼ÂÇÈçÏÂʾÀý£º\n" + "\\code\n" + "/*! ÓÉÓÚ½ØÈ¡¶øʹ¸ÃÀ಻¿É¼û */\n" + "class Invisible { };\n\n" + "/*! ±»½ØÈ¡µÄÀ࣬¼Ì³Ð¹Øϵ±»Òþ²ØÆðÀ´ÁË */\n" + "class Truncated : public Invisible { };\n\n" + "/* ûÓб»"CN_SPC"doxygen"CN_SPC"µÄ×¢ÊÍÎĵµ»¯µÄÀà */\n" + "class Undocumented { };\n\n" + "/*! ±»¹«Óм̳еÄÀà */\n" + "class PublicBase : public Truncated { };\n\n" + "/*! ±»±£»¤¼Ì³ÐµÄÀà */\n" + "class ProtectedBase { };\n\n" + "/*! ±»Ë½Óм̳еÄÀà */\n" + "class PrivateBase { };\n\n" + "/*! ±»Ê¹ÓõÄÀà */\n" + "class Used { };\n\n" + "/*! ¼Ì³ÐÁËÈô¸ÉÆäËüÀàµÄÀà */\n" + "class Inherited : public PublicBase,\n" + " protected ProtectedBase,\n" + " private PrivateBase,\n" + " public Undocumented\n" + "{\n" + " private:\n" + " Used *m_usedClass;\n" + "};\n" + "\\endcode\n" + "Èç¹ûÔÚÅäÖÃÎļþÖÐÖ¸¶¨ÁË"CN_SPC"MAX_DOT_GRAPH_HEIGHT"CN_SPC"µÄֵΪ200£¬" + "ÔòDoxygen½«Éú³ÉÈçϵÄͼÐΣº" + "<p><center><img src=\"graph_legend.gif\"></center>\n" + "<p>\n" + "ÒÔÉÏͼÐÎÖеľØÐÎÓÐÈçϵĺ¬Ò壺\n" + "<ul>\n" + "<li>±»ºÚÉ«Ìî³äµÄ¾ØÐδú±íµ±Ç°µÄÀà»ò½á¹¹¡£\n" + "<li>ºÚÉ«±ß¿òµÄ¾ØÐδú±í<i>Îĵµ»¯</i>µÄÀà»ò½á¹¹¡£\n" + "<li>»ÒÉ«±ß¿òµÄ¾ØÐδú±íûÓÐ<i>Îĵµ»¯</i>µÄÀà»ò½á¹¹¡£\n" + "<li>ºìÉ«±ß¿òµÄ¾ØÐδú±í¼Ì³Ð/°üº¬¹ØϵûÓб»ÍêÕûÏÔʾ³öµÄÀà»ò½á¹¹¡£Èç¹ûÒ»·ùͼÏñµÄ³ß" + "´ç´óÓÚÖ¸¶¨³ß´ç£¬Ëü½«±»½ØÈ¡¡£" + "</ul>\n" + "¸÷¸ö¼ýÍ·ÓÐÈçϵĺ¬Ò壺\n" + "<ul>\n" + "<li>ÉîÀ¶É«µÄ¼ýÍ·ÓÃÓÚÏÔʾÁ½¸öÀàÖ®¼äµÄ¹«Óм̳йØϵ¡£\n" + "<li>ÉîÂÌÉ«µÄ¼ýÍ·ÓÃÓÚÏÔʾ±£»¤¼Ì³Ð¹Øϵ¡£\n" + "<li>ÉîºìÉ«µÄ¼ýÍ·ÓÃÓÚÏÔʾ˽Óм̳йØϵ¡£\n" + "<li>×ÏÉ«µã×´ÏßÌõµÄ¼ýÍ·ÓÃÓÚÏÔʾÁ½¸öÀàÖ®¼ä°üº¬»òÕßʹÓõĹØϵ¡£Í¨¹ý¼ýÍ·ÅԱߵıäÁ¿¿ÉÒÔ" + "·ÃÎʵ½¼ýÍ·ËùÖ¸µÄÀà»ò½á¹¹¡£\n" + "</ul>\n"; + } + /*! text for the link to the legend page */ + QCString trLegend() + { + return "ͼÀý"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.0 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a test item */ + virtual QCString trTest() + { + return "²âÊÔ"; + } + /*! Used as the header of the test list */ + virtual QCString trTestList() + { + return "²âÊÔÁбí"; + } + +}; + +#endif diff --git a/src/translator_cz.h b/src/translator_cz.h index c833a15..9b758c4 100644 --- a/src/translator_cz.h +++ b/src/translator_cz.h @@ -65,7 +65,12 @@ // 2000/09/06 (Petr Prikryl) // - Reimplementation of the method trInheritsList() which takes // into account quantity of base classes. -// +// +// 2000/09/11 (Petr Prikryl) +// - Update for "new since 1.2.1" version. The text of trDCOPMethods() +// was translated rather blindly (not knowing what exactly +// the DCOP means). +// // Notices: // -------- // The conditional compilation ensures or the neutral functionality @@ -75,7 +80,7 @@ // the conditional definition of the inline Decode() using the // method ISO88592ToWin1250() -- for conversion of strings for the // Windows version. The version which does not call the function is -// probably slightly faster (if the inline is well optimized). +// probably slightly faster. class TranslatorCzech : public Translator { @@ -1094,6 +1099,15 @@ class TranslatorCzech : public Translator return Decode("Seznam testù"); } +////////////////////////////////////////////////////////////////////////// +// new since 1.2.1 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for KDE-2 IDL methods */ + virtual QCString trDCOPMethods() + { + return Decode("Metody DCOP"); + } }; #endif // TRANSLATOR_CZ_H diff --git a/src/translator_nl.h b/src/translator_nl.h index 14db842..80a5030 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -37,19 +37,10 @@ class TranslatorDutch : public Translator { return "Documentatie van type definitie members"; } QCString trMemberEnumerationDocumentation() { return "Documentatie van enumeratie members"; } - QCString trEnumerationValueDocumentation() - { return "Documentatie van enumeratie waarden"; } QCString trMemberFunctionDocumentation() { return "Documentatie van functie members"; } QCString trMemberDataDocumentation() { return "Documentatie van data members"; } - QCString trGeneratedFrom(const char *s,bool single) - { - QCString result=(QCString)"De documentatie voor deze"+s+ - " is gegenereerd op grond van de volgende file"; - if (single) result+=":"; else result+="s:"; - return result; - } QCString trMore() { return "Meer..."; } QCString trListOfAllMembers() @@ -185,6 +176,8 @@ class TranslatorDutch : public Translator { return "Documentatie van typedefs"; } QCString trEnumerationTypeDocumentation() { return "Documentatie van enumeratie types"; } + QCString trEnumerationValueDocumentation() + { return "Documentatie van enumeratie waarden"; } QCString trFunctionDocumentation() { return "Documentatie van functies"; } QCString trVariableDocumentation() @@ -712,6 +705,30 @@ class TranslatorDutch : public Translator return "Test Lijst"; } +////////////////////////////////////////////////////////////////////////// +// new since 1.2.1 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for KDE-2 IDL methods */ + virtual QCString trDCOPMethods() + { + return "DCOP Methoden"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.2 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a section header for IDL properties */ + virtual QCString trProperties() + { + return "Properties"; + } + /*! Used as a section header for IDL property documentation */ + virtual QCString trPropertyDocumentation() + { + return "Property Documentatie"; + } }; #endif diff --git a/src/util.cpp b/src/util.cpp index e5c484e..02188c4 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -169,29 +169,66 @@ bool isId(char c) // return result; //} -// remove all annoymous scopes from string s -QCString removeAnnonymousScopes(const QCString &s) +/*! + Removes all anoymous scopes from string s + Possible examples: +\verbatim + "bla::@10::blep" => "bla::blep" + "bla::@10::@11::blep" => "bla::blep" + "@10::blep" => "blep" + " @10::blep" => "blep" + "@9::@10::blep" => "blep" + "bla::@1" => "bla" + "bla::@1::@2" => "bla" + "bla @1" => "bla" +\endverbatim + */ +QCString removeAnonymousScopes(const QCString &s) { QCString result; - int i,ni,l=s.length(); + if (s.isEmpty()) return result; + static QRegExp re("[ :]*@[0-9]+[: ]*"); + int i,l,sl=s.length(); int p=0; - while ((i=s.find('@',p))!=-1) - { - if (i>p+2) result+=s.mid(p,i-p-2); - if ((ni=s.find("::",i+1))!=-1) - { - p=ni+2; - } - else - { - p=l; + while ((i=re.match(s,p,&l))!=-1) + { + result+=s.mid(p,i-p); + int c=i; + bool b1=FALSE,b2=FALSE; + while (c<i+l && s.at(c)!='@') if (s.at(c++)==':') b1=TRUE; + c=i+l-1; + while (c>=i && s.at(c)!='@') if (s.at(c--)==':') b2=TRUE; + if (b1 && b2) + { + result+="::"; } + p=i+l; + } + result+=s.right(sl-p); + //printf("removeAnonymousScopes(`%s')=`%s'\n",s.data(),result.data()); + return result; +} + +// replace anonymous scopes with __anonymous__ +QCString replaceAnonymousScopes(const QCString &s) +{ + QCString result; + if (s.isEmpty()) return result; + static QRegExp re("@[0-9]+"); + int i,l,sl=s.length(); + int p=0; + while ((i=re.match(s,p,&l))!=-1) + { + result+=s.mid(p,i-p); + result+="__anonymous__"; + p=i+l; } - if (p!=l) result+=s.mid(p,l-p); - //printf("removeAnnonymousScopes(`%s')=`%s'\n",s.data(),result.data()); + result+=s.right(sl-p); + //printf("replaceAnonymousScopes(`%s')=`%s'\n",s.data(),result.data()); return result; } + // strip annonymous left hand side part of the scope QCString stripAnnonymousNamespaceScope(const QCString &s) { @@ -1203,13 +1240,375 @@ void stripIrrelevantConstVolatile(QCString &s) } } -//---------------------------------------------------------------------- -// Matches the arguments list srcAl with the argument list dstAl -// Returns TRUE if the argument lists are equal. Two argument list are -// considered equal if the number of arguments is equal and the types of all -// arguments are equal. Furthermore the const and volatile specifiers -// stored in the list should be equal. +// a bit of debug support for matchArguments +#define MATCH +#define NOMATCH +//#define MATCH printf("Match at line %d\n",__LINE__); +//#define NOMATCH printf("Nomatch at line %d\n",__LINE__); + +static bool matchArgument(const Argument *srcA,const Argument *dstA, + const QCString &className, + const QCString &namespaceName, + NamespaceList *usingList) +{ + QCString srcAType=trimTemplateSpecifiers(className,srcA->type); + QCString dstAType=trimTemplateSpecifiers(className,dstA->type); + if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6); + if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6); + stripIrrelevantConstVolatile(srcAType); + stripIrrelevantConstVolatile(dstAType); + + if (srcA->array!=dstA->array) // nomatch for char[] against char + { + NOMATCH + return FALSE; + } + if (srcAType!=dstAType) // check if the argument only differs on name + { + //printf("scope=`%s': `%s' <=> `%s'\n",className.data(),srcAType.data(),dstAType.data()); + + // remove a namespace scope that is only in one type + // (assuming a using statement was used) + trimNamespaceScope(srcAType,dstAType); + + //QCString srcScope; + //QCString dstScope; + + // strip redundant scope specifiers + if (!className.isEmpty()) + { + srcAType=trimScope(className,srcAType); + dstAType=trimScope(className,dstAType); + //printf("trimScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); + ClassDef *cd; + if (!namespaceName.isEmpty()) + cd=getClass(namespaceName+"::"+className); + else + cd=getClass(className); + if (cd && cd->baseClasses()->count()>0) + { + trimBaseClassScope(cd->baseClasses(),srcAType); + trimBaseClassScope(cd->baseClasses(),dstAType); + } + //printf("trimBaseClassScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); + } + if (!namespaceName.isEmpty()) + { + srcAType=trimScope(namespaceName,srcAType); + dstAType=trimScope(namespaceName,dstAType); + } + if (usingList && usingList->count()>0) + { + NamespaceListIterator nli(*usingList); + NamespaceDef *nd; + for (;(nd=nli.current());++nli) + { + srcAType=trimScope(nd->name(),srcAType); + dstAType=trimScope(nd->name(),dstAType); + } + } + + if (!srcA->name.isEmpty() && !dstA->type.isEmpty() && + (srcAType+" "+srcA->name)==dstAType) + { + MATCH + return TRUE; + } + else if (!dstA->name.isEmpty() && !srcA->type.isEmpty() && + (dstAType+" "+dstA->name)==srcAType) + { + MATCH + return TRUE; + } + //printf("srcA=%s::%s dstA=%s::%s\n",srcAType.data(),srcA->name.data(), + // dstAType.data(),dstA->name.data()); + + uint srcPos=0,dstPos=0; + bool equal=TRUE; + while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal) + { + equal=srcAType.at(srcPos)==dstAType.at(dstPos); + if (equal) srcPos++,dstPos++; + } + if (srcPos<srcAType.length() && dstPos<dstAType.length()) + { + // if nothing matches or the match ends in the middle or at the + // end of a string then there is no match + if (srcPos==0 || dstPos==0) + { + NOMATCH + return FALSE; + } + if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos))) + { + // check if a name if already found -> if no then there is no match + if (!srcA->name.isEmpty() || !dstA->name.isEmpty()) + { + NOMATCH + return FALSE; + } + while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; + while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; + if (srcPos<srcAType.length() || dstPos<dstAType.length()) + { + NOMATCH + return FALSE; + } + } + else + { + // otherwise we assume that a name starts at the current position. + while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; + while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; + // if nothing more follows for both types then we assume we have + // found a match. Note that now `signed int' and `signed' match, but + // seeing that int is not a name can only be done by looking at the + // semantics. + + if (srcPos!=srcAType.length() || dstPos!=dstAType.length()) + { + NOMATCH + return FALSE; + } + } + } + else if (dstPos<dstAType.length()) + { + if (!isspace(dstAType.at(dstPos))) // maybe the names differ + { + while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; + if (dstPos!=dstAType.length()) + { + NOMATCH + return FALSE; // more than a difference in name -> no match + } + } + else // maybe dst has a name while src has not + { + dstPos++; + while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; + if (dstPos!=dstAType.length()) + { + NOMATCH + return FALSE; // nope not a name -> no match + } + } + } + else if (srcPos<srcAType.length()) + { + if (!isspace(srcAType.at(srcPos))) // maybe the names differ + { + while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; + if (srcPos!=srcAType.length()) + { + NOMATCH + return FALSE; // more than a difference in name -> no match + } + } + else // maybe src has a name while dst has not + { + srcPos++; + while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; + if (srcPos!=srcAType.length()) + { + NOMATCH + return FALSE; // nope not a name -> no match + } + } + } + } + MATCH + return TRUE; +} +static void mergeArgument(Argument *srcA,Argument *dstA, + const QCString &className, + const QCString &namespaceName, + NamespaceList *usingList) +{ + QCString srcAType=trimTemplateSpecifiers(className,srcA->type); + QCString dstAType=trimTemplateSpecifiers(className,dstA->type); + if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6); + if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6); + stripIrrelevantConstVolatile(srcAType); + stripIrrelevantConstVolatile(dstAType); + + if (srcAType!=dstAType) // check if the argument only differs on name + { + //printf("scope=`%s': `%s' <=> `%s'\n",className.data(),srcAType.data(),dstAType.data()); + + // remove a namespace scope that is only in one type + // (assuming a using statement was used) + trimNamespaceScope(srcAType,dstAType); + + //QCString srcScope; + //QCString dstScope; + + // strip redundant scope specifiers + if (!className.isEmpty()) + { + srcAType=trimScope(className,srcAType); + dstAType=trimScope(className,dstAType); + //printf("trimScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); + ClassDef *cd; + if (!namespaceName.isEmpty()) + cd=getClass(namespaceName+"::"+className); + else + cd=getClass(className); + if (cd && cd->baseClasses()->count()>0) + { + trimBaseClassScope(cd->baseClasses(),srcAType); + trimBaseClassScope(cd->baseClasses(),dstAType); + } + //printf("trimBaseClassScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); + } + if (!namespaceName.isEmpty()) + { + srcAType=trimScope(namespaceName,srcAType); + dstAType=trimScope(namespaceName,dstAType); + } + if (usingList && usingList->count()>0) + { + NamespaceListIterator nli(*usingList); + NamespaceDef *nd; + for (;(nd=nli.current());++nli) + { + srcAType=trimScope(nd->name(),srcAType); + dstAType=trimScope(nd->name(),dstAType); + } + } + + if (!srcA->name.isEmpty() && !dstA->type.isEmpty() && + (srcAType+" "+srcA->name)==dstAType) + { + srcA->type=srcAType+" "+srcA->name; + srcA->name.resize(0); + return; + } + else if (!dstA->name.isEmpty() && !srcA->type.isEmpty() && + (dstAType+" "+dstA->name)==srcAType) + { + dstA->type=dstAType+" "+dstA->name; + dstA->name.resize(0); + return; + } + //printf("srcA=%s::%s dstA=%s::%s\n",srcAType.data(),srcA->name.data(), + // dstAType.data(),dstA->name.data()); + + uint srcPos=0,dstPos=0; + bool equal=TRUE; + while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal) + { + equal=srcAType.at(srcPos)==dstAType.at(dstPos); + if (equal) srcPos++,dstPos++; + } + if (srcPos<srcAType.length() && dstPos<dstAType.length()) + { + // if nothing matches or the match ends in the middle or at the + // end of a string then there is no match + int srcStart=srcPos; + int dstStart=dstPos; + if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos))) + { + // find the start of the name + while (srcStart>=0 && isId(srcAType.at(srcStart))) srcStart--; + while (dstStart>=0 && isId(dstAType.at(dstStart))) dstStart--; + if (srcStart>0) // move the name from the type to the name field + { + srcA->name=srcAType.right(srcAType.length()-srcStart-1); + srcA->type=srcAType.left(srcStart+1).stripWhiteSpace(); + } + if (dstStart>0) // move the name from the type to the name field + { + dstA->name=dstAType.right(dstAType.length()-dstStart-1); + dstA->type=dstAType.left(dstStart+1).stripWhiteSpace(); + } + } + else + { + dstA->name=dstAType.right(dstAType.length()-dstStart); + dstA->type=dstAType.left(dstStart).stripWhiteSpace(); + srcA->name=srcAType.right(dstAType.length()-srcStart); + srcA->type=srcAType.left(srcStart).stripWhiteSpace(); + } + } + else if (dstPos<dstAType.length()) + { + if (!isspace(dstAType.at(dstPos))) // maybe the names differ + { + int startPos=dstPos; + while (startPos>=0 && isId(dstAType.at(startPos))) startPos--; + if (startPos>0) + { + dstA->name=dstAType.right(dstAType.length()-startPos-1); + dstA->type=dstAType.left(startPos+1).stripWhiteSpace(); + } + } + else // maybe dst has a name while src has not + { + dstPos++; + int startPos=dstPos; + dstA->name=dstAType.right(dstAType.length()-startPos); + dstA->type=dstAType.left(startPos).stripWhiteSpace(); + } + } + else if (srcPos<srcAType.length()) + { + if (!isspace(srcAType.at(srcPos))) // maybe the names differ + { + int startPos=srcPos; + while (startPos>=0 && isId(srcAType.at(startPos))) startPos--; + if (startPos>0) + { + srcA->name=srcAType.right(srcAType.length()-startPos-1); + srcA->type=srcAType.left(startPos+1).stripWhiteSpace(); + } + } + else // maybe src has a name while dst has not + { + srcPos++; + int startPos=srcPos; + srcA->name=srcAType.right(srcAType.length()-startPos); + srcA->type=srcAType.left(startPos).stripWhiteSpace(); + } + } + return; + } + //printf("match exactly\n"); + if (srcA->name.isEmpty() && dstA->name.isEmpty()) + // arguments match exactly but no name -> + // see if we can find the name + { + int i=srcAType.length()-1; + while (i>=0 && isId(srcAType.at(i))) i--; + if (i>0 && i<(int)srcAType.length()-1 && srcAType.at(i)!=':') + // there is (probably) a name + { + srcA->name=srcAType.right(srcAType.length()-i-1); + srcA->type=srcAType.left(i+1).stripWhiteSpace(); + dstA->name=dstAType.right(dstAType.length()-i-1); + dstA->type=dstAType.left(i+1).stripWhiteSpace(); + } + } + else if (!dstA->name.isEmpty()) + { + srcA->name = dstA->name.copy(); + } + else if (!srcA->name.isEmpty()) + { + dstA->name = srcA->name.copy(); + } + return; +} + + +/*! + * Matches the arguments list srcAl with the argument list dstAl + * Returns TRUE if the argument lists are equal. Two argument list are + * considered equal if the number of arguments is equal and the types of all + * arguments are equal. Furthermore the const and volatile specifiers + * stored in the list should be equal. + */ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, const char *cl,const char *ns,bool checkCV, NamespaceList *usingList) @@ -1231,7 +1630,17 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, if (srcAl==0 || dstAl==0) { - return srcAl==dstAl; // at least one of the members is not a function + bool match = srcAl==dstAl; // at least one of the members is not a function + if (match) + { + MATCH + return TRUE; + } + else + { + NOMATCH + return FALSE; + } } // handle special case with void argument @@ -1241,6 +1650,7 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, Argument *a=new Argument; a->type = "void"; srcAl->append(a); + MATCH return TRUE; } if ( dstAl->count()==0 && srcAl->count()==1 && @@ -1249,11 +1659,13 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, Argument *a=new Argument; a->type = "void"; dstAl->append(a); + MATCH return TRUE; } if (srcAl->count() != dstAl->count()) { + NOMATCH return FALSE; // different number of arguments -> no match } @@ -1261,10 +1673,12 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, { if (srcAl->constSpecifier != dstAl->constSpecifier) { + NOMATCH return FALSE; // one member is const, the other not -> no match } if (srcAl->volatileSpecifier != dstAl->volatileSpecifier) { + NOMATCH return FALSE; // one member is volatile, the other not -> no match } } @@ -1274,200 +1688,22 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, ArgumentListIterator srcAli(*srcAl),dstAli(*dstAl); Argument *srcA,*dstA; for (;(srcA=srcAli.current(),dstA=dstAli.current());++srcAli,++dstAli) - { - QCString srcAType=trimTemplateSpecifiers(className,srcA->type); - QCString dstAType=trimTemplateSpecifiers(className,dstA->type); - if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6); - if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6); - stripIrrelevantConstVolatile(srcAType); - stripIrrelevantConstVolatile(dstAType); - - if (srcA->array!=dstA->array) return FALSE; - if (srcAType!=dstAType) // check if the argument only differs on name + { + if (!matchArgument(srcA,dstA,className,namespaceName,usingList)) { - //printf("scope=`%s': `%s' <=> `%s'\n",className.data(),srcAType.data(),dstAType.data()); - - // remove a namespace scope that is only in one type - // (assuming a using statement was used) - trimNamespaceScope(srcAType,dstAType); - - //QCString srcScope; - //QCString dstScope; - - // strip redundant scope specifiers - if (!className.isEmpty()) - { - srcAType=trimScope(className,srcAType); - dstAType=trimScope(className,dstAType); - //printf("trimScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); - ClassDef *cd; - if (!namespaceName.isEmpty()) - cd=getClass(namespaceName+"::"+className); - else - cd=getClass(className); - if (cd && cd->baseClasses()->count()>0) - { - trimBaseClassScope(cd->baseClasses(),srcAType); - trimBaseClassScope(cd->baseClasses(),dstAType); - } - //printf("trimBaseClassScope: `%s' <=> `%s'\n",srcAType.data(),dstAType.data()); - } - if (!namespaceName.isEmpty()) - { - srcAType=trimScope(namespaceName,srcAType); - dstAType=trimScope(namespaceName,dstAType); - } - if (usingList && usingList->count()>0) - { - NamespaceListIterator nli(*usingList); - NamespaceDef *nd; - for (;(nd=nli.current());++nli) - { - srcAType=trimScope(nd->name(),srcAType); - dstAType=trimScope(nd->name(),dstAType); - } - } - //printf("srcAType=%s dstAType=%s\n",srcAType.data(),dstAType.data()); - - uint srcPos=0,dstPos=0; - bool equal=TRUE; - while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal) - { - equal=srcAType.at(srcPos)==dstAType.at(dstPos); - if (equal) srcPos++,dstPos++; - } - if (srcPos<srcAType.length() && dstPos<dstAType.length()) - { - // if nothing matches or the match ends in the middle or at the - // end of a string then there is no match - //if (srcPos==0 || isalnum(srcAType.at(srcPos-1)) || - // dstPos==0 || isalnum(dstAType.at(dstPos-1))) { printf("No match1\n"); return FALSE; } - int srcStart=srcPos; - int dstStart=dstPos; - if (srcPos==0 || dstPos==0) return FALSE; - if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos))) - { - // check if a name if already found -> if no then there is no match - if (!srcA->name.isEmpty() || !dstA->name.isEmpty()) return FALSE; - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - if (srcPos<srcAType.length() || dstPos<dstAType.length()) return FALSE; - // find the start of the name - while (srcStart>=0 && isId(srcAType.at(srcStart))) srcStart--; - while (dstStart>=0 && isId(dstAType.at(dstStart))) dstStart--; - if (srcStart>0) // move the name from the type to the name field - { - srcA->name=srcAType.right(srcAType.length()-srcStart-1); - srcA->type=srcAType.left(srcStart+1).stripWhiteSpace(); - } - if (dstStart>0) // move the name from the type to the name field - { - dstA->name=dstAType.right(dstAType.length()-dstStart-1); - dstA->type=dstAType.left(dstStart+1).stripWhiteSpace(); - } - } - else - { - // otherwise we assume that a name starts at the current position. - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - // if nothing more follows for both types then we assume we have - // found a match. Note that now `signed int' and `signed' match, but - // seeing that int is not a name can only be done by looking at the - // semantics. - - if (srcPos!=srcAType.length() || dstPos!=dstAType.length()) { return FALSE; } - dstA->name=dstAType.right(dstAType.length()-dstStart); - dstA->type=dstAType.left(dstStart).stripWhiteSpace(); - srcA->name=srcAType.right(dstAType.length()-srcStart); - srcA->type=srcAType.left(srcStart).stripWhiteSpace(); - } - } - else if (dstPos<dstAType.length()) - { - if (!isspace(dstAType.at(dstPos))) // maybe the names differ - { - int startPos=dstPos; - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - if (dstPos!=dstAType.length()) return FALSE; // more than a difference in name -> no match - while (startPos>=0 && isId(dstAType.at(startPos))) startPos--; - if (startPos>0) - { - dstA->name=dstAType.right(dstAType.length()-startPos-1); - dstA->type=dstAType.left(startPos+1).stripWhiteSpace(); - } - } - else // maybe dst has a name while src has not - { - dstPos++; - int startPos=dstPos; - while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++; - if (dstPos!=dstAType.length()) return FALSE; // nope not a name -> no match - else // its a name (most probably) so move it - { - dstA->name=dstAType.right(dstAType.length()-startPos); - dstA->type=dstAType.left(startPos).stripWhiteSpace(); - } - } - } - else if (srcPos<srcAType.length()) - { - if (!isspace(srcAType.at(srcPos))) // maybe the names differ - { - int startPos=srcPos; - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - if (srcPos!=srcAType.length()) return FALSE; // more than a difference in name -> no match - while (startPos>=0 && isId(srcAType.at(startPos))) startPos--; - if (startPos>0) - { - srcA->name=srcAType.right(srcAType.length()-startPos-1); - srcA->type=srcAType.left(startPos+1).stripWhiteSpace(); - } - } - else // maybe src has a name while dst has not - { - srcPos++; - int startPos=srcPos; - while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++; - if (srcPos!=srcAType.length()) return FALSE; // nope not a name -> no match - else // its a name (most probably) so move it - { - srcA->name=srcAType.right(srcAType.length()-startPos); - srcA->type=srcAType.left(startPos).stripWhiteSpace(); - } - } - } - else // without scopes the names match exactly - { - } - return TRUE; - } - //printf("match exactly\n"); - if (srcA->name.isEmpty() && dstA->name.isEmpty()) - // arguments match exactly but no name -> - // see if we can find the name - { - int i=srcAType.length()-1; - while (i>=0 && isId(srcAType.at(i))) i--; - if (i>0 && i<(int)srcAType.length()-1 && srcAType.at(i)!=':') - // there is (probably) a name - { - srcA->name=srcAType.right(srcAType.length()-i-1); - srcA->type=srcAType.left(i+1).stripWhiteSpace(); - dstA->name=dstAType.right(dstAType.length()-i-1); - dstA->type=dstAType.left(i+1).stripWhiteSpace(); - } - } - else if (!dstA->name.isEmpty()) - { - srcA->name=dstA->name.copy(); - } - else if (!srcA->name.isEmpty()) - { - dstA->name=srcA->name.copy(); + NOMATCH + return FALSE; } } - //printf("Match found!\n"); + // merge/correct argument type/names + for (srcAli.toFirst(),dstAli.toFirst(); + (srcA=srcAli.current(),dstA=dstAli.current()); + ++srcAli,++dstAli + ) + { + mergeArgument(srcA,dstA,className,namespaceName,usingList); + } + MATCH return TRUE; // all arguments match } @@ -1572,7 +1808,9 @@ bool getDefs(const QCString &scName,const QCString &memberName, const char *args, MemberDef *&md, ClassDef *&cd, FileDef *&fd, NamespaceDef *&nd, GroupDef *&gd, - bool forceEmptyScope) + bool forceEmptyScope, + FileDef *currentFile + ) { fd=0, md=0, cd=0, nd=0, gd=0; if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */ @@ -1784,6 +2022,8 @@ bool getDefs(const QCString &scName,const QCString &memberName, } else // no scope => global function { + QList<MemberDef> members; + //printf("Function with global scope `%s' args=`%s'\n",namespaceName.data(),args); MemberListIterator mli(*mn); for (mli.toFirst();(md=mli.current());++mli) @@ -1794,12 +2034,10 @@ bool getDefs(const QCString &scName,const QCString &memberName, gd=md->getGroupDef(); //printf("md->name()=`%s' md->args=`%s' fd=%p gd=%p\n", // md->name().data(),args,fd,gd); - bool inGroup=FALSE; if ((fd && fd->isLinkable()) || - (inGroup=(gd && gd->isLinkable())) + (gd && gd->isLinkable()) ) { - if (inGroup) fd=0; //printf("fd=%p gd=%p inGroup=`%d' args=`%s'\n",fd,gd,inGroup,args); bool match=TRUE; ArgumentList *argList=0; @@ -1813,7 +2051,7 @@ bool getDefs(const QCString &scName,const QCString &memberName, if (match) { //printf("Found match!\n"); - return TRUE; + members.append(md); } } } @@ -1831,18 +2069,44 @@ bool getDefs(const QCString &scName,const QCString &memberName, //printf("member is linkable md->name()=`%s'\n",md->name().data()); fd=md->getFileDef(); gd=md->getGroupDef(); - bool inGroup=FALSE; if ((fd && fd->isLinkable()) || - (inGroup=(gd && gd->isLinkable())) + (gd && gd->isLinkable()) ) { - if (inGroup) fd=0; - return TRUE; + members.append(md); } } md=mn->prev(); } } + if (members.count()==1 || currentFile!=0) + { + md=members.first(); + } + else if (members.count()>1) + { + // use some C scoping rules to determine the correct link + // 1. member in current file + // 2. non-static member in different file + MemberDef *bmd = 0; + for (md=members.first(); md; md=members.next()) + { + if (md->getFileDef() == currentFile) + { + bmd = 0; + break; + } + if (!(md->isStatic())) bmd = md; + } + if (bmd) md=bmd; + } + if (md) // found a matching global member + { + fd=md->getFileDef(); + gd=md->getGroupDef(); + if (gd && gd->isLinkable()) fd=0; else gd=0; + return TRUE; + } } if (scopeOffset==0) { @@ -85,11 +85,16 @@ extern void linkifyText(const TextGeneratorIntf &ol,const char *clName,const cha extern void setAnchors(char id,MemberList *ml,int groupId=-1); extern QCString fileToString(const char *name); extern QCString dateToString(bool); -extern bool getDefs(const QCString &scopeName,const QCString &memberName, - const char *, MemberDef *&md, - ClassDef *&cd,FileDef *&fd, - NamespaceDef *&nd,GroupDef *&gd, - bool forceEmptyScope=FALSE +extern bool getDefs(const QCString &scopeName, + const QCString &memberName, + const char *, + MemberDef *&md, + ClassDef *&cd, + FileDef *&fd, + NamespaceDef *&nd, + GroupDef *&gd, + bool forceEmptyScope=FALSE, + FileDef *currentFile=0 ); extern bool generateRef(OutputList &ol,const char *, const char *,bool inSeeBlock,const char * =0); @@ -133,7 +138,8 @@ bool leftScopeMatch(const QCString &scope, const QCString &name); void writePageRef(OutputList &ol,const char *cn,const char *mn); QCString substituteKeywords(const QCString &s,const char *title); int getPrefixIndex(const QCString &name); -QCString removeAnnonymousScopes(const QCString &s); +QCString removeAnonymousScopes(const QCString &s); +QCString replaceAnonymousScopes(const QCString &s); void initClassHierarchy(ClassList *cl); bool hasVisibleRoot(BaseClassList *bcl); int minClassDistance(ClassDef *cd,ClassDef *bcd,int level=0); diff --git a/src/xml_dtd.h b/src/xml_dtd.h index f43db77..010a465 100644 --- a/src/xml_dtd.h +++ b/src/xml_dtd.h @@ -1,4 +1,4 @@ -"<?xml encoding=\"ISO-8859-1\"?>\n" +"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" "<!-- DTD describing the grammar used in doxygen's XML output -->\n" "\n" "<!-- standard character entities -->\n" @@ -50,6 +50,8 @@ " |friend\n" " |related\n" " |define|prototype|typedef|enum|func|var\n" +" |dcop-func\n" +" |property\n" " ) #REQUIRED\n" " '\n" ">\n" |